2017-08-01 14:30:58 +02:00
/*
Bullet Continuous Collision Detection and Physics Library
Copyright ( c ) 2013 Erwin Coumans http : //bulletphysics.org
This software is provided ' as - is ' , without any express or implied warranty .
In no event will the authors be held liable for any damages arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it freely ,
subject to the following restrictions :
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 .
2. Altered source versions must be plainly marked as such , and must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
# ifndef BT_MULTIBODY_LINK_H
# define BT_MULTIBODY_LINK_H
# include "LinearMath/btQuaternion.h"
# include "LinearMath/btVector3.h"
# include "BulletCollision/CollisionDispatch/btCollisionObject.h"
2019-01-03 14:26:51 +01:00
enum btMultiBodyLinkFlags
2017-08-01 14:30:58 +02:00
{
BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION = 1 ,
BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION = 2 ,
} ;
//both defines are now permanently enabled
# define BT_MULTIBODYLINK_INCLUDE_PLANAR_JOINTS
# define TEST_SPATIAL_ALGEBRA_LAYER
//
// Various spatial helper functions
//
//namespace {
# include "LinearMath/btSpatialAlgebra.h"
//}
//
// Link struct
//
2019-01-03 14:26:51 +01:00
struct btMultibodyLink
2017-08-01 14:30:58 +02:00
{
BT_DECLARE_ALIGNED_ALLOCATOR ( ) ;
2019-01-03 14:26:51 +01:00
btScalar m_mass ; // mass of link
btVector3 m_inertiaLocal ; // inertia of link (local frame; diagonal)
int m_parent ; // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btQuaternion m_zeroRotParentToThis ; // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btVector3 m_dVector ; // vector from the inboard joint pos to this link's COM. (local frame.) constant.
//this is set to zero for planar joint (see also m_eVector comment)
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
// m_eVector is constant, but depends on the joint type:
// revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
2017-08-01 14:30:58 +02:00
// planar: vector from COM of parent to COM of this link, WHEN Q = 0. (local frame.)
// todo: fix the planar so it is consistent with the other joints
2019-01-03 14:26:51 +01:00
btVector3 m_eVector ;
2017-08-01 14:30:58 +02:00
btSpatialMotionVector m_absFrameTotVelocity , m_absFrameLocVelocity ;
enum eFeatherstoneJointType
{
eRevolute = 0 ,
ePrismatic = 1 ,
eSpherical = 2 ,
ePlanar = 3 ,
eFixed = 4 ,
eInvalid
} ;
// "axis" = spatial joint axis (Mirtich Defn 9 p104). (expressed in local frame.) constant.
2019-01-03 14:26:51 +01:00
// for prismatic: m_axesTop[0] = zero;
// m_axesBottom[0] = unit vector along the joint axis.
// for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
// m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
2017-08-01 14:30:58 +02:00
//
// for spherical: m_axesTop[0][1][2] (u1,u2,u3) form a 3x3 identity matrix (3 rotation axes)
// m_axesBottom[0][1][2] cross u1,u2,u3 (i.e. COM linear motion due to the rotation at the joint)
//
// for planar: m_axesTop[0] = unit vector along the rotation axis (u); defines the plane of motion
// m_axesTop[1][2] = zero
// m_axesBottom[0] = zero
2019-01-03 14:26:51 +01:00
// m_axesBottom[1][2] = unit vectors along the translational axes on that plane
2017-08-01 14:30:58 +02:00
btSpatialMotionVector m_axes [ 6 ] ;
void setAxisTop ( int dof , const btVector3 & axis ) { m_axes [ dof ] . m_topVec = axis ; }
2019-01-03 14:26:51 +01:00
void setAxisBottom ( int dof , const btVector3 & axis )
{
m_axes [ dof ] . m_bottomVec = axis ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
void setAxisTop ( int dof , const btScalar & x , const btScalar & y , const btScalar & z )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
m_axes [ dof ] . m_topVec . setValue ( x , y , z ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
void setAxisBottom ( int dof , const btScalar & x , const btScalar & y , const btScalar & z )
{
m_axes [ dof ] . m_bottomVec . setValue ( x , y , z ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
const btVector3 & getAxisTop ( int dof ) const { return m_axes [ dof ] . m_topVec ; }
const btVector3 & getAxisBottom ( int dof ) const { return m_axes [ dof ] . m_bottomVec ; }
2017-08-01 14:30:58 +02:00
int m_dofOffset , m_cfgOffset ;
2019-01-03 14:26:51 +01:00
btQuaternion m_cachedRotParentToThis ; // rotates vectors in parent frame to vectors in local frame
btVector3 m_cachedRVector ; // vector from COM of parent to COM of this link, in local frame.
2020-01-08 18:05:43 +01:00
// predicted verstion
btQuaternion m_cachedRotParentToThis_interpolate ; // rotates vectors in parent frame to vectors in local frame
btVector3 m_cachedRVector_interpolate ; // vector from COM of parent to COM of this link, in local frame.
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btVector3 m_appliedForce ; // In WORLD frame
btVector3 m_appliedTorque ; // In WORLD frame
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btVector3 m_appliedConstraintForce ; // In WORLD frame
btVector3 m_appliedConstraintTorque ; // In WORLD frame
2017-08-01 14:30:58 +02:00
btScalar m_jointPos [ 7 ] ;
2020-01-08 18:05:43 +01:00
btScalar m_jointPos_interpolate [ 7 ] ;
2019-01-03 14:26:51 +01:00
//m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
//It gets set to zero after each internal stepSimulation call
2017-08-01 14:30:58 +02:00
btScalar m_jointTorque [ 6 ] ;
2019-01-03 14:26:51 +01:00
class btMultiBodyLinkCollider * m_collider ;
2017-08-01 14:30:58 +02:00
int m_flags ;
2019-01-03 14:26:51 +01:00
int m_dofCount , m_posVarCount ; //redundant but handy
2017-08-01 14:30:58 +02:00
eFeatherstoneJointType m_jointType ;
2019-01-03 14:26:51 +01:00
struct btMultiBodyJointFeedback * m_jointFeedback ;
btTransform m_cachedWorldTransform ; //this cache is updated when calling btMultiBody::forwardKinematics
const char * m_linkName ; //m_linkName memory needs to be managed by the developer/user!
const char * m_jointName ; //m_jointName memory needs to be managed by the developer/user!
const void * m_userPtr ; //m_userPtr ptr needs to be managed by the developer/user!
btScalar m_jointDamping ; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
btScalar m_jointFriction ; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
btScalar m_jointLowerLimit ; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
btScalar m_jointUpperLimit ; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
btScalar m_jointMaxForce ; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
btScalar m_jointMaxVelocity ; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
2017-08-01 14:30:58 +02:00
// ctor: set some sensible defaults
btMultibodyLink ( )
2019-01-03 14:26:51 +01:00
: m_mass ( 1 ) ,
m_parent ( - 1 ) ,
m_zeroRotParentToThis ( 0 , 0 , 0 , 1 ) ,
m_cachedRotParentToThis ( 0 , 0 , 0 , 1 ) ,
2020-01-08 18:05:43 +01:00
m_cachedRotParentToThis_interpolate ( 0 , 0 , 0 , 1 ) ,
2019-01-03 14:26:51 +01:00
m_collider ( 0 ) ,
m_flags ( 0 ) ,
m_dofCount ( 0 ) ,
m_posVarCount ( 0 ) ,
m_jointType ( btMultibodyLink : : eInvalid ) ,
m_jointFeedback ( 0 ) ,
m_linkName ( 0 ) ,
m_jointName ( 0 ) ,
m_userPtr ( 0 ) ,
m_jointDamping ( 0 ) ,
m_jointFriction ( 0 ) ,
m_jointLowerLimit ( 0 ) ,
m_jointUpperLimit ( 0 ) ,
m_jointMaxForce ( 0 ) ,
m_jointMaxVelocity ( 0 )
2017-08-01 14:30:58 +02:00
{
m_inertiaLocal . setValue ( 1 , 1 , 1 ) ;
setAxisTop ( 0 , 0. , 0. , 0. ) ;
setAxisBottom ( 0 , 1. , 0. , 0. ) ;
m_dVector . setValue ( 0 , 0 , 0 ) ;
m_eVector . setValue ( 0 , 0 , 0 ) ;
m_cachedRVector . setValue ( 0 , 0 , 0 ) ;
2020-01-08 18:05:43 +01:00
m_cachedRVector_interpolate . setValue ( 0 , 0 , 0 ) ;
2019-01-03 14:26:51 +01:00
m_appliedForce . setValue ( 0 , 0 , 0 ) ;
2017-08-01 14:30:58 +02:00
m_appliedTorque . setValue ( 0 , 0 , 0 ) ;
2019-01-03 14:26:51 +01:00
m_appliedConstraintForce . setValue ( 0 , 0 , 0 ) ;
m_appliedConstraintTorque . setValue ( 0 , 0 , 0 ) ;
//
2017-08-01 14:30:58 +02:00
m_jointPos [ 0 ] = m_jointPos [ 1 ] = m_jointPos [ 2 ] = m_jointPos [ 4 ] = m_jointPos [ 5 ] = m_jointPos [ 6 ] = 0.f ;
2019-01-03 14:26:51 +01:00
m_jointPos [ 3 ] = 1.f ; //"quat.w"
2017-08-01 14:30:58 +02:00
m_jointTorque [ 0 ] = m_jointTorque [ 1 ] = m_jointTorque [ 2 ] = m_jointTorque [ 3 ] = m_jointTorque [ 4 ] = m_jointTorque [ 5 ] = 0.f ;
m_cachedWorldTransform . setIdentity ( ) ;
}
2019-01-03 14:26:51 +01:00
// routine to update m_cachedRotParentToThis and m_cachedRVector
2017-08-01 14:30:58 +02:00
void updateCacheMultiDof ( btScalar * pq = 0 )
{
2020-01-08 18:05:43 +01:00
btScalar * pJointPos = ( pq ? pq : & m_jointPos [ 0 ] ) ;
btQuaternion & cachedRot = m_cachedRotParentToThis ;
btVector3 & cachedVector = m_cachedRVector ;
2019-01-03 14:26:51 +01:00
switch ( m_jointType )
2017-08-01 14:30:58 +02:00
{
case eRevolute :
{
2020-01-08 18:05:43 +01:00
cachedRot = btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) * m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( m_cachedRotParentToThis , m_eVector ) ;
2017-08-01 14:30:58 +02:00
break ;
}
case ePrismatic :
{
// m_cachedRotParentToThis never changes, so no need to update
2020-01-08 18:05:43 +01:00
cachedVector = m_dVector + quatRotate ( m_cachedRotParentToThis , m_eVector ) + pJointPos [ 0 ] * getAxisBottom ( 0 ) ;
2017-08-01 14:30:58 +02:00
break ;
}
case eSpherical :
{
2020-01-08 18:05:43 +01:00
cachedRot = btQuaternion ( pJointPos [ 0 ] , pJointPos [ 1 ] , pJointPos [ 2 ] , - pJointPos [ 3 ] ) * m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( cachedRot , m_eVector ) ;
2017-08-01 14:30:58 +02:00
break ;
}
case ePlanar :
{
2020-01-08 18:05:43 +01:00
cachedRot = btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) * m_zeroRotParentToThis ;
cachedVector = quatRotate ( btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) , pJointPos [ 1 ] * getAxisBottom ( 1 ) + pJointPos [ 2 ] * getAxisBottom ( 2 ) ) + quatRotate ( cachedRot , m_eVector ) ;
2017-08-01 14:30:58 +02:00
break ;
}
case eFixed :
{
2020-01-08 18:05:43 +01:00
cachedRot = m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( cachedRot , m_eVector ) ;
2017-08-01 14:30:58 +02:00
break ;
}
default :
{
//invalid type
btAssert ( 0 ) ;
}
}
2020-01-08 18:05:43 +01:00
m_cachedRotParentToThis_interpolate = m_cachedRotParentToThis ;
m_cachedRVector_interpolate = m_cachedRVector ;
2017-08-01 14:30:58 +02:00
}
2020-01-08 18:05:43 +01:00
void updateInterpolationCacheMultiDof ( )
{
btScalar * pJointPos = & m_jointPos_interpolate [ 0 ] ;
btQuaternion & cachedRot = m_cachedRotParentToThis_interpolate ;
btVector3 & cachedVector = m_cachedRVector_interpolate ;
switch ( m_jointType )
{
case eRevolute :
{
cachedRot = btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) * m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( m_cachedRotParentToThis , m_eVector ) ;
break ;
}
case ePrismatic :
{
// m_cachedRotParentToThis never changes, so no need to update
cachedVector = m_dVector + quatRotate ( m_cachedRotParentToThis , m_eVector ) + pJointPos [ 0 ] * getAxisBottom ( 0 ) ;
break ;
}
case eSpherical :
{
cachedRot = btQuaternion ( pJointPos [ 0 ] , pJointPos [ 1 ] , pJointPos [ 2 ] , - pJointPos [ 3 ] ) * m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( cachedRot , m_eVector ) ;
break ;
}
case ePlanar :
{
cachedRot = btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) * m_zeroRotParentToThis ;
cachedVector = quatRotate ( btQuaternion ( getAxisTop ( 0 ) , - pJointPos [ 0 ] ) , pJointPos [ 1 ] * getAxisBottom ( 1 ) + pJointPos [ 2 ] * getAxisBottom ( 2 ) ) + quatRotate ( cachedRot , m_eVector ) ;
break ;
}
case eFixed :
{
cachedRot = m_zeroRotParentToThis ;
cachedVector = m_dVector + quatRotate ( cachedRot , m_eVector ) ;
break ;
}
default :
{
//invalid type
btAssert ( 0 ) ;
}
}
}
2021-09-29 15:47:08 +02:00
2017-08-01 14:30:58 +02:00
} ;
2019-01-03 14:26:51 +01:00
# endif //BT_MULTIBODY_LINK_H