/*! @file FloatingBaseModel.h * @brief Implementation of Rigid Body Floating Base model data structure * * This class stores the kinematic tree described in "Rigid Body Dynamics * Algorithms" by Featherstone (download from * https://www.springer.com/us/book/9780387743141 on MIT internet) * * The tree includes an additional "rotor" body for each body. This rotor is * fixed to the parent body and has a gearing constraint. This is efficiently * included using a technique similar to what is described in Chapter 12 of * "Robot and Multibody Dynamics" by Jain. Note that this implementation is * highly specific to the case of a single rotating rotor per rigid body. Rotors * have the same joint type as their body, but with an additional gear ratio * multiplier applied to the motion subspace. The rotors associated with the * floating base don't do anything. */ #ifndef LIBBIOMIMETICS_FLOATINGBASEMODEL_H #define LIBBIOMIMETICS_FLOATINGBASEMODEL_H #include #include #include "Math/orientation_tools.h" #include "SpatialInertia.h" #include "spatial.h" #include using std::vector; using namespace ori; using namespace spatial; /*! * The state of a floating base model (base and joints) */ template struct FBModelState { EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat bodyOrientation; Vec3 bodyPosition; SVec bodyVelocity; // body coordinates DVec q; DVec qd; /*! * Print the position of the body */ void print() const { printf("position: %.3f %.3f %.3f\n", bodyPosition[0], bodyPosition[1], bodyPosition[2]); } }; /*! * The result of running the articulated body algorithm on a rigid-body floating * base model */ template struct FBModelStateDerivative { EIGEN_MAKE_ALIGNED_OPERATOR_NEW Vec3 dBodyPosition; SVec dBodyVelocity; DVec qdd; }; /*! * Class to represent a floating base rigid body model with rotors and ground * contacts. No concept of state. */ template class FloatingBaseModel { public: /*! * Initialize a floating base model with default gravity */ FloatingBaseModel() : _gravity(0, 0, -9.81) {} ~FloatingBaseModel() {} void addBase(const SpatialInertia& inertia); void addBase(T mass, const Vec3& com, const Mat3& I); int addGroundContactPoint(int bodyID, const Vec3& location, bool isFoot = false); void addGroundContactBoxPoints(int bodyId, const Vec3& dims); int addBody(const SpatialInertia& inertia, const SpatialInertia& rotorInertia, T gearRatio, int parent, JointType jointType, CoordinateAxis jointAxis, const Mat6& Xtree, const Mat6& Xrot); int addBody(const MassProperties& inertia, const MassProperties& rotorInertia, T gearRatio, int parent, JointType jointType, CoordinateAxis jointAxis, const Mat6& Xtree, const Mat6& Xrot); void check(); T totalRotorMass(); T totalNonRotorMass(); /*! * Get vector of parents, where parents[i] is the parent body of body i * @return Vector of parents */ const std::vector& getParentVector() { return _parents; } /*! * Get vector of body spatial inertias * @return Vector of body spatial inertias */ const std::vector, Eigen::aligned_allocator>>& getBodyInertiaVector() { return _Ibody; } /*! * Get vector of rotor spatial inertias * @return Vector of rotor spatial inertias */ const std::vector, Eigen::aligned_allocator>>& getRotorInertiaVector() { return _Irot; } /*! * Set the gravity */ void setGravity(Vec3& g) { _gravity = g; } /*! * Set the flag to enable computing contact info for a given contact point * @param gc_index : index of contact point * @param flag : enable/disable contact calculation */ void setContactComputeFlag(size_t gc_index, bool flag) { _compute_contact_info[gc_index] = flag; } DMat invContactInertia(const int gc_index, const D6Mat& force_directions); T invContactInertia(const int gc_index, const Vec3& force_ics_at_contact); T applyTestForce(const int gc_index, const Vec3& force_ics_at_contact, FBModelStateDerivative& dstate_out); T applyTestForce(const int gc_index, const Vec3& force_ics_at_contact, DVec& dstate_out); void addDynamicsVars(int count); void resizeSystemMatricies(); /*! * Update the state of the simulator, invalidating previous results * @param state : the new state */ void setState(const FBModelState& state) { _state = state; _biasAccelerationsUpToDate = false; _compositeInertiasUpToDate = false; resetCalculationFlags(); } /*! * Mark all previously calculated values as invalid */ void resetCalculationFlags() { _articulatedBodiesUpToDate = false; _kinematicsUpToDate = false; _forcePropagatorsUpToDate = false; _qddEffectsUpToDate = false; _accelerationsUpToDate = false; } /*! * Update the state derivative of the simulator, invalidating previous results. * @param dState : the new state derivative */ void setDState(const FBModelStateDerivative& dState) { _dState = dState; _accelerationsUpToDate = false; } Vec3 getPosition(const int link_idx, const Vec3 & local_pos); Vec3 getPosition(const int link_idx); Mat3 getOrientation(const int link_idx); Vec3 getLinearVelocity(const int link_idx, const Vec3& point); Vec3 getLinearVelocity(const int link_idx); Vec3 getLinearAcceleration(const int link_idx, const Vec3& point); Vec3 getLinearAcceleration(const int link_idx); Vec3 getAngularVelocity(const int link_idx); Vec3 getAngularAcceleration(const int link_idx); void forwardKinematics(); void biasAccelerations(); void compositeInertias(); void forwardAccelerationKinematics(); void contactJacobians(); DVec generalizedGravityForce(); DVec generalizedCoriolisForce(); DMat massMatrix(); DVec inverseDynamics(const FBModelStateDerivative& dState); void runABA(const DVec& tau, FBModelStateDerivative& dstate); size_t _nDof = 0; Vec3 _gravity; vector _parents; vector _gearRatios; vector _d, _u; vector _jointTypes; vector _jointAxes; vector, Eigen::aligned_allocator>> _Xtree, _Xrot; vector, Eigen::aligned_allocator>> _Ibody, _Irot; vector _bodyNames; size_t _nGroundContact = 0; vector _gcParent; vector> _gcLocation; vector _footIndicesGC; vector> _pGC; vector> _vGC; vector _compute_contact_info; /*! * Get the mass matrix for the system */ const DMat& getMassMatrix() const { return _H; } /*! * Get the gravity term (generalized forces) */ const DVec& getGravityForce() const { return _G; } /*! * Get the coriolis term (generalized forces) */ const DVec& getCoriolisForce() const { return _Cqd; } /// BEGIN ALGORITHM SUPPORT VARIABLES FBModelState _state; FBModelStateDerivative _dState; vectorAligned> _v, _vrot, _a, _arot, _avp, _avprot, _c, _crot, _S, _Srot, _fvp, _fvprot, _ag, _agrot, _f, _frot; vectorAligned> _U, _Urot, _Utot, _pA, _pArot; vectorAligned> _externalForces; vectorAligned> _IC; vectorAligned> _Xup, _Xa, _Xuprot, _IA, _ChiUp; DMat _H, _C; DVec _Cqd, _G; vectorAligned> _J; vectorAligned> _Jdqd; vectorAligned> _Jc; vectorAligned> _Jcdqd; bool _kinematicsUpToDate = false; bool _biasAccelerationsUpToDate = false; bool _accelerationsUpToDate = false; bool _compositeInertiasUpToDate = false; void updateArticulatedBodies(); void updateForcePropagators(); void udpateQddEffects(); /*! * Set all external forces to zero */ void resetExternalForces() { for (size_t i = 0; i < _nDof; i++) { _externalForces[i] = SVec::Zero(); } } bool _articulatedBodiesUpToDate = false; bool _forcePropagatorsUpToDate = false; bool _qddEffectsUpToDate = false; DMat _qdd_from_base_accel; DMat _qdd_from_subqdd; Eigen::ColPivHouseholderQR> _invIA5; }; #endif // LIBBIOMIMETICS_FLOATINGBASEMODEL_H