1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
25 #include <ode/odeconfig.h>
27 #include <ode/odemath.h>
28 #include <ode/rotation.h>
29 #include <ode/timer.h>
30 #include <ode/error.h>
31 #include <ode/matrix.h>
35 //****************************************************************************
41 // memory allocation system
42 #ifdef dUSE_MALLOC_FOR_ALLOCA
43 unsigned int dMemoryFlag
;
44 #define REPORT_OUT_OF_MEMORY fprintf(stderr, "Insufficient memory to complete rigid body simulation. Results will not be accurate.\n")
46 #define ALLOCA(t,v,s) t* v=(t*)malloc(s)
47 #define UNALLOCA(t) free(t)
50 #define ALLOCA(t,v,s) t* v=(t*)dALLOCA16(s)
51 #define UNALLOCA(t) /* nothing */
55 //****************************************************************************
56 // debugging - comparison of various vectors and matrices produced by the
57 // slow and fast versions of the stepper.
59 //#define COMPARE_METHODS
61 #ifdef COMPARE_METHODS
63 dMatrixComparison comparator
;
66 // undef to use the fast decomposition
67 #define DIRECT_CHOLESKY
70 //****************************************************************************
71 // special matrix multipliers
73 // this assumes the 4th and 8th rows of B and C are zero.
75 static void Multiply2_p8r (dReal
*A
, dReal
*B
, dReal
*C
,
76 int p
, int r
, int Askip
)
80 dIASSERT (p
>0 && r
>0 && A
&& B
&& C
);
100 // this assumes the 4th and 8th rows of B and C are zero.
102 static void MultiplyAdd2_p8r (dReal
*A
, dReal
*B
, dReal
*C
,
103 int p
, int r
, int Askip
)
107 dIASSERT (p
>0 && r
>0 && A
&& B
&& C
);
127 // this assumes the 4th and 8th rows of B are zero.
129 static void Multiply0_p81 (dReal
*A
, dReal
*B
, dReal
*C
, int p
)
132 dIASSERT (p
>0 && A
&& B
&& C
);
147 // this assumes the 4th and 8th rows of B are zero.
149 static void MultiplyAdd0_p81 (dReal
*A
, dReal
*B
, dReal
*C
, int p
)
152 dIASSERT (p
>0 && A
&& B
&& C
);
167 // this assumes the 4th and 8th rows of B are zero.
169 static void MultiplyAdd1_8q1 (dReal
*A
, dReal
*B
, dReal
*C
, int q
)
173 dIASSERT (q
>0 && A
&& B
&& C
);
175 for (k
=0; k
<q
; k
++) sum
+= B
[k
*8] * C
[k
];
178 for (k
=0; k
<q
; k
++) sum
+= B
[1+k
*8] * C
[k
];
181 for (k
=0; k
<q
; k
++) sum
+= B
[2+k
*8] * C
[k
];
184 for (k
=0; k
<q
; k
++) sum
+= B
[4+k
*8] * C
[k
];
187 for (k
=0; k
<q
; k
++) sum
+= B
[5+k
*8] * C
[k
];
190 for (k
=0; k
<q
; k
++) sum
+= B
[6+k
*8] * C
[k
];
195 // this assumes the 4th and 8th rows of B are zero.
197 static void Multiply1_8q1 (dReal
*A
, dReal
*B
, dReal
*C
, int q
)
201 dIASSERT (q
>0 && A
&& B
&& C
);
203 for (k
=0; k
<q
; k
++) sum
+= B
[k
*8] * C
[k
];
206 for (k
=0; k
<q
; k
++) sum
+= B
[1+k
*8] * C
[k
];
209 for (k
=0; k
<q
; k
++) sum
+= B
[2+k
*8] * C
[k
];
212 for (k
=0; k
<q
; k
++) sum
+= B
[4+k
*8] * C
[k
];
215 for (k
=0; k
<q
; k
++) sum
+= B
[5+k
*8] * C
[k
];
218 for (k
=0; k
<q
; k
++) sum
+= B
[6+k
*8] * C
[k
];
222 //****************************************************************************
223 // the slow, but sure way
224 // note that this does not do any joint feedback!
226 // given lists of bodies and joints that form an island, perform a first
229 // `body' is the body array, `nb' is the size of the array.
230 // `_joint' is the body array, `nj' is the size of the array.
232 void dInternalStepIsland_x1 (dxWorld
*world
, dxBody
* const *body
, int nb
,
233 dxJoint
* const *_joint
, int nj
, dReal stepsize
)
239 dTimerStart("preprocessing");
242 // number all bodies in the body list - set their tag values
243 for (i
=0; i
<nb
; i
++) body
[i
]->tag
= i
;
245 // make a local copy of the joint array, because we might want to modify it.
246 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
247 // but not the joint array, because the caller might need it unchanged).
248 ALLOCA(dxJoint
*,joint
,nj
*sizeof(dxJoint
*));
249 #ifdef dUSE_MALLOC_FOR_ALLOCA
251 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
255 memcpy (joint
,_joint
,nj
* sizeof(dxJoint
*));
257 // for all bodies, compute the inertia tensor and its inverse in the global
258 // frame, and compute the rotational force and add it to the torque
260 // @@@ check computation of rotational force.
261 ALLOCA(dReal
,I
,3*nb
*4*sizeof(dReal
));
262 #ifdef dUSE_MALLOC_FOR_ALLOCA
265 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
269 ALLOCA(dReal
,invI
,3*nb
*4*sizeof(dReal
));
270 #ifdef dUSE_MALLOC_FOR_ALLOCA
274 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
279 //dSetZero (I,3*nb*4);
280 //dSetZero (invI,3*nb*4);
281 for (i
=0; i
<nb
; i
++) {
283 // compute inertia tensor in global frame
284 dMULTIPLY2_333 (tmp
,body
[i
]->mass
.I
,body
[i
]->posr
.R
);
285 dMULTIPLY0_333 (I
+i
*12,body
[i
]->posr
.R
,tmp
);
286 // compute inverse inertia tensor in global frame
287 dMULTIPLY2_333 (tmp
,body
[i
]->invI
,body
[i
]->posr
.R
);
288 dMULTIPLY0_333 (invI
+i
*12,body
[i
]->posr
.R
,tmp
);
289 // compute rotational force
290 dMULTIPLY0_331 (tmp
,I
+i
*12,body
[i
]->avel
);
291 dCROSS (body
[i
]->tacc
,-=,body
[i
]->avel
,tmp
);
294 // add the gravity force to all bodies
295 for (i
=0; i
<nb
; i
++) {
296 if ((body
[i
]->flags
& dxBodyNoGravity
)==0) {
297 body
[i
]->facc
[0] += body
[i
]->mass
.mass
* world
->gravity
[0];
298 body
[i
]->facc
[1] += body
[i
]->mass
.mass
* world
->gravity
[1];
299 body
[i
]->facc
[2] += body
[i
]->mass
.mass
* world
->gravity
[2];
303 // get m = total constraint dimension, nub = number of unbounded variables.
304 // create constraint offset array and number-of-rows array for all joints.
305 // the constraints are re-ordered as follows: the purely unbounded
306 // constraints, the mixed unbounded + LCP constraints, and last the purely
309 // joints with m=0 are inactive and are removed from the joints array
310 // entirely, so that the code that follows does not consider them.
312 ALLOCA(dxJoint::Info1
,info
,nj
*sizeof(dxJoint::Info1
));
313 #ifdef dUSE_MALLOC_FOR_ALLOCA
318 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
323 ALLOCA(int,ofs
,nj
*sizeof(int));
324 #ifdef dUSE_MALLOC_FOR_ALLOCA
330 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
335 for (i
=0, j
=0; j
<nj
; j
++) { // i=dest, j=src
336 joint
[j
]->vtable
->getInfo1 (joint
[j
],info
+i
);
337 dIASSERT (info
[i
].m
>= 0 && info
[i
].m
<= 6 &&
338 info
[i
].nub
>= 0 && info
[i
].nub
<= info
[i
].m
);
346 // the purely unbounded constraints
347 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
== info
[i
].m
) {
352 // the mixed unbounded + LCP constraints
353 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
> 0 && info
[i
].nub
< info
[i
].m
) {
357 // the purely LCP constraints
358 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
== 0) {
363 // create (6*nb,6*nb) inverse mass matrix `invM', and fill it with mass
366 dTimerNow ("create mass matrix");
368 int nskip
= dPAD (n6
);
369 ALLOCA(dReal
, invM
, n6
*nskip
*sizeof(dReal
));
370 #ifdef dUSE_MALLOC_FOR_ALLOCA
377 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
382 dSetZero (invM
,n6
*nskip
);
383 for (i
=0; i
<nb
; i
++) {
384 dReal
*MM
= invM
+(i
*6)*nskip
+(i
*6);
385 MM
[0] = body
[i
]->invMass
;
386 MM
[nskip
+1] = body
[i
]->invMass
;
387 MM
[2*nskip
+2] = body
[i
]->invMass
;
389 for (j
=0; j
<3; j
++) for (k
=0; k
<3; k
++) {
390 MM
[j
*nskip
+k
] = invI
[i
*12+j
*4+k
];
394 // assemble some body vectors: fe = external forces, v = velocities
395 ALLOCA(dReal
,fe
,n6
*sizeof(dReal
));
396 #ifdef dUSE_MALLOC_FOR_ALLOCA
404 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
409 ALLOCA(dReal
,v
,n6
*sizeof(dReal
));
410 #ifdef dUSE_MALLOC_FOR_ALLOCA
419 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
426 for (i
=0; i
<nb
; i
++) {
427 for (j
=0; j
<3; j
++) fe
[i
*6+j
] = body
[i
]->facc
[j
];
428 for (j
=0; j
<3; j
++) fe
[i
*6+3+j
] = body
[i
]->tacc
[j
];
429 for (j
=0; j
<3; j
++) v
[i
*6+j
] = body
[i
]->lvel
[j
];
430 for (j
=0; j
<3; j
++) v
[i
*6+3+j
] = body
[i
]->avel
[j
];
433 // this will be set to the velocity update
434 ALLOCA(dReal
,vnew
,n6
*sizeof(dReal
));
435 #ifdef dUSE_MALLOC_FOR_ALLOCA
445 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
451 // if there are constraints, compute cforce
453 // create a constraint equation right hand side vector `c', a constraint
454 // force mixing vector `cfm', and LCP low and high bound vectors, and an
456 ALLOCA(dReal
,c
,m
*sizeof(dReal
));
457 #ifdef dUSE_MALLOC_FOR_ALLOCA
468 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
472 ALLOCA(dReal
,cfm
,m
*sizeof(dReal
));
473 #ifdef dUSE_MALLOC_FOR_ALLOCA
485 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
489 ALLOCA(dReal
,lo
,m
*sizeof(dReal
));
490 #ifdef dUSE_MALLOC_FOR_ALLOCA
503 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
507 ALLOCA(dReal
,hi
,m
*sizeof(dReal
));
508 #ifdef dUSE_MALLOC_FOR_ALLOCA
522 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
526 ALLOCA(int,findex
,m
*sizeof(int));
527 #ifdef dUSE_MALLOC_FOR_ALLOCA
528 if (findex
== NULL
) {
542 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
547 dSetValue (cfm
,m
,world
->global_cfm
);
548 dSetValue (lo
,m
,-dInfinity
);
549 dSetValue (hi
,m
, dInfinity
);
550 for (i
=0; i
<m
; i
++) findex
[i
] = -1;
552 // create (m,6*nb) jacobian mass matrix `J', and fill it with constraint
553 // data. also fill the c vector.
555 dTimerNow ("create J");
557 ALLOCA(dReal
,J
,m
*nskip
*sizeof(dReal
));
558 #ifdef dUSE_MALLOC_FOR_ALLOCA
574 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
578 dSetZero (J
,m
*nskip
);
579 dxJoint::Info2 Jinfo
;
580 Jinfo
.rowskip
= nskip
;
581 Jinfo
.fps
= dRecip(stepsize
);
582 Jinfo
.erp
= world
->global_erp
;
583 for (i
=0; i
<nj
; i
++) {
584 Jinfo
.J1l
= J
+ nskip
*ofs
[i
] + 6*joint
[i
]->node
[0].body
->tag
;
585 Jinfo
.J1a
= Jinfo
.J1l
+ 3;
586 if (joint
[i
]->node
[1].body
) {
587 Jinfo
.J2l
= J
+ nskip
*ofs
[i
] + 6*joint
[i
]->node
[1].body
->tag
;
588 Jinfo
.J2a
= Jinfo
.J2l
+ 3;
594 Jinfo
.c
= c
+ ofs
[i
];
595 Jinfo
.cfm
= cfm
+ ofs
[i
];
596 Jinfo
.lo
= lo
+ ofs
[i
];
597 Jinfo
.hi
= hi
+ ofs
[i
];
598 Jinfo
.findex
= findex
+ ofs
[i
];
599 joint
[i
]->vtable
->getInfo2 (joint
[i
],&Jinfo
);
600 // adjust returned findex values for global index numbering
601 for (j
=0; j
<info
[i
].m
; j
++) {
602 if (findex
[ofs
[i
] + j
] >= 0) findex
[ofs
[i
] + j
] += ofs
[i
];
606 // compute A = J*invM*J'
608 dTimerNow ("compute A");
610 ALLOCA(dReal
,JinvM
,m
*nskip
*sizeof(dReal
));
611 #ifdef dUSE_MALLOC_FOR_ALLOCA
628 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
632 //dSetZero (JinvM,m*nskip);
633 dMultiply0 (JinvM
,J
,invM
,m
,n6
,n6
);
635 ALLOCA(dReal
,A
,m
*mskip
*sizeof(dReal
));
636 #ifdef dUSE_MALLOC_FOR_ALLOCA
654 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
658 //dSetZero (A,m*mskip);
659 dMultiply2 (A
,JinvM
,J
,m
,n6
,m
);
661 // add cfm to the diagonal of A
662 for (i
=0; i
<m
; i
++) A
[i
*mskip
+i
] += cfm
[i
] * Jinfo
.fps
;
664 # ifdef COMPARE_METHODS
665 comparator
.nextMatrix (A
,m
,m
,1,"A");
668 // compute `rhs', the right hand side of the equation J*a=c
670 dTimerNow ("compute rhs");
672 ALLOCA(dReal
,tmp1
,n6
*sizeof(dReal
));
673 #ifdef dUSE_MALLOC_FOR_ALLOCA
692 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
696 //dSetZero (tmp1,n6);
697 dMultiply0 (tmp1
,invM
,fe
,n6
,n6
,1);
698 for (i
=0; i
<n6
; i
++) tmp1
[i
] += v
[i
]/stepsize
;
699 ALLOCA(dReal
,rhs
,m
*sizeof(dReal
));
700 #ifdef dUSE_MALLOC_FOR_ALLOCA
720 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
725 dMultiply0 (rhs
,J
,tmp1
,m
,n6
,1);
726 for (i
=0; i
<m
; i
++) rhs
[i
] = c
[i
]/stepsize
- rhs
[i
];
728 # ifdef COMPARE_METHODS
729 comparator
.nextMatrix (c
,m
,1,0,"c");
730 comparator
.nextMatrix (rhs
,m
,1,0,"rhs");
737 #ifndef DIRECT_CHOLESKY
738 // solve the LCP problem and get lambda.
739 // this will destroy A but that's okay
741 dTimerNow ("solving LCP problem");
743 ALLOCA(dReal
,lambda
,m
*sizeof(dReal
));
744 #ifdef dUSE_MALLOC_FOR_ALLOCA
745 if (lambda
== NULL
) {
765 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
769 ALLOCA(dReal
,residual
,m
*sizeof(dReal
));
770 #ifdef dUSE_MALLOC_FOR_ALLOCA
771 if (residual
== NULL
) {
792 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
796 dSolveLCP (m
,A
,lambda
,rhs
,residual
,nub
,lo
,hi
,findex
);
800 #ifdef dUSE_MALLOC_FOR_ALLOCA
801 if (dMemoryFlag
== d_MEMORY_OUT_OF_MEMORY
)
808 // OLD WAY - direct factor and solve
810 // factorize A (L*L'=A)
812 dTimerNow ("factorize A");
814 ALLOCA(dReal
,L
,m
*mskip
*sizeof(dReal
));
815 #ifdef dUSE_MALLOC_FOR_ALLOCA
836 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
840 memcpy (L
,A
,m
*mskip
*sizeof(dReal
));
841 if (dFactorCholesky (L
,m
)==0) dDebug (0,"A is not positive definite");
845 dTimerNow ("compute lambda");
847 ALLOCA(dReal
,lambda
,m
*sizeof(dReal
));
848 #ifdef dUSE_MALLOC_FOR_ALLOCA
849 if (lambda
== NULL
) {
870 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
874 memcpy (lambda
,rhs
,m
* sizeof(dReal
));
875 dSolveCholesky (L
,lambda
,m
);
878 # ifdef COMPARE_METHODS
879 comparator
.nextMatrix (lambda
,m
,1,0,"lambda");
882 // compute the velocity update `vnew'
884 dTimerNow ("compute velocity update");
886 dMultiply1 (tmp1
,J
,lambda
,n6
,m
,1);
887 for (i
=0; i
<n6
; i
++) tmp1
[i
] += fe
[i
];
888 dMultiply0 (vnew
,invM
,tmp1
,n6
,n6
,1);
889 for (i
=0; i
<n6
; i
++) vnew
[i
] = v
[i
] + stepsize
*vnew
[i
];
892 // see if the constraint has worked: compute J*vnew and make sure it equals
893 // `c' (to within a certain tolerance).
895 dTimerNow ("verify constraint equation");
897 dMultiply0 (tmp1
,J
,vnew
,m
,n6
,1);
899 for (i
=0; i
<m
; i
++) {
900 err
+= dFabs(tmp1
[i
]-c
[i
]);
902 printf ("total constraint error=%.6e\n",err
);
920 dMultiply0 (vnew
,invM
,fe
,n6
,n6
,1);
921 for (i
=0; i
<n6
; i
++) vnew
[i
] = v
[i
] + stepsize
*vnew
[i
];
924 #ifdef COMPARE_METHODS
925 comparator
.nextMatrix (vnew
,n6
,1,0,"vnew");
928 // apply the velocity update to the bodies
930 dTimerNow ("update velocity");
932 for (i
=0; i
<nb
; i
++) {
933 for (j
=0; j
<3; j
++) body
[i
]->lvel
[j
] = vnew
[i
*6+j
];
934 for (j
=0; j
<3; j
++) body
[i
]->avel
[j
] = vnew
[i
*6+3+j
];
937 // update the position and orientation from the new linear/angular velocity
938 // (over the given timestep)
940 dTimerNow ("update position");
942 for (i
=0; i
<nb
; i
++) dxStepBody (body
[i
],stepsize
);
945 dTimerNow ("tidy up");
948 // zero all force accumulators
949 for (i
=0; i
<nb
; i
++) {
950 body
[i
]->facc
[0] = 0;
951 body
[i
]->facc
[1] = 0;
952 body
[i
]->facc
[2] = 0;
953 body
[i
]->facc
[3] = 0;
954 body
[i
]->tacc
[0] = 0;
955 body
[i
]->tacc
[1] = 0;
956 body
[i
]->tacc
[2] = 0;
957 body
[i
]->tacc
[3] = 0;
962 if (m
> 0) dTimerReport (stdout
,1);
976 //****************************************************************************
977 // an optimized version of dInternalStepIsland1()
979 void dInternalStepIsland_x2 (dxWorld
*world
, dxBody
* const *body
, int nb
,
980 dxJoint
* const *_joint
, int nj
, dReal stepsize
)
984 dTimerStart("preprocessing");
987 dReal stepsize1
= dRecip(stepsize
);
989 // number all bodies in the body list - set their tag values
990 for (i
=0; i
<nb
; i
++) body
[i
]->tag
= i
;
992 // make a local copy of the joint array, because we might want to modify it.
993 // (the "dxJoint *const*" declaration says we're allowed to modify the joints
994 // but not the joint array, because the caller might need it unchanged).
995 ALLOCA(dxJoint
*,joint
,nj
*sizeof(dxJoint
*));
996 #ifdef dUSE_MALLOC_FOR_ALLOCA
998 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1002 memcpy (joint
,_joint
,nj
* sizeof(dxJoint
*));
1004 // for all bodies, compute the inertia tensor and its inverse in the global
1005 // frame, and compute the rotational force and add it to the torque
1006 // accumulator. I and invI are vertically stacked 3x4 matrices, one per body.
1007 // @@@ check computation of rotational force.
1009 ALLOCA(dReal
,I
,3*nb
*4*sizeof(dReal
));
1010 # ifdef dUSE_MALLOC_FOR_ALLOCA
1013 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1019 #endif // for dGYROSCOPIC
1021 ALLOCA(dReal
,invI
,3*nb
*4*sizeof(dReal
));
1022 #ifdef dUSE_MALLOC_FOR_ALLOCA
1026 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1031 //dSetZero (I,3*nb*4);
1032 //dSetZero (invI,3*nb*4);
1033 for (i
=0; i
<nb
; i
++) {
1036 // compute inverse inertia tensor in global frame
1037 dMULTIPLY2_333 (tmp
,body
[i
]->invI
,body
[i
]->posr
.R
);
1038 dMULTIPLY0_333 (invI
+i
*12,body
[i
]->posr
.R
,tmp
);
1040 // compute inertia tensor in global frame
1041 dMULTIPLY2_333 (tmp
,body
[i
]->mass
.I
,body
[i
]->posr
.R
);
1042 dMULTIPLY0_333 (I
+i
*12,body
[i
]->posr
.R
,tmp
);
1044 // compute rotational force
1045 dMULTIPLY0_331 (tmp
,I
+i
*12,body
[i
]->avel
);
1046 dCROSS (body
[i
]->tacc
,-=,body
[i
]->avel
,tmp
);
1050 // add the gravity force to all bodies
1051 for (i
=0; i
<nb
; i
++) {
1052 if ((body
[i
]->flags
& dxBodyNoGravity
)==0) {
1053 body
[i
]->facc
[0] += body
[i
]->mass
.mass
* world
->gravity
[0];
1054 body
[i
]->facc
[1] += body
[i
]->mass
.mass
* world
->gravity
[1];
1055 body
[i
]->facc
[2] += body
[i
]->mass
.mass
* world
->gravity
[2];
1059 // get m = total constraint dimension, nub = number of unbounded variables.
1060 // create constraint offset array and number-of-rows array for all joints.
1061 // the constraints are re-ordered as follows: the purely unbounded
1062 // constraints, the mixed unbounded + LCP constraints, and last the purely
1063 // LCP constraints. this assists the LCP solver to put all unbounded
1064 // variables at the start for a quick factorization.
1066 // joints with m=0 are inactive and are removed from the joints array
1067 // entirely, so that the code that follows does not consider them.
1068 // also number all active joints in the joint list (set their tag values).
1069 // inactive joints receive a tag value of -1.
1072 ALLOCA(dxJoint::Info1
,info
,nj
*sizeof(dxJoint::Info1
));
1073 #ifdef dUSE_MALLOC_FOR_ALLOCA
1078 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1082 ALLOCA(int,ofs
,nj
*sizeof(int));
1083 #ifdef dUSE_MALLOC_FOR_ALLOCA
1089 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1093 for (i
=0, j
=0; j
<nj
; j
++) { // i=dest, j=src
1094 joint
[j
]->vtable
->getInfo1 (joint
[j
],info
+i
);
1095 dIASSERT (info
[i
].m
>= 0 && info
[i
].m
<= 6 &&
1096 info
[i
].nub
>= 0 && info
[i
].nub
<= info
[i
].m
);
1097 if (info
[i
].m
> 0) {
1098 joint
[i
] = joint
[j
];
1108 // the purely unbounded constraints
1109 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
== info
[i
].m
) {
1114 // the mixed unbounded + LCP constraints
1115 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
> 0 && info
[i
].nub
< info
[i
].m
) {
1119 // the purely LCP constraints
1120 for (i
=0; i
<nj
; i
++) if (info
[i
].nub
== 0) {
1125 // this will be set to the force due to the constraints
1126 ALLOCA(dReal
,cforce
,nb
*8*sizeof(dReal
));
1127 #ifdef dUSE_MALLOC_FOR_ALLOCA
1128 if (cforce
== NULL
) {
1134 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1138 dSetZero (cforce
,nb
*8);
1140 // if there are constraints, compute cforce
1142 // create a constraint equation right hand side vector `c', a constraint
1143 // force mixing vector `cfm', and LCP low and high bound vectors, and an
1145 ALLOCA(dReal
,c
,m
*sizeof(dReal
));
1146 #ifdef dUSE_MALLOC_FOR_ALLOCA
1154 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1158 ALLOCA(dReal
,cfm
,m
*sizeof(dReal
));
1159 #ifdef dUSE_MALLOC_FOR_ALLOCA
1168 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1172 ALLOCA(dReal
,lo
,m
*sizeof(dReal
));
1173 #ifdef dUSE_MALLOC_FOR_ALLOCA
1183 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1187 ALLOCA(dReal
,hi
,m
*sizeof(dReal
));
1188 #ifdef dUSE_MALLOC_FOR_ALLOCA
1199 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1203 ALLOCA(int,findex
,m
*sizeof(int));
1204 #ifdef dUSE_MALLOC_FOR_ALLOCA
1205 if (findex
== NULL
) {
1216 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1221 dSetValue (cfm
,m
,world
->global_cfm
);
1222 dSetValue (lo
,m
,-dInfinity
);
1223 dSetValue (hi
,m
, dInfinity
);
1224 for (i
=0; i
<m
; i
++) findex
[i
] = -1;
1226 // get jacobian data from constraints. a (2*m)x8 matrix will be created
1227 // to store the two jacobian blocks from each constraint. it has this
1230 // l l l 0 a a a 0 \ .
1231 // l l l 0 a a a 0 }-- jacobian body 1 block for joint 0 (3 rows)
1232 // l l l 0 a a a 0 /
1233 // l l l 0 a a a 0 \ .
1234 // l l l 0 a a a 0 }-- jacobian body 2 block for joint 0 (3 rows)
1235 // l l l 0 a a a 0 /
1236 // l l l 0 a a a 0 }--- jacobian body 1 block for joint 1 (1 row)
1237 // l l l 0 a a a 0 }--- jacobian body 2 block for joint 1 (1 row)
1240 // (lll) = linear jacobian data
1241 // (aaa) = angular jacobian data
1244 dTimerNow ("create J");
1246 ALLOCA(dReal
,J
,2*m
*8*sizeof(dReal
));
1247 #ifdef dUSE_MALLOC_FOR_ALLOCA
1260 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1265 dxJoint::Info2 Jinfo
;
1267 Jinfo
.fps
= stepsize1
;
1268 Jinfo
.erp
= world
->global_erp
;
1269 for (i
=0; i
<nj
; i
++) {
1270 Jinfo
.J1l
= J
+ 2*8*ofs
[i
];
1271 Jinfo
.J1a
= Jinfo
.J1l
+ 4;
1272 Jinfo
.J2l
= Jinfo
.J1l
+ 8*info
[i
].m
;
1273 Jinfo
.J2a
= Jinfo
.J2l
+ 4;
1274 Jinfo
.c
= c
+ ofs
[i
];
1275 Jinfo
.cfm
= cfm
+ ofs
[i
];
1276 Jinfo
.lo
= lo
+ ofs
[i
];
1277 Jinfo
.hi
= hi
+ ofs
[i
];
1278 Jinfo
.findex
= findex
+ ofs
[i
];
1279 joint
[i
]->vtable
->getInfo2 (joint
[i
],&Jinfo
);
1280 // adjust returned findex values for global index numbering
1281 for (j
=0; j
<info
[i
].m
; j
++) {
1282 if (findex
[ofs
[i
] + j
] >= 0) findex
[ofs
[i
] + j
] += ofs
[i
];
1286 // compute A = J*invM*J'. first compute JinvM = J*invM. this has the same
1287 // format as J so we just go through the constraints in J multiplying by
1288 // the appropriate scalars and matrices.
1290 dTimerNow ("compute A");
1292 ALLOCA(dReal
,JinvM
,2*m
*8*sizeof(dReal
));
1293 #ifdef dUSE_MALLOC_FOR_ALLOCA
1294 if (JinvM
== NULL
) {
1307 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1311 dSetZero (JinvM
,2*m
*8);
1312 for (i
=0; i
<nj
; i
++) {
1313 int b
= joint
[i
]->node
[0].body
->tag
;
1314 dReal body_invMass
= body
[b
]->invMass
;
1315 dReal
*body_invI
= invI
+ b
*12;
1316 dReal
*Jsrc
= J
+ 2*8*ofs
[i
];
1317 dReal
*Jdst
= JinvM
+ 2*8*ofs
[i
];
1318 for (j
=info
[i
].m
-1; j
>=0; j
--) {
1319 for (k
=0; k
<3; k
++) Jdst
[k
] = Jsrc
[k
] * body_invMass
;
1320 dMULTIPLY0_133 (Jdst
+4,Jsrc
+4,body_invI
);
1324 if (joint
[i
]->node
[1].body
) {
1325 b
= joint
[i
]->node
[1].body
->tag
;
1326 body_invMass
= body
[b
]->invMass
;
1327 body_invI
= invI
+ b
*12;
1328 for (j
=info
[i
].m
-1; j
>=0; j
--) {
1329 for (k
=0; k
<3; k
++) Jdst
[k
] = Jsrc
[k
] * body_invMass
;
1330 dMULTIPLY0_133 (Jdst
+4,Jsrc
+4,body_invI
);
1337 // now compute A = JinvM * J'. A's rows and columns are grouped by joint,
1338 // i.e. in the same way as the rows of J. block (i,j) of A is only nonzero
1339 // if joints i and j have at least one body in common. this fact suggests
1340 // the algorithm used to fill A:
1342 // for b = all bodies
1343 // n = number of joints attached to body b
1346 // ii = actual joint number for i
1347 // jj = actual joint number for j
1348 // // (ii,jj) will be set to all pairs of joints around body b
1349 // compute blockwise: A(ii,jj) += JinvM(ii) * J(jj)'
1351 // this algorithm catches all pairs of joints that have at least one body
1352 // in common. it does not compute the diagonal blocks of A however -
1353 // another similar algorithm does that.
1355 int mskip
= dPAD(m
);
1356 ALLOCA(dReal
,A
,m
*mskip
*sizeof(dReal
));
1357 #ifdef dUSE_MALLOC_FOR_ALLOCA
1372 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1376 dSetZero (A
,m
*mskip
);
1377 for (i
=0; i
<nb
; i
++) {
1378 for (dxJointNode
*n1
=body
[i
]->firstjoint
; n1
; n1
=n1
->next
) {
1379 for (dxJointNode
*n2
=n1
->next
; n2
; n2
=n2
->next
) {
1380 // get joint numbers and ensure ofs[j1] >= ofs[j2]
1381 int j1
= n1
->joint
->tag
;
1382 int j2
= n2
->joint
->tag
;
1383 if (ofs
[j1
] < ofs
[j2
]) {
1389 // if either joint was tagged as -1 then it is an inactive (m=0)
1390 // joint that should not be considered
1391 if (j1
==-1 || j2
==-1) continue;
1393 // determine if body i is the 1st or 2nd body of joints j1 and j2
1394 int jb1
= (joint
[j1
]->node
[1].body
== body
[i
]);
1395 int jb2
= (joint
[j2
]->node
[1].body
== body
[i
]);
1396 // jb1/jb2 must be 0 for joints with only one body
1397 dIASSERT(joint
[j1
]->node
[1].body
|| jb1
==0);
1398 dIASSERT(joint
[j2
]->node
[1].body
|| jb2
==0);
1401 MultiplyAdd2_p8r (A
+ ofs
[j1
]*mskip
+ ofs
[j2
],
1402 JinvM
+ 2*8*ofs
[j1
] + jb1
*8*info
[j1
].m
,
1403 J
+ 2*8*ofs
[j2
] + jb2
*8*info
[j2
].m
,
1404 info
[j1
].m
,info
[j2
].m
, mskip
);
1408 // compute diagonal blocks of A
1409 for (i
=0; i
<nj
; i
++) {
1410 Multiply2_p8r (A
+ ofs
[i
]*(mskip
+1),
1413 info
[i
].m
,info
[i
].m
, mskip
);
1414 if (joint
[i
]->node
[1].body
) {
1415 MultiplyAdd2_p8r (A
+ ofs
[i
]*(mskip
+1),
1416 JinvM
+ 2*8*ofs
[i
] + 8*info
[i
].m
,
1417 J
+ 2*8*ofs
[i
] + 8*info
[i
].m
,
1418 info
[i
].m
,info
[i
].m
, mskip
);
1422 // add cfm to the diagonal of A
1423 for (i
=0; i
<m
; i
++) A
[i
*mskip
+i
] += cfm
[i
] * stepsize1
;
1425 # ifdef COMPARE_METHODS
1426 comparator
.nextMatrix (A
,m
,m
,1,"A");
1429 // compute the right hand side `rhs'
1431 dTimerNow ("compute rhs");
1433 ALLOCA(dReal
,tmp1
,nb
*8*sizeof(dReal
));
1434 #ifdef dUSE_MALLOC_FOR_ALLOCA
1450 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1454 //dSetZero (tmp1,nb*8);
1455 // put v/h + invM*fe into tmp1
1456 for (i
=0; i
<nb
; i
++) {
1457 dReal body_invMass
= body
[i
]->invMass
;
1458 dReal
*body_invI
= invI
+ i
*12;
1459 for (j
=0; j
<3; j
++) tmp1
[i
*8+j
] = body
[i
]->facc
[j
] * body_invMass
+
1460 body
[i
]->lvel
[j
] * stepsize1
;
1461 dMULTIPLY0_331 (tmp1
+ i
*8 + 4,body_invI
,body
[i
]->tacc
);
1462 for (j
=0; j
<3; j
++) tmp1
[i
*8+4+j
] += body
[i
]->avel
[j
] * stepsize1
;
1464 // put J*tmp1 into rhs
1465 ALLOCA(dReal
,rhs
,m
*sizeof(dReal
));
1466 #ifdef dUSE_MALLOC_FOR_ALLOCA
1483 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1488 for (i
=0; i
<nj
; i
++) {
1489 dReal
*JJ
= J
+ 2*8*ofs
[i
];
1490 Multiply0_p81 (rhs
+ofs
[i
],JJ
,
1491 tmp1
+ 8*joint
[i
]->node
[0].body
->tag
, info
[i
].m
);
1492 if (joint
[i
]->node
[1].body
) {
1493 MultiplyAdd0_p81 (rhs
+ofs
[i
],JJ
+ 8*info
[i
].m
,
1494 tmp1
+ 8*joint
[i
]->node
[1].body
->tag
, info
[i
].m
);
1498 for (i
=0; i
<m
; i
++) rhs
[i
] = c
[i
]*stepsize1
- rhs
[i
];
1500 # ifdef COMPARE_METHODS
1501 comparator
.nextMatrix (c
,m
,1,0,"c");
1502 comparator
.nextMatrix (rhs
,m
,1,0,"rhs");
1505 // solve the LCP problem and get lambda.
1506 // this will destroy A but that's okay
1508 dTimerNow ("solving LCP problem");
1510 ALLOCA(dReal
,lambda
,m
*sizeof(dReal
));
1511 #ifdef dUSE_MALLOC_FOR_ALLOCA
1512 if (lambda
== NULL
) {
1529 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1533 ALLOCA(dReal
,residual
,m
*sizeof(dReal
));
1534 #ifdef dUSE_MALLOC_FOR_ALLOCA
1535 if (residual
== NULL
) {
1553 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1557 dSolveLCP (m
,A
,lambda
,rhs
,residual
,nub
,lo
,hi
,findex
);
1559 #ifdef dUSE_MALLOC_FOR_ALLOCA
1560 if (dMemoryFlag
== d_MEMORY_OUT_OF_MEMORY
)
1565 // OLD WAY - direct factor and solve
1567 // // factorize A (L*L'=A)
1569 // dTimerNow ("factorize A");
1571 // dReal *L = (dReal*) ALLOCA (m*mskip*sizeof(dReal));
1572 // memcpy (L,A,m*mskip*sizeof(dReal));
1573 //# ifdef FAST_FACTOR
1574 // dFastFactorCholesky (L,m); // does not report non positive definiteness
1576 // if (dFactorCholesky (L,m)==0) dDebug (0,"A is not positive definite");
1579 // // compute lambda
1581 // dTimerNow ("compute lambda");
1583 // dReal *lambda = (dReal*) ALLOCA (m * sizeof(dReal));
1584 // memcpy (lambda,rhs,m * sizeof(dReal));
1585 // dSolveCholesky (L,lambda,m);
1587 # ifdef COMPARE_METHODS
1588 comparator
.nextMatrix (lambda
,m
,1,0,"lambda");
1591 // compute the constraint force `cforce'
1593 dTimerNow ("compute constraint force");
1595 // compute cforce = J'*lambda
1596 for (i
=0; i
<nj
; i
++) {
1597 dReal
*JJ
= J
+ 2*8*ofs
[i
];
1598 dxBody
* b1
= joint
[i
]->node
[0].body
;
1599 dxBody
* b2
= joint
[i
]->node
[1].body
;
1600 dJointFeedback
*fb
= joint
[i
]->feedback
;
1603 // the user has requested feedback on the amount of force that this
1604 // joint is applying to the bodies. we use a slightly slower
1605 // computation that splits out the force components and puts them
1606 // in the feedback structure.
1609 Multiply1_8q1 (data
, JJ
, lambda
+ofs
[i
], info
[i
].m
);
1610 dReal
*cf1
= cforce
+ 8*b1
->tag
;
1611 cf1
[0] += (fb
->f1
[0] = data
[0]);
1612 cf1
[1] += (fb
->f1
[1] = data
[1]);
1613 cf1
[2] += (fb
->f1
[2] = data
[2]);
1614 cf1
[4] += (fb
->t1
[0] = data
[4]);
1615 cf1
[5] += (fb
->t1
[1] = data
[5]);
1616 cf1
[6] += (fb
->t1
[2] = data
[6]);
1618 Multiply1_8q1 (data
, JJ
+ 8*info
[i
].m
, lambda
+ofs
[i
], info
[i
].m
);
1619 dReal
*cf2
= cforce
+ 8*b2
->tag
;
1620 cf2
[0] += (fb
->f2
[0] = data
[0]);
1621 cf2
[1] += (fb
->f2
[1] = data
[1]);
1622 cf2
[2] += (fb
->f2
[2] = data
[2]);
1623 cf2
[4] += (fb
->t2
[0] = data
[4]);
1624 cf2
[5] += (fb
->t2
[1] = data
[5]);
1625 cf2
[6] += (fb
->t2
[2] = data
[6]);
1629 // no feedback is required, let's compute cforce the faster way
1630 MultiplyAdd1_8q1 (cforce
+ 8*b1
->tag
,JJ
, lambda
+ofs
[i
], info
[i
].m
);
1632 MultiplyAdd1_8q1 (cforce
+ 8*b2
->tag
,
1633 JJ
+ 8*info
[i
].m
, lambda
+ofs
[i
], info
[i
].m
);
1651 // compute the velocity update
1653 dTimerNow ("compute velocity update");
1657 for (i
=0; i
<nb
; i
++) {
1658 for (j
=0; j
<3; j
++) cforce
[i
*8+j
] += body
[i
]->facc
[j
];
1659 for (j
=0; j
<3; j
++) cforce
[i
*8+4+j
] += body
[i
]->tacc
[j
];
1661 // multiply cforce by stepsize
1662 for (i
=0; i
< nb
*8; i
++) cforce
[i
] *= stepsize
;
1663 // add invM * cforce to the body velocity
1664 for (i
=0; i
<nb
; i
++) {
1665 dReal body_invMass
= body
[i
]->invMass
;
1666 dReal
*body_invI
= invI
+ i
*12;
1667 for (j
=0; j
<3; j
++) body
[i
]->lvel
[j
] += body_invMass
* cforce
[i
*8+j
];
1668 dMULTIPLYADD0_331 (body
[i
]->avel
,body_invI
,cforce
+i
*8+4);
1671 // update the position and orientation from the new linear/angular velocity
1672 // (over the given timestep)
1674 dTimerNow ("update position");
1676 for (i
=0; i
<nb
; i
++) dxStepBody (body
[i
],stepsize
);
1678 #ifdef COMPARE_METHODS
1679 ALLOCA(dReal
,tmp
, ALLOCA (nb
*6*sizeof(dReal
));
1680 #ifdef dUSE_MALLOC_FOR_ALLOCA
1688 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1692 for (i
=0; i
<nb
; i
++) {
1693 for (j
=0; j
<3; j
++) tmp_vnew
[i
*6+j
] = body
[i
]->lvel
[j
];
1694 for (j
=0; j
<3; j
++) tmp_vnew
[i
*6+3+j
] = body
[i
]->avel
[j
];
1696 comparator
.nextMatrix (tmp_vnew
,nb
*6,1,0,"vnew");
1701 dTimerNow ("tidy up");
1704 // zero all force accumulators
1705 for (i
=0; i
<nb
; i
++) {
1706 body
[i
]->facc
[0] = 0;
1707 body
[i
]->facc
[1] = 0;
1708 body
[i
]->facc
[2] = 0;
1709 body
[i
]->facc
[3] = 0;
1710 body
[i
]->tacc
[0] = 0;
1711 body
[i
]->tacc
[1] = 0;
1712 body
[i
]->tacc
[2] = 0;
1713 body
[i
]->tacc
[3] = 0;
1718 if (m
> 0) dTimerReport (stdout
,1);
1729 //****************************************************************************
1731 void dInternalStepIsland (dxWorld
*world
, dxBody
* const *body
, int nb
,
1732 dxJoint
* const *joint
, int nj
, dReal stepsize
)
1735 #ifdef dUSE_MALLOC_FOR_ALLOCA
1736 dMemoryFlag
= d_MEMORY_OK
;
1739 #ifndef COMPARE_METHODS
1740 dInternalStepIsland_x2 (world
,body
,nb
,joint
,nj
,stepsize
);
1742 #ifdef dUSE_MALLOC_FOR_ALLOCA
1743 if (dMemoryFlag
== d_MEMORY_OUT_OF_MEMORY
) {
1744 REPORT_OUT_OF_MEMORY
;
1751 #ifdef COMPARE_METHODS
1755 ALLOCA(dxBody
,state
,nb
*sizeof(dxBody
));
1756 #ifdef dUSE_MALLOC_FOR_ALLOCA
1757 if (state
== NULL
) {
1758 dMemoryFlag
= d_MEMORY_OUT_OF_MEMORY
;
1759 REPORT_OUT_OF_MEMORY
;
1763 for (i
=0; i
<nb
; i
++) memcpy (state
+i
,body
[i
],sizeof(dxBody
));
1767 dInternalStepIsland_x1 (world
,body
,nb
,joint
,nj
,stepsize
);
1769 #ifdef dUSE_MALLOC_FOR_ALLOCA
1770 if (dMemoryFlag
== d_MEMORY_OUT_OF_MEMORY
) {
1772 REPORT_OUT_OF_MEMORY
;
1778 for (i
=0; i
<nb
; i
++) memcpy (body
[i
],state
+i
,sizeof(dxBody
));
1781 dInternalStepIsland_x2 (world
,body
,nb
,joint
,nj
,stepsize
);
1783 #ifdef dUSE_MALLOC_FOR_ALLOCA
1784 if (dMemoryFlag
== d_MEMORY_OUT_OF_MEMORY
) {
1786 REPORT_OUT_OF_MEMORY
;
1791 //comparator.dump();