// ------------------------------------------------------------------------------- // Copyright (c) 2012, Junggon Kim // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ------------------------------------------------------------------------------- //================================================================================ // GBody: class for rigid bodies // // junggon@gmail.com //================================================================================ #ifndef _GEAR_RIGID_BODY_ #define _GEAR_RIGID_BODY_ #include #include "gelement.h" #include "gconstraint_jointloop.h" #include "liegroup.h" #include "rmatrix3j.h" class GJoint; class GForce; //============================================================= // GBody //============================================================= class GBody: public GElement { public: std::list pJoints; // attached joint elements std::list pForces; // attached force elements SE3 T_global; // SE3: {global} --> {body} // --------- parent/child relation in the (virtual) tree topology system ------------- GJoint *pBaseJoint; // pBaseJoint->pRightBody = this GBody *pParentBody; // pointer to parent body, pParentBody = pBaseJoint->pLeftBody std::list pChildBodies; // pointers to child bodies, pChildBodies[]->pParentBody = this SE3 T, invT; // T = SE3: pParentBody->{body} --> {body}, invT = Inv(T) int bjDOF; // DOF of the base joint (=pBaseJoint->GetDOF()) RMatrix S, dS; // properties of the base joint(pBaseJoint), but viewed in {body} frame se3 Sdq, dSdq, Sddq, DSdqDt; RMatrix Jacobian; // System Jacobian that maps the velocity of the system coordinates to the body's velocity (tree topology assumed) GConstraintJointLoop fwdJointChain; // forward joint chain from ground to the body // --------- geometric dynamics ------------------------------------------------------ // quantities to be set by user Inertia I; // generalized inertia (w.r.t. {body}) dse3 Fe; // generalized force acting on body from external environment (w.r.t. {body}) // internal variables se3 V; // generalized body velocity of {body} relative to {global} but viewed in {body}. V = inv(T_global)*d(T_global)/dt. se3 dV; // generalized body acceleration. V = dV/dt. dse3 F; // generalized force acting on body through pBaseJoint and viewed in {body}. AInertia aI; // articulated body inertia dse3 aB; // bias force: F = aI*dV + aB se3 eta; RMatrix aI_S; RMatrix Psi; AInertia Pi; dse3 beta; // --------- derivatives of the geometric dynamics ----------------------------------- // --------- derivative of the geometric dynamics w.r.t. an arbitrary scalar variable p ------ // 'D' means 'partial derivative' // prerequisite: // - set bnzD[q,dq]Dp // - set pBaseJoint->pCoordinates[]->(DqDp,DdqDp) // - set pBaseJoint->pCoordinates[]->DddqDp if pBaseJoint->isPrescribed() == true // - set pBaseJoint->pCoordinates[]->DtauDp if pBaseJoint->isPrescribed() == false // - set bnzD[S,h,Fe,I]Dp // - set DSDp, DdSDp, DhDp, DFeDp, DIDp // DSDp, DdSDp, DhDp are related with each other, and cannot be set with arbitrary values. // For example, if p == pBaseJoint->pCoordinates[i]->q then DhDp = S[i]. // variables to be set by user RMatrix DSDp, DdSDp; // DS/Dp, D(DS/Dt)/Dp se3 DhDp; // invT*DT/Dp dse3 DFeDp; Inertia DIDp; bool bnzDqDp, bnzDdqDp; bool bnzDSDp, bnzDdSDp, bnzDhDp, bnzDFeDp, bnzDIDp; // --------- auxiliary --------------------------------------------------------------- bool bDpAlien; // see set_bDpAlien(...) below. // internal variables se3 DVDp; se3 DdVDp; dse3 DFDp; AInertia DaIDp; dse3 DaBDp; se3 DetaDp; RMatrix DPsiDp; AInertia DPiDp; dse3 DbetaDp; public: GBody(); virtual ~GBody() {} public: virtual void clear(); virtual bool getReady(); virtual std::string getInfoStr(); // --------- set methods ------------------------------------------------------------- // mass properties void setMass(const gReal &mass_, const Vec3 &p_ = Vec3(0,0,0)); // point mass at p in {body} void setMass(const gReal &mass_, const gReal &ixx_, const gReal &iyy_, const gReal &izz_, const gReal &ixy_, const gReal &ixz_, const gReal &iyz_, const SE3 &T_ref_ = SE3()); void addMass(const gReal &mass_, const gReal &ixx_, const gReal &iyy_, const gReal &izz_, const gReal &ixy_, const gReal &ixz_, const gReal &iyz_, const SE3 &T_ref_ = SE3()); void extractMass(const gReal &mass_, const gReal &ixx_, const gReal &iyy_, const gReal &izz_, const gReal &ixy_, const gReal &ixz_, const gReal &iyz_, const SE3 &T_ref_ = SE3()); // mass_ = mass of the body // inertia = [ixx_, ixy_, ixz_] = the 3 x 3 inertia matrix w.r.t. {ref} // [ixy_, iyy_, iyz_] // [ixz_, iyz_, izz_] // ** Be cautious on the ordering, (ixx_, iyy_, izz_, ixy_, ixz_, iyz_). // T_ref_ = SE3: {body} -> {ref} void moveMass(const SE3 &T_ref_new_); // current mass and inertia of the body will be moved to {ref_new} // T_ref_new_ = SE3: {body} -> {ref_new} // external force void setExternalForceLocally(const dse3 &Fe_local_); // Fe_local_ = external generalized force w.r.t. {body} void setExternalForceGlobally(const dse3 &Fe_global_); // Fe_global_ = external generalized force w.r.t. {global} void setExternalForceGlobally(const Vec3 &p_, const Vec3 &fg_); // set external force fg_ (w.r.t. {global}) acting on the body at p_ (w.r.t. {body}) void addExternalForceLocally(const dse3 &Fe_local_); void addExternalForceGlobally(const dse3 &Fe_global_); void addExternalForceGlobally(const Vec3 &p_, const Vec3 &fg_); // variables for differentiating dynamics void set_DSDp(const RMatrix &DSDp_) { DSDp = DSDp_; } void set_DdSDp(const RMatrix &DdSDp_) { DdSDp = DdSDp_; } void set_DhDp(const se3 &DhDp_) { DhDp = DhDp_; } void set_DFeDp(const dse3 &DFeDp_) { DFeDp = DFeDp_; } void set_DIDp(const Inertia &DIDp_) { DIDp = DIDp_; } void set_bnzAll(bool bnzAll_) { bnzDqDp = bnzDdqDp = bnzDSDp = bnzDdSDp = bnzDhDp = bnzDFeDp = bnzDIDp = bnzAll_; } void set_bnzDqDp(bool bnzDqDp_) { bnzDqDp = bnzDqDp_; } void set_bnzDdqDp(bool bnzDdqDp_) { bnzDdqDp = bnzDdqDp_; } void set_bnzDSDp(bool bnzDSDp_) { bnzDSDp = bnzDSDp_; } void set_bnzDdSDp(bool bnzDdSDp_) { bnzDdSDp = bnzDdSDp_; } void set_bnzDhDp(bool bnzDhDp_) { bnzDhDp = bnzDhDp_; } void set_bnzDFeDp(bool bnzDFeDp_) { bnzDFeDp = bnzDFeDp_; } void set_bnzDIDp(bool bnzDIDp_) { bnzDIDp = bnzDIDp_; } // --------- get methods ------------------------------------------------------------- // position and orientation SE3 &getPoseGlobal() { return T_global; } // return the global pose (position and orientation) of {body} (equal to getGlobalTransform()) SE3 getPoseGlobal(const SE3 &T_); // return the global pose of {tmp} where T_ = SE(3): {body} --> {tmp} Vec3 getPositionGlobal(); // return the global position of {body}'s origin Vec3 getPositionGlobal(const Vec3 &p_); // return the global position of a local body point p_ (p_ = a position vector w.r.t. {body}) SO3 getOrientationGlobal(); // return the global orientation of {body} SO3 getOrientationGlobal(const SO3 &R_); // return the global orientation of {tmp} where R_ = SO(3): {body} --> {tmp} // velocity Vec3 getVelocityLinearGlobal(); // return the linear velocity of the body at the origin of {body} w.r.t. {global} Vec3 getVelocityLinearGlobal(const Vec3 &p_); // return the linear velocity of the body at p_ w.r.t. {global}, where p_ is a relative position vector w.r.t {body} Vec3 getVelocityAngularGlobal(); // return the angular velocity of the body w.r.t. {global} se3 getVelocityGlobal(); // return se3(getVelocityAngularGlobal(), getVelocityLinearGlobal()) se3 getVelocityGlobal(const Vec3 &p_); // return se3(getVelocityAngularGlobal(), getVelocityLInearGlobal(p_)) // acceleration ** To get a relative acceleration of the body to the ground, the acceleration of the ground should be extracted. ** Vec3 getAccelerationLinearGlobal(); // return the linear acceleration of the body at the origin of {body} w.r.t. {global} Vec3 getAccelerationLinearGlobal(const Vec3 &p_); // return the linear acceleration of the body at p_ w.r.t. {global}, where p_ is a relative position vector w.r.t. {body} Vec3 getAccelerationAngularGlobal(); // return the angular acceleration of the body w.r.t. {global} se3 getAccelerationGlobal(); // return se3(getAccelerationAngularGlobal(), getAccelerationLinearGlobal()) se3 getAccelerationGlobal(const Vec3 &p_); // return se3(getAccelerationAngularGlobal(), getAccelerationLinearGlobal(p_)) // mass, center of mass gReal getMass(); // return mass Vec3 getPositionCOM(); // return the position of the body's c.o.m. w.r.t. {body} Vec3 getPositionCOMGlobal(); // return the position of the body's c.o.m. w.r.t. {global} Vec3 getVelocityCOMGlobal(); // return the velocity of the body at c.o.m. w.r.t. {global} Vec3 getAccelerationCOMGlobal(); // return the acceleration of the body at c.o.m. w.r.t. {global} // momentum dse3 getMomentum(); // return the generalized momentum w.r.t. {body} dse3 getMomentumGlobal(); // return the generalized momentum w.r.t. {global} // derivative of the center of mass Vec3 getDerivative_PositionCOMGlobal_Dq(GCoordinate *pCoordinate_); // return the derivative of the position of the center of mass in {global} w.r.t. pCoordinate_->q // Prerequisites: 1. fwdJointChain.M1 = identity and fwdJointChain.jointLoopConstraintType = JOINTLOOP_ORIENTATION_POSITION. // 2. fwdJointChain.update_J(); // derivative of the momentum dse3 getDerivative_MomentumGlobal_Dq(GCoordinate *pCoordinate_); dse3 getDerivative_MomentumGlobal_Ddq(GCoordinate *pCoordinate_); // return the derivative of the generalized momentum in {global} w.r.t. pCoordinate_->q // return the derivative of the generalized momentum in {global} w.r.t. pCoordinate_->dq // Prerequisites: 1. fwdJointChain.M1 = identity and fwdJointChain.jointLoopConstraintType = JOINTLOOP_ORIENTATION_POSITION. // 2. fwdJointChain.update_J(); // --------- methods for geometric kinematics and dynamics --------------------------- // load base joint information void load_base_joint_info(); // import S, dS, Sdq, dSdq, Sddq, DSdqDt from pBaseJoint->(S,dS,...) // update base joint information void update_base_joint_info(); // update S, dS, Sdq, dSdq, Sddq, DSdqDt with pBaseJoint->(S,dS,...) if needed // geometric dynamics void initExternalForce() { Fe.SetZero(); } void neDynaRecursion_a(); void neDynaRecursion_b(); void fsDynaRecursion_a(); void fsDynaRecursion_b(); void fsDynaRecursion_c(); dse3 getTransformed_F(); // return F viewed in pParentBody->{body} AInertia getTransformed_aI(); // return aI viewed in pParentBody->{body} dse3 getTransformed_aB(); // return aB viewed in pParentBody->{body} // derivative of the dynamics void neDynaRecursion_DaDp(); void neDynaRecursion_DbDp(); void fsDynaRecursion_DaDp(); void fsDynaRecursion_DbDp(); void fsDynaRecursion_DcDp(); dse3 getTransformed_DFDp(); AInertia getTransformed_DaIDp(); dse3 getTransformed_DaBDp(); // set differentiating variable void setDifferentiatingVariable_Dq(GCoordinate *pCoordinate_); void setDifferentiatingVariable_Ddq(GCoordinate *pCoordinate_); void setDifferentiatingVariable_Dddq(GCoordinate *pCoordinate_); void setDifferentiatingVariable_Dtau(GCoordinate *pCoordinate_); void setDifferentiatingVariable_DFe(GBody *pBody_, int idx_); void set_bDpAlien(bool bDpAlien_) { bDpAlien = bDpAlien_; } // Set 'bDpAlien = true' for fast computation of DddqDp or DtauDp // in case that // DVDp = DetaDp = DaIDp = DPsiDp = DPiDp = 0, // DSDp = DdSDp = DhDp = DIDp = 0, // and DFeDp, DdVDp, DFDp, DaBDp, DbetaDp are nonzero. // --------- sub-functions for geometric kinematics and dynamics --------------------- virtual void update_T(); virtual void update_V(); virtual void update_eta(); virtual void update_dV(bool b_update_); // set b_update_ = true to update dV with new pBaseJoint->get_ddq() virtual void update_F(); virtual void update_F_fs(); virtual void update_aI(); virtual void update_aB(); virtual void update_Psi(); virtual void update_Pi(); virtual void update_beta(); virtual void update_tau(); virtual void update_ddq(); void set_eta_zero(); void update_aB_zeroV_zeroeta(); void update_beta_zeroeta(); virtual void update_DVDp(); virtual void update_DetaDp(); virtual void update_DdVDp(); virtual void update_DFDp(); virtual void update_DFDp_fs(); virtual void update_DaIDp(); virtual void update_DaBDp(); virtual void update_DPsiDp(); virtual void update_DPiDp(); virtual void update_DbetaDp(); virtual void update_DtauDp(); virtual void update_DddqDp(); se3 get_S(GCoordinate *pCoordinate_); // return i-th column of S where pBaseJoint->pCoordinates[i] = pCoordinate_. se3 get_dS(GCoordinate *pCoordinate_); // return i-th column of dS where pBaseJoint->pCoordinates[i] = pCoordinate_. RMatrix get_DSDq(GCoordinate *pCoordinate_); // return DS/Dq where q = pCoordinate_->q. RMatrix get_DdSDq(GCoordinate *pCoordinate_); // return D(DS/Dt)/Dq where q = pCoordinate_->q. RMatrix get_DdSDdq(GCoordinate *pCoordinate_); // return D(DS/Dt)/Ddq where dq = pCoordinate_->dq. bool isIncluded(GCoordinate *pCoordinate_); // return true if pCoordinate_ is included pBaseJoint->pCoordinates. }; #endif