Home | History | Annotate | Download | only in Featherstone
      1 /*
      2  * PURPOSE:
      3  *   Class representing an articulated rigid body. Stores the body's
      4  *   current state, allows forces and torques to be set, handles
      5  *   timestepping and implements Featherstone's algorithm.
      6  *
      7  * COPYRIGHT:
      8  *   Copyright (C) Stephen Thompson, <stephen (at) solarflare.org.uk>, 2011-2013
      9  *   Portions written By Erwin Coumans: replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
     10 
     11  This software is provided 'as-is', without any express or implied warranty.
     12  In no event will the authors be held liable for any damages arising from the use of this software.
     13  Permission is granted to anyone to use this software for any purpose,
     14  including commercial applications, and to alter it and redistribute it freely,
     15  subject to the following restrictions:
     16 
     17  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
     18  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20 
     21  */
     22 
     23 
     24 #ifndef BT_MULTIBODY_H
     25 #define BT_MULTIBODY_H
     26 
     27 #include "LinearMath/btScalar.h"
     28 #include "LinearMath/btVector3.h"
     29 #include "LinearMath/btQuaternion.h"
     30 #include "LinearMath/btMatrix3x3.h"
     31 #include "LinearMath/btAlignedObjectArray.h"
     32 
     33 #ifdef BT_USE_DOUBLE_PRECISION
     34 	#define btMultiBodyData	btMultiBodyDoubleData
     35 	#define btMultiBodyDataName	"btMultiBodyDoubleData"
     36 	#define btMultiBodyLinkData btMultiBodyLinkDoubleData
     37 	#define btMultiBodyLinkDataName	"btMultiBodyLinkDoubleData"
     38 #else
     39 	#define btMultiBodyData	btMultiBodyFloatData
     40 	#define btMultiBodyDataName	"btMultiBodyFloatData"
     41 	#define btMultiBodyLinkData btMultiBodyLinkFloatData
     42 	#define btMultiBodyLinkDataName	"btMultiBodyLinkFloatData"
     43 #endif //BT_USE_DOUBLE_PRECISION
     44 
     45 #include "btMultiBodyLink.h"
     46 class btMultiBodyLinkCollider;
     47 
     48 class btMultiBody
     49 {
     50 public:
     51 
     52 
     53 	BT_DECLARE_ALIGNED_ALLOCATOR();
     54 
     55     //
     56     // initialization
     57     //
     58 
     59 	btMultiBody(int n_links,             // NOT including the base
     60 		btScalar mass,                // mass of base
     61 		const btVector3 &inertia,    // inertia of base, in base frame; assumed diagonal
     62 		bool fixedBase,           // whether the base is fixed (true) or can move (false)
     63 		bool canSleep,
     64 		bool multiDof = false
     65 			  );
     66 
     67 
     68 	virtual ~btMultiBody();
     69 
     70 	void setupFixed(int linkIndex,
     71 						   btScalar mass,
     72 						   const btVector3 &inertia,
     73 						   int parent,
     74 						   const btQuaternion &rotParentToThis,
     75 						   const btVector3 &parentComToThisPivotOffset,
     76                            const btVector3 &thisPivotToThisComOffset,
     77 						   bool disableParentCollision);
     78 
     79 
     80 	void setupPrismatic(int i,
     81                                btScalar mass,
     82                                const btVector3 &inertia,
     83                                int parent,
     84                                const btQuaternion &rotParentToThis,
     85                                const btVector3 &jointAxis,
     86                                const btVector3 &parentComToThisPivotOffset,
     87 							   const btVector3 &thisPivotToThisComOffset,
     88 							   bool disableParentCollision);
     89 
     90     void setupRevolute(int linkIndex,            // 0 to num_links-1
     91                        btScalar mass,
     92                        const btVector3 &inertia,
     93                        int parentIndex,
     94                        const btQuaternion &rotParentToThis,  // rotate points in parent frame to this frame, when q = 0
     95                        const btVector3 &jointAxis,    // in my frame
     96                        const btVector3 &parentComToThisPivotOffset,    // vector from parent COM to joint axis, in PARENT frame
     97                        const btVector3 &thisPivotToThisComOffset,       // vector from joint axis to my COM, in MY frame
     98 					   bool disableParentCollision=false);
     99 
    100 	void setupSpherical(int linkIndex,											// 0 to num_links-1
    101                        btScalar mass,
    102                        const btVector3 &inertia,
    103                        int parent,
    104                        const btQuaternion &rotParentToThis,		// rotate points in parent frame to this frame, when q = 0
    105                        const btVector3 &parentComToThisPivotOffset,			// vector from parent COM to joint axis, in PARENT frame
    106                        const btVector3 &thisPivotToThisComOffset,				// vector from joint axis to my COM, in MY frame
    107 					   bool disableParentCollision=false);
    108 
    109 	void setupPlanar(int i,											// 0 to num_links-1
    110                        btScalar mass,
    111                        const btVector3 &inertia,
    112                        int parent,
    113                        const btQuaternion &rotParentToThis,		// rotate points in parent frame to this frame, when q = 0
    114 					   const btVector3 &rotationAxis,
    115                        const btVector3 &parentComToThisComOffset,			// vector from parent COM to this COM, in PARENT frame
    116 					   bool disableParentCollision=false);
    117 
    118 	const btMultibodyLink& getLink(int index) const
    119 	{
    120 		return m_links[index];
    121 	}
    122 
    123 	btMultibodyLink& getLink(int index)
    124 	{
    125 		return m_links[index];
    126 	}
    127 
    128 
    129 	void setBaseCollider(btMultiBodyLinkCollider* collider)//collider can be NULL to disable collision for the base
    130 	{
    131 		m_baseCollider = collider;
    132 	}
    133 	const btMultiBodyLinkCollider* getBaseCollider() const
    134 	{
    135 		return m_baseCollider;
    136 	}
    137 	btMultiBodyLinkCollider* getBaseCollider()
    138 	{
    139 		return m_baseCollider;
    140 	}
    141 
    142     //
    143     // get parent
    144     // input: link num from 0 to num_links-1
    145     // output: link num from 0 to num_links-1, OR -1 to mean the base.
    146     //
    147     int getParent(int link_num) const;
    148 
    149 
    150     //
    151     // get number of m_links, masses, moments of inertia
    152     //
    153 
    154     int getNumLinks() const { return m_links.size(); }
    155 	int getNumDofs() const { return m_dofCount; }
    156 	int getNumPosVars() const { return m_posVarCnt; }
    157     btScalar getBaseMass() const { return m_baseMass; }
    158     const btVector3 & getBaseInertia() const { return m_baseInertia; }
    159     btScalar getLinkMass(int i) const;
    160     const btVector3 & getLinkInertia(int i) const;
    161 
    162 
    163 
    164     //
    165     // change mass (incomplete: can only change base mass and inertia at present)
    166     //
    167 
    168     void setBaseMass(btScalar mass) { m_baseMass = mass; }
    169     void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
    170 
    171 
    172     //
    173     // get/set pos/vel/rot/omega for the base link
    174     //
    175 
    176     const btVector3 & getBasePos() const { return m_basePos; }    // in world frame
    177     const btVector3 getBaseVel() const
    178 	{
    179 		return btVector3(m_realBuf[3],m_realBuf[4],m_realBuf[5]);
    180 	}     // in world frame
    181     const btQuaternion & getWorldToBaseRot() const
    182 	{
    183 		return m_baseQuat;
    184 	}     // rotates world vectors into base frame
    185     btVector3 getBaseOmega() const { return btVector3(m_realBuf[0],m_realBuf[1],m_realBuf[2]); }   // in world frame
    186 
    187     void setBasePos(const btVector3 &pos)
    188 	{
    189 		m_basePos = pos;
    190 	}
    191 
    192 	void setBaseWorldTransform(const btTransform& tr)
    193 	{
    194 		setBasePos(tr.getOrigin());
    195 		setWorldToBaseRot(tr.getRotation().inverse());
    196 
    197 	}
    198 
    199 	btTransform getBaseWorldTransform() const
    200 	{
    201 		btTransform tr;
    202 		tr.setOrigin(getBasePos());
    203 		tr.setRotation(getWorldToBaseRot().inverse());
    204 		return tr;
    205 	}
    206 
    207     void setBaseVel(const btVector3 &vel)
    208 	{
    209 
    210 		m_realBuf[3]=vel[0]; m_realBuf[4]=vel[1]; m_realBuf[5]=vel[2];
    211 	}
    212     void setWorldToBaseRot(const btQuaternion &rot)
    213 	{
    214 		m_baseQuat = rot;					//m_baseQuat asumed to ba alias!?
    215 	}
    216     void setBaseOmega(const btVector3 &omega)
    217 	{
    218 		m_realBuf[0]=omega[0];
    219 		m_realBuf[1]=omega[1];
    220 		m_realBuf[2]=omega[2];
    221 	}
    222 
    223 
    224     //
    225     // get/set pos/vel for child m_links (i = 0 to num_links-1)
    226     //
    227 
    228     btScalar getJointPos(int i) const;
    229     btScalar getJointVel(int i) const;
    230 
    231 	btScalar * getJointVelMultiDof(int i);
    232 	btScalar * getJointPosMultiDof(int i);
    233 
    234 	const btScalar * getJointVelMultiDof(int i) const ;
    235 	const btScalar * getJointPosMultiDof(int i) const ;
    236 
    237     void setJointPos(int i, btScalar q);
    238     void setJointVel(int i, btScalar qdot);
    239 	void setJointPosMultiDof(int i, btScalar *q);
    240     void setJointVelMultiDof(int i, btScalar *qdot);
    241 
    242 
    243 
    244     //
    245     // direct access to velocities as a vector of 6 + num_links elements.
    246     // (omega first, then v, then joint velocities.)
    247     //
    248     const btScalar * getVelocityVector() const
    249 	{
    250 		return &m_realBuf[0];
    251 	}
    252 /*    btScalar * getVelocityVector()
    253 	{
    254 		return &real_buf[0];
    255 	}
    256   */
    257 
    258     //
    259     // get the frames of reference (positions and orientations) of the child m_links
    260     // (i = 0 to num_links-1)
    261     //
    262 
    263     const btVector3 & getRVector(int i) const;   // vector from COM(parent(i)) to COM(i), in frame i's coords
    264     const btQuaternion & getParentToLocalRot(int i) const;   // rotates vectors in frame parent(i) to vectors in frame i.
    265 
    266 
    267     //
    268     // transform vectors in local frame of link i to world frame (or vice versa)
    269     //
    270     btVector3 localPosToWorld(int i, const btVector3 &vec) const;
    271     btVector3 localDirToWorld(int i, const btVector3 &vec) const;
    272     btVector3 worldPosToLocal(int i, const btVector3 &vec) const;
    273     btVector3 worldDirToLocal(int i, const btVector3 &vec) const;
    274 
    275 
    276     //
    277     // calculate kinetic energy and angular momentum
    278     // useful for debugging.
    279     //
    280 
    281     btScalar getKineticEnergy() const;
    282     btVector3 getAngularMomentum() const;
    283 
    284 
    285     //
    286     // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
    287     //
    288 
    289     void clearForcesAndTorques();
    290    void clearConstraintForces();
    291 
    292 	void clearVelocities();
    293 
    294     void addBaseForce(const btVector3 &f)
    295 	{
    296 		m_baseForce += f;
    297 	}
    298     void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
    299     void addLinkForce(int i, const btVector3 &f);
    300     void addLinkTorque(int i, const btVector3 &t);
    301 
    302  void addBaseConstraintForce(const btVector3 &f)
    303         {
    304                 m_baseConstraintForce += f;
    305         }
    306     void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
    307     void addLinkConstraintForce(int i, const btVector3 &f);
    308     void addLinkConstraintTorque(int i, const btVector3 &t);
    309 
    310 
    311 void addJointTorque(int i, btScalar Q);
    312 	void addJointTorqueMultiDof(int i, int dof, btScalar Q);
    313 	void addJointTorqueMultiDof(int i, const btScalar *Q);
    314 
    315     const btVector3 & getBaseForce() const { return m_baseForce; }
    316     const btVector3 & getBaseTorque() const { return m_baseTorque; }
    317     const btVector3 & getLinkForce(int i) const;
    318     const btVector3 & getLinkTorque(int i) const;
    319     btScalar getJointTorque(int i) const;
    320 	btScalar * getJointTorqueMultiDof(int i);
    321 
    322 
    323     //
    324     // dynamics routines.
    325     //
    326 
    327     // timestep the velocities (given the external forces/torques set using addBaseForce etc).
    328     // also sets up caches for calcAccelerationDeltas.
    329     //
    330     // Note: the caller must provide three vectors which are used as
    331     // temporary scratch space. The idea here is to reduce dynamic
    332     // memory allocation: the same scratch vectors can be re-used
    333     // again and again for different Multibodies, instead of each
    334     // btMultiBody allocating (and then deallocating) their own
    335     // individual scratch buffers. This gives a considerable speed
    336     // improvement, at least on Windows (where dynamic memory
    337     // allocation appears to be fairly slow).
    338     //
    339     void stepVelocities(btScalar dt,
    340                         btAlignedObjectArray<btScalar> &scratch_r,
    341                         btAlignedObjectArray<btVector3> &scratch_v,
    342                         btAlignedObjectArray<btMatrix3x3> &scratch_m);
    343 
    344 	void stepVelocitiesMultiDof(btScalar dt,
    345                         btAlignedObjectArray<btScalar> &scratch_r,
    346                         btAlignedObjectArray<btVector3> &scratch_v,
    347                         btAlignedObjectArray<btMatrix3x3> &scratch_m,
    348 			bool isConstraintPass=false
    349 		);
    350 
    351     // calcAccelerationDeltas
    352     // input: force vector (in same format as jacobian, i.e.:
    353     //                      3 torque values, 3 force values, num_links joint torque values)
    354     // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
    355     // (existing contents of output array are replaced)
    356     // stepVelocities must have been called first.
    357     void calcAccelerationDeltas(const btScalar *force, btScalar *output,
    358                                 btAlignedObjectArray<btScalar> &scratch_r,
    359                                 btAlignedObjectArray<btVector3> &scratch_v) const;
    360 
    361 	void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
    362                                 btAlignedObjectArray<btScalar> &scratch_r,
    363                                 btAlignedObjectArray<btVector3> &scratch_v) const;
    364 
    365     // apply a delta-vee directly. used in sequential impulses code.
    366     void applyDeltaVee(const btScalar * delta_vee)
    367 	{
    368 
    369         for (int i = 0; i < 6 + getNumLinks(); ++i)
    370 		{
    371 			m_realBuf[i] += delta_vee[i];
    372 		}
    373 
    374     }
    375     void applyDeltaVee(const btScalar * delta_vee, btScalar multiplier)
    376 	{
    377 		btScalar sum = 0;
    378         for (int i = 0; i < 6 + getNumLinks(); ++i)
    379 		{
    380 			sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
    381 		}
    382 		btScalar l = btSqrt(sum);
    383 		/*
    384 		static btScalar maxl = -1e30f;
    385 		if (l>maxl)
    386 		{
    387 			maxl=l;
    388 	//		printf("maxl=%f\n",maxl);
    389 		}
    390 		*/
    391 		if (l>m_maxAppliedImpulse)
    392 		{
    393 //			printf("exceeds 100: l=%f\n",maxl);
    394 			multiplier *= m_maxAppliedImpulse/l;
    395 		}
    396 
    397         for (int i = 0; i < 6 + getNumLinks(); ++i)
    398 		{
    399 			sum += delta_vee[i]*multiplier*delta_vee[i]*multiplier;
    400 			m_realBuf[i] += delta_vee[i] * multiplier;
    401 			btClamp(m_realBuf[i],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
    402 		}
    403     }
    404 
    405 	void applyDeltaVeeMultiDof2(const btScalar * delta_vee, btScalar multiplier)
    406 	{
    407 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
    408                 {
    409                         m_deltaV[dof] += delta_vee[dof] * multiplier;
    410                 }
    411 	}
    412 	void processDeltaVeeMultiDof2()
    413 	{
    414 		applyDeltaVeeMultiDof(&m_deltaV[0],1);
    415 
    416 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
    417                 {
    418 			m_deltaV[dof] = 0.f;
    419 		}
    420 	}
    421 
    422 	void applyDeltaVeeMultiDof(const btScalar * delta_vee, btScalar multiplier)
    423 	{
    424 		//for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
    425 		//	printf("%.4f ", delta_vee[dof]*multiplier);
    426 		//printf("\n");
    427 
    428 		//btScalar sum = 0;
    429 		//for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
    430 		//{
    431 		//	sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
    432 		//}
    433 		//btScalar l = btSqrt(sum);
    434 
    435 		//if (l>m_maxAppliedImpulse)
    436 		//{
    437 		//	multiplier *= m_maxAppliedImpulse/l;
    438 		//}
    439 
    440 		for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
    441 		{
    442 			m_realBuf[dof] += delta_vee[dof] * multiplier;
    443 			btClamp(m_realBuf[dof],-m_maxCoordinateVelocity,m_maxCoordinateVelocity);
    444 		}
    445     }
    446 
    447 
    448 
    449     // timestep the positions (given current velocities).
    450     void stepPositions(btScalar dt);
    451 	void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
    452 
    453 
    454     //
    455     // contacts
    456     //
    457 
    458     // This routine fills out a contact constraint jacobian for this body.
    459     // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
    460     // 'normal' & 'contact_point' are both given in world coordinates.
    461     void fillContactJacobian(int link,
    462                              const btVector3 &contact_point,
    463                              const btVector3 &normal,
    464                              btScalar *jac,
    465                              btAlignedObjectArray<btScalar> &scratch_r,
    466                              btAlignedObjectArray<btVector3> &scratch_v,
    467                              btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
    468 
    469 	//multidof version of fillContactJacobian
    470 	void fillContactJacobianMultiDof(int link,
    471                              const btVector3 &contact_point,
    472                              const btVector3 &normal,
    473                              btScalar *jac,
    474                              btAlignedObjectArray<btScalar> &scratch_r,
    475                              btAlignedObjectArray<btVector3> &scratch_v,
    476 							 btAlignedObjectArray<btMatrix3x3> &scratch_m) const { filConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
    477 
    478 	//a more general version of fillContactJacobianMultiDof which does not assume..
    479 	//.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
    480 	void filConstraintJacobianMultiDof(int link,
    481                              const btVector3 &contact_point,
    482 							 const btVector3 &normal_ang,
    483                              const btVector3 &normal_lin,
    484                              btScalar *jac,
    485                              btAlignedObjectArray<btScalar> &scratch_r,
    486                              btAlignedObjectArray<btVector3> &scratch_v,
    487                              btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
    488 
    489 
    490     //
    491     // sleeping
    492     //
    493 	void	setCanSleep(bool canSleep)
    494 	{
    495 		m_canSleep = canSleep;
    496 	}
    497 
    498 	bool getCanSleep()const
    499 	{
    500 		return m_canSleep;
    501 	}
    502 
    503     bool isAwake() const { return m_awake; }
    504     void wakeUp();
    505     void goToSleep();
    506     void checkMotionAndSleepIfRequired(btScalar timestep);
    507 
    508 	bool hasFixedBase() const
    509 	{
    510 		    return m_fixedBase;
    511 	}
    512 
    513 	int getCompanionId() const
    514 	{
    515 		return m_companionId;
    516 	}
    517 	void setCompanionId(int id)
    518 	{
    519 		//printf("for %p setCompanionId(%d)\n",this, id);
    520 		m_companionId = id;
    521 	}
    522 
    523 	void setNumLinks(int numLinks)//careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
    524 	{
    525 		m_links.resize(numLinks);
    526 	}
    527 
    528 	btScalar getLinearDamping() const
    529 	{
    530 			return m_linearDamping;
    531 	}
    532 	void setLinearDamping( btScalar damp)
    533 	{
    534 		m_linearDamping = damp;
    535 	}
    536 	btScalar getAngularDamping() const
    537 	{
    538 		return m_angularDamping;
    539 	}
    540 	void setAngularDamping( btScalar damp)
    541 	{
    542 		m_angularDamping = damp;
    543 	}
    544 
    545 	bool getUseGyroTerm() const
    546 	{
    547 		return m_useGyroTerm;
    548 	}
    549 	void setUseGyroTerm(bool useGyro)
    550 	{
    551 		m_useGyroTerm = useGyro;
    552 	}
    553 	btScalar	getMaxCoordinateVelocity() const
    554 	{
    555 		return m_maxCoordinateVelocity ;
    556 	}
    557 	void	setMaxCoordinateVelocity(btScalar maxVel)
    558 	{
    559 		m_maxCoordinateVelocity = maxVel;
    560 	}
    561 
    562 	btScalar	getMaxAppliedImpulse() const
    563 	{
    564 		return m_maxAppliedImpulse;
    565 	}
    566 	void	setMaxAppliedImpulse(btScalar maxImp)
    567 	{
    568 		m_maxAppliedImpulse = maxImp;
    569 	}
    570 	void	setHasSelfCollision(bool hasSelfCollision)
    571 	{
    572 		m_hasSelfCollision = hasSelfCollision;
    573 	}
    574 	bool hasSelfCollision() const
    575 	{
    576 		return m_hasSelfCollision;
    577 	}
    578 
    579 	bool isMultiDof() { return m_isMultiDof; }
    580 	void finalizeMultiDof();
    581 
    582 	void useRK4Integration(bool use) { m_useRK4 = use; }
    583 	bool isUsingRK4Integration() const { return m_useRK4; }
    584 	void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
    585 	bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
    586 
    587 	bool isPosUpdated() const
    588 	{
    589 		return __posUpdated;
    590 	}
    591 	void setPosUpdated(bool updated)
    592 	{
    593 		__posUpdated = updated;
    594 	}
    595 
    596 	//internalNeedsJointFeedback is for internal use only
    597 	bool internalNeedsJointFeedback() const
    598 	{
    599 		return m_internalNeedsJointFeedback;
    600 	}
    601 	void	forwardKinematics(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
    602 
    603 	void	updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion>& scratch_q,btAlignedObjectArray<btVector3>& scratch_m);
    604 
    605 	virtual	int	calculateSerializeBufferSize()	const;
    606 
    607 	///fills the dataBuffer and returns the struct name (and 0 on failure)
    608 	virtual	const char*	serialize(void* dataBuffer,  class btSerializer* serializer) const;
    609 
    610 	const char*				getBaseName() const
    611 	{
    612 		return m_baseName;
    613 	}
    614 	///memory of setBaseName needs to be manager by user
    615 	void	setBaseName(const char* name)
    616 	{
    617 		m_baseName = name;
    618 	}
    619 
    620 private:
    621     btMultiBody(const btMultiBody &);  // not implemented
    622     void operator=(const btMultiBody &);  // not implemented
    623 
    624     void compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const;
    625 
    626 	void solveImatrix(const btVector3& rhs_top, const btVector3& rhs_bot, float result[6]) const;
    627 	void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
    628 
    629 	void updateLinksDofOffsets()
    630 	{
    631 		int dofOffset = 0, cfgOffset = 0;
    632 		for(int bidx = 0; bidx < m_links.size(); ++bidx)
    633 		{
    634 			m_links[bidx].m_dofOffset = dofOffset; m_links[bidx].m_cfgOffset = cfgOffset;
    635 			dofOffset += m_links[bidx].m_dofCount; cfgOffset += m_links[bidx].m_posVarCount;
    636 		}
    637 	}
    638 
    639 	void mulMatrix(btScalar *pA, btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
    640 
    641 
    642 private:
    643 
    644 	btMultiBodyLinkCollider* m_baseCollider;//can be NULL
    645 	const char*				m_baseName;//memory needs to be manager by user!
    646 
    647     btVector3 m_basePos;       // position of COM of base (world frame)
    648     btQuaternion m_baseQuat;   // rotates world points into base frame
    649 
    650     btScalar m_baseMass;         // mass of the base
    651     btVector3 m_baseInertia;   // inertia of the base (in local frame; diagonal)
    652 
    653     btVector3 m_baseForce;     // external force applied to base. World frame.
    654     btVector3 m_baseTorque;    // external torque applied to base. World frame.
    655 
    656     btVector3 m_baseConstraintForce;     // external force applied to base. World frame.
    657     btVector3 m_baseConstraintTorque;    // external torque applied to base. World frame.
    658 
    659     btAlignedObjectArray<btMultibodyLink> m_links;    // array of m_links, excluding the base. index from 0 to num_links-1.
    660 	btAlignedObjectArray<btMultiBodyLinkCollider*> m_colliders;
    661 
    662 
    663     //
    664     // realBuf:
    665     //  offset         size            array
    666     //   0              6 + num_links   v (base_omega; base_vel; joint_vels)					MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
    667     //   6+num_links    num_links       D
    668     //
    669     // vectorBuf:
    670     //  offset         size         array
    671     //   0              num_links    h_top
    672     //   num_links      num_links    h_bottom
    673     //
    674     // matrixBuf:
    675     //  offset         size         array
    676     //   0              num_links+1  rot_from_parent
    677     //
    678    btAlignedObjectArray<btScalar> m_deltaV;
    679     btAlignedObjectArray<btScalar> m_realBuf;
    680     btAlignedObjectArray<btVector3> m_vectorBuf;
    681     btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
    682 
    683 
    684 	btMatrix3x3 m_cachedInertiaTopLeft;
    685 	btMatrix3x3 m_cachedInertiaTopRight;
    686 	btMatrix3x3 m_cachedInertiaLowerLeft;
    687 	btMatrix3x3 m_cachedInertiaLowerRight;
    688 
    689     bool m_fixedBase;
    690 
    691     // Sleep parameters.
    692     bool m_awake;
    693     bool m_canSleep;
    694     btScalar m_sleepTimer;
    695 
    696 	int	m_companionId;
    697 	btScalar	m_linearDamping;
    698 	btScalar	m_angularDamping;
    699 	bool	m_useGyroTerm;
    700 	btScalar	m_maxAppliedImpulse;
    701 	btScalar	m_maxCoordinateVelocity;
    702 	bool		m_hasSelfCollision;
    703 	bool		m_isMultiDof;
    704 		bool __posUpdated;
    705 		int m_dofCount, m_posVarCnt;
    706 	bool m_useRK4, m_useGlobalVelocities;
    707 
    708 	///the m_needsJointFeedback gets updated/computed during the stepVelocitiesMultiDof and it for internal usage only
    709 	bool m_internalNeedsJointFeedback;
    710 };
    711 
    712 struct btMultiBodyLinkDoubleData
    713 {
    714 	btQuaternionDoubleData	m_zeroRotParentToThis;
    715 	btVector3DoubleData		m_parentComToThisComOffset;
    716 	btVector3DoubleData		m_thisPivotToThisComOffset;
    717 	btVector3DoubleData		m_jointAxisTop[6];
    718 	btVector3DoubleData		m_jointAxisBottom[6];
    719 
    720 
    721 	char					*m_linkName;
    722 	char					*m_jointName;
    723 	btCollisionObjectDoubleData	*m_linkCollider;
    724 
    725 	btVector3DoubleData		m_linkInertia;   // inertia of the base (in local frame; diagonal)
    726 	double					m_linkMass;
    727 	int						m_parentIndex;
    728 	int						m_jointType;
    729 
    730 
    731 
    732 
    733 	int						m_dofCount;
    734 	int						m_posVarCount;
    735 	double					m_jointPos[7];
    736 	double					m_jointVel[6];
    737 	double					m_jointTorque[6];
    738 
    739 
    740 
    741 };
    742 
    743 struct btMultiBodyLinkFloatData
    744 {
    745 	btQuaternionFloatData	m_zeroRotParentToThis;
    746 	btVector3FloatData		m_parentComToThisComOffset;
    747 	btVector3FloatData		m_thisPivotToThisComOffset;
    748 	btVector3FloatData		m_jointAxisTop[6];
    749 	btVector3FloatData		m_jointAxisBottom[6];
    750 
    751 
    752 	char				*m_linkName;
    753 	char				*m_jointName;
    754 	btCollisionObjectFloatData	*m_linkCollider;
    755 
    756 	btVector3FloatData	m_linkInertia;   // inertia of the base (in local frame; diagonal)
    757 	int						m_dofCount;
    758 	float				m_linkMass;
    759 	int					m_parentIndex;
    760 	int					m_jointType;
    761 
    762 
    763 
    764 	float					m_jointPos[7];
    765 	float					m_jointVel[6];
    766 	float					m_jointTorque[6];
    767 	int						m_posVarCount;
    768 
    769 
    770 };
    771 
    772 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
    773 struct	btMultiBodyDoubleData
    774 {
    775 	char	*m_baseName;
    776 	btMultiBodyLinkDoubleData	*m_links;
    777 	btCollisionObjectDoubleData	*m_baseCollider;
    778 
    779 	btTransformDoubleData m_baseWorldTransform;
    780 	btVector3DoubleData m_baseInertia;   // inertia of the base (in local frame; diagonal)
    781 
    782 	int		m_numLinks;
    783 	double	m_baseMass;
    784 
    785 	char m_padding[4];
    786 
    787 };
    788 
    789 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
    790 struct	btMultiBodyFloatData
    791 {
    792 	char	*m_baseName;
    793 	btMultiBodyLinkFloatData	*m_links;
    794 	btCollisionObjectFloatData	*m_baseCollider;
    795 	btTransformFloatData m_baseWorldTransform;
    796 	btVector3FloatData m_baseInertia;   // inertia of the base (in local frame; diagonal)
    797 
    798 	float	m_baseMass;
    799 	int		m_numLinks;
    800 };
    801 
    802 
    803 
    804 #endif
    805