1 #define BIORBD_API_EXPORTS
2 #include "RigidBody/Joints.h"
4 #include <rbdl/rbdl_utils.h>
5 #include <rbdl/Kinematics.h>
6 #include <rbdl/Dynamics.h>
7 #include "Utils/String.h"
8 #include "Utils/Quaternion.h"
9 #include "Utils/Matrix.h"
10 #include "Utils/Error.h"
11 #include "Utils/RotoTrans.h"
12 #include "Utils/Rotation.h"
13 #include "Utils/SpatialVector.h"
14 #include "RigidBody/GeneralizedCoordinates.h"
15 #include "RigidBody/GeneralizedVelocity.h"
16 #include "RigidBody/GeneralizedAcceleration.h"
17 #include "RigidBody/GeneralizedTorque.h"
18 #include "RigidBody/Segment.h"
19 #include "RigidBody/Markers.h"
20 #include "RigidBody/NodeSegment.h"
21 #include "RigidBody/MeshFace.h"
22 #include "RigidBody/Mesh.h"
23 #include "RigidBody/SegmentCharacteristics.h"
24 #include "RigidBody/Contacts.h"
27 RigidBodyDynamics::
Model(),
28 m_segments(std::make_shared<std::vector<biorbd::rigidbody::
Segment>>()),
29 m_nbRoot(std::make_shared<unsigned int>(0)),
30 m_nbDof(std::make_shared<unsigned int>(0)),
31 m_nbQ(std::make_shared<unsigned int>(0)),
32 m_nbQdot(std::make_shared<unsigned int>(0)),
33 m_nbQddot(std::make_shared<unsigned int>(0)),
34 m_nRotAQuat(std::make_shared<unsigned int>(0)),
35 m_isKinematicsComputed(std::make_shared<bool>(false)),
36 m_totalMass(std::make_shared<double>(0))
42 RigidBodyDynamics::
Model(other),
43 m_segments(other.m_segments),
44 m_nbRoot(other.m_nbRoot),
45 m_nbDof(other.m_nbDof),
47 m_nbQdot(other.m_nbQdot),
48 m_nbQddot(other.m_nbQddot),
49 m_nRotAQuat(other.m_nRotAQuat),
50 m_isKinematicsComputed(other.m_isKinematicsComputed),
51 m_totalMass(other.m_totalMass)
70 static_cast<RigidBodyDynamics::Model&
>(*this) = other;
72 for (
unsigned int i=0; i<other.
m_segments->size(); ++i)
73 (*m_segments)[i] = (*other.
m_segments)[i].DeepCopy();
76 *m_nbQ = *other.
m_nbQ;
93 std::vector<biorbd::utils::String> names;
94 for (
unsigned int i = 0; i < nbSegment(); ++i) {
95 for (
unsigned int j = 0; j < segment(i).nbDof(); ++j) {
96 names.push_back(segment(i).name() +
"_" + segment(i).nameDof(j));
100 for (
unsigned int i = 0; i < nbSegment(); ++i) {
101 if (segment(i).isRotationAQuaternion()) {
102 names.push_back(segment(i).name() +
"_" + segment(i).nameDof(3));
130 const std::vector<biorbd::utils::Range>& QRanges,
131 const std::vector<biorbd::utils::Range>& QDotRanges,
132 const std::vector<biorbd::utils::Range>& QDDotRanges,
134 const RigidBodyDynamics::Math::SpatialTransform& centreOfRotation,
138 *
this, segmentName, parentName, translationSequence,
139 rotationSequence, QRanges, QDotRanges, QDDotRanges, characteristics,
140 centreOfRotation, forcePlates);
141 if (this->GetBodyId(parentName.c_str()) == std::numeric_limits<unsigned int>::max())
142 *m_nbRoot += tp.
nbDof();
143 *m_nbDof += tp.
nbDof();
151 *m_totalMass += characteristics.mMass;
152 m_segments->push_back(tp);
159 const std::vector<biorbd::utils::Range>& QRanges,
160 const std::vector<biorbd::utils::Range>& QDotRanges,
161 const std::vector<biorbd::utils::Range>& QDDotRanges,
163 const RigidBodyDynamics::Math::SpatialTransform& cor,
167 *
this, segmentName, parentName, seqR, QRanges, QDotRanges, QDDotRanges,
168 characteristics, cor, forcePlates);
169 if (this->GetBodyId(parentName.c_str()) == std::numeric_limits<unsigned int>::max())
170 *m_nbRoot += tp.
nbDof();
171 *m_nbDof += tp.
nbDof();
173 *m_totalMass += characteristics.mMass;
174 m_segments->push_back(tp);
186 gravity = newGravity;
191 return (*m_segments)[idx];
196 return segment(
static_cast<unsigned int>(GetBodyBiorbdId(name.c_str())));
201 return static_cast<unsigned int>(m_segments->size());
205 std::vector<std::vector<biorbd::utils::SpatialVector>> &spatialVector,
206 unsigned int frame)
const
209 std::vector<biorbd::utils::SpatialVector> sv2;
210 for (
auto vec : spatialVector)
211 sv2.push_back(vec[frame]);
214 return dispatchedForce(sv2);
218 std::vector<biorbd::utils::SpatialVector> &sv)
const{
220 std::vector<RigidBodyDynamics::Math::SpatialVector> sv_out;
224 sv_out.push_back(sv_zero);
227 for (
auto segment : *m_segments){
228 unsigned int nbDof = segment.nbDof();
231 for (
unsigned int i=0; i<nbDof-1; ++i)
232 sv_out.push_back(sv_zero);
233 if (segment.platformIdx() >= 0){
234 sv_out.push_back(sv[
static_cast<unsigned int>(segment.platformIdx())]);
237 sv_out.push_back(sv_zero);
246 for (
int i=0; i<static_cast<int>(m_segments->size()); ++i)
247 if (!(*m_segments)[
static_cast<unsigned int>(i)].name().compare(segmentName))
255 UpdateKinematicsCustom (&Q,
nullptr,
nullptr);
256 return allGlobalJCS();
261 std::vector<biorbd::utils::RotoTrans> out;
262 for (
unsigned int i=0; i<m_segments->size(); ++i)
263 out.push_back(globalJCS(i));
271 UpdateKinematicsCustom (&Q,
nullptr,
nullptr);
272 return globalJCS(name);
280 UpdateKinematicsCustom (&Q,
nullptr,
nullptr);
281 return globalJCS(idx);
286 return globalJCS(
static_cast<unsigned int>(GetBodyBiorbdId(name)));
290 unsigned int idx)
const
292 return CalcBodyWorldTransformation((*m_segments)[idx].
id());
296 std::vector<biorbd::utils::RotoTrans> out;
298 for (
unsigned int i=0; i<m_segments->size(); ++i)
299 out.push_back(localJCS(i));
304 return localJCS(
static_cast<unsigned int>(GetBodyBiorbdId(name.c_str())));
307 return (*m_segments)[idx].localJCS();
313 const std::vector<biorbd::rigidbody::NodeSegment>& v,
317 UpdateKinematicsCustom(&Q,
nullptr,
nullptr);
326 std::vector<biorbd::rigidbody::NodeSegment> out;
327 for (
unsigned int i = 0; i < marks.
nbMarkers(); ++i) {
332 out.push_back(projectPoint(Q, tp,
false));
349 UpdateKinematicsCustom (&Q);
355 true,
true, axesToRemove,
static_cast<int>(GetBodyId(segmentName.c_str())));
358 return projectPoint(Q, node,
false);
376 UpdateKinematicsCustom (&Q);
388 CalcMatRotJacobian(Q, GetBodyId(node.
parent().c_str()), RigidBodyDynamics::Math::Matrix3d::Identity(), JCor,
false);
389 for (
unsigned int n=0; n<3; ++n)
391 G_tp += JCor.block(n*3,0,3,nbQ()) * node(n);
397 return biorbd::utils::Matrix::Zero(3,nbQ());
412 return projectPointJacobian(Q, p, updateKin);
417 const std::vector<biorbd::rigidbody::NodeSegment> &v,
421 const std::vector<biorbd::rigidbody::NodeSegment>& tp(projectPoint(Q, v, updateKin));
424 std::vector<biorbd::utils::Matrix> G;
426 for (
unsigned int i=0; i<tp.size(); ++i){
435 const unsigned int segmentIdx,
440 UpdateKinematicsCustom (&Q);
442 return CalcBodyWorldTransformation(segmentIdx);
446 const unsigned int segmentIdx)
const
448 if (segmentIdx >= this->fixed_body_discriminator) {
449 unsigned int fbody_id = segmentIdx - this->fixed_body_discriminator;
450 unsigned int parent_id = this->mFixedBodies[fbody_id].mMovableParent;
452 this->X_base[parent_id].E.transpose(),
453 this->X_base[parent_id].r);
455 this->mFixedBodies[fbody_id].mParentTransform.E.transpose(),
456 this->mFixedBodies[fbody_id].mParentTransform.r);
458 return RigidBodyDynamics::Math::SpatialTransform (transfo_tp.
rot(), transfo_tp.
trans());
461 return RigidBodyDynamics::Math::SpatialTransform (this->X_base[segmentIdx].E.transpose(), this->X_base[segmentIdx].r);
472 UpdateKinematicsCustom(&Q);
476 const std::vector<biorbd::rigidbody::NodeSegment>& com_segment(CoMbySegment(Q,
true));
478 for (
unsigned int i=0; i<com_segment.size(); ++i)
479 com += (*m_segments)[i].characteristics().mMass * com_segment[i];
482 com = com/this->mass();
493 return CalcAngularMomentum(Q, Qdot, updateKin);
500 RigidBodyDynamics::Math::MatrixNd massMatrix(nbQ(), nbQ());
501 massMatrix.setZero();
502 RigidBodyDynamics::CompositeRigidBodyAlgorithm(*
this, Q, massMatrix, updateKin);
511 UpdateKinematicsCustom(&Q, &Qdot);
518 for (
auto segment : *m_segments){
520 RigidBodyDynamics::CalcPointJacobian(
521 *
this, Q, GetBodyId(segment.name().c_str()),
522 segment.characteristics().mCenterOfMass, Jac,
false);
523 com_dot += ((Jac*Qdot) * segment.characteristics().mMass);
526 com_dot = com_dot/mass();
536 biorbd::utils::Scalar mass;
537 RigidBodyDynamics::Math::Vector3d com, com_ddot;
538 RigidBodyDynamics::Utils::CalcCenterOfMass(
539 *
this, Q, Qdot, &Qddot, mass, com,
nullptr, &com_ddot,
540 nullptr,
nullptr,
true);
553 UpdateKinematicsCustom(&Q,
nullptr,
nullptr);
560 for (
auto segment : *m_segments){
562 RigidBodyDynamics::CalcPointJacobian(
563 *
this, Q, GetBodyId(segment.name().c_str()),
564 segment.characteristics().mCenterOfMass, Jac,
false);
565 JacTotal += segment.characteristics().mMass*Jac;
569 JacTotal /= this->mass();
580 UpdateKinematicsCustom (&Q);
583 std::vector<biorbd::rigidbody::NodeSegment> out;
584 for (
unsigned int i=0; i<m_segments->size(); ++i){
585 out.push_back(CoMbySegment(Q,i,
false));
594 std::vector<biorbd::rigidbody::NodeSegment> allCoM(CoMbySegment(Q, updateKin));
596 for (
unsigned int i=0; i<allCoM.size(); ++i){
597 CoMs.block(0, i, 3, 1) = allCoM[i];
605 const unsigned int idx,
610 UpdateKinematicsCustom (&Q);
612 return RigidBodyDynamics::CalcBodyToBaseCoordinates(
613 *
this, Q, (*m_segments)[idx].
id(),
614 (*m_segments)[idx].characteristics().mCenterOfMass,
false);
624 UpdateKinematicsCustom (&Q);
627 std::vector<biorbd::utils::Vector3d> out;
628 for (
unsigned int i=0; i<m_segments->size(); ++i){
629 out.push_back(CoMdotBySegment(Q,Qdot,i,
false));
638 const unsigned int idx,
642 return CalcPointVelocity(
643 *
this, Q, Qdot, (*m_segments)[idx].
id(),
644 (*m_segments)[idx].characteristics().mCenterOfMass,updateKin);
655 UpdateKinematicsCustom (&Q);
658 std::vector<biorbd::utils::Vector3d> out;
659 for (
unsigned int i=0; i<m_segments->size(); ++i){
660 out.push_back(CoMddotBySegment(Q,Qdot,Qddot,i,
false));
670 const unsigned int idx,
675 UpdateKinematicsCustom (&Q);
677 return RigidBodyDynamics::CalcPointAcceleration(
678 *
this, Q, Qdot, Qddot, (*m_segments)[idx].
id(),
679 (*m_segments)[idx].characteristics().mCenterOfMass,
false);
687 UpdateKinematicsCustom (&Q);
689 std::vector<std::vector<biorbd::utils::Vector3d>> v;
692 const std::vector<biorbd::utils::RotoTrans>& RT(allGlobalJCS());
695 for (
unsigned int i=0; i<nbSegment(); ++i)
696 v.push_back(meshPoints(RT,i));
706 UpdateKinematicsCustom (&Q);
710 const std::vector<biorbd::utils::RotoTrans>& RT(allGlobalJCS());
712 return meshPoints(RT,i);
715 std::vector<biorbd::utils::Matrix>
721 UpdateKinematicsCustom (&Q);
723 const std::vector<biorbd::utils::RotoTrans>& RT(allGlobalJCS());
725 std::vector<biorbd::utils::Matrix> all_points;
726 for (
unsigned int i=0; i<m_segments->size(); ++i) {
728 for (
unsigned int j=0; j<mesh(i).nbVertex(); ++j){
731 mat.block(0, j, 3, 1) = tp;
733 all_points.push_back(mat);
738 const std::vector<biorbd::utils::RotoTrans> &RT,
739 unsigned int i)
const{
742 std::vector<biorbd::utils::Vector3d> v;
743 for (
unsigned int j=0; j<mesh(i).nbVertex(); ++j){
754 std::vector<std::vector<biorbd::rigidbody::MeshFace>> v_all;
755 for (
unsigned int j=0; j<nbSegment(); ++j)
756 v_all.push_back(meshFaces(j));
761 return mesh(idx).faces();
766 std::vector<biorbd::rigidbody::Mesh> segmentOut;
767 for (
unsigned int i=0; i<nbSegment(); ++i)
768 segmentOut.push_back(mesh(i));
774 return segment(idx).characteristics().mesh();
782 RigidBodyDynamics::Math::Vector3d com, angular_momentum;
783 biorbd::utils::Scalar mass;
788 UpdateKinematicsCustom (&Q, &Qdot);
790 RigidBodyDynamics::Utils::CalcCenterOfMass(
791 *
this, Q, Qdot,
nullptr, mass, com,
nullptr,
nullptr,
792 &angular_momentum,
nullptr,
false);
793 return angular_momentum;
802 RigidBodyDynamics::Math::Vector3d com, angular_momentum;
803 biorbd::utils::Scalar mass;
808 UpdateKinematicsCustom (&Q);
810 RigidBodyDynamics::Utils::CalcCenterOfMass(
811 *
this, Q, Qdot, &Qddot, mass, com,
nullptr,
nullptr,
812 &angular_momentum,
nullptr,
false);
814 return angular_momentum;
822 UpdateKinematicsCustom (&Q, &Qdot);
825 biorbd::utils::Scalar mass;
826 RigidBodyDynamics::Math::Vector3d com;
827 RigidBodyDynamics::Utils::CalcCenterOfMass (
828 *
this, Q, Qdot,
nullptr, mass, com,
nullptr,
829 nullptr,
nullptr,
nullptr,
false);
830 RigidBodyDynamics::Math::SpatialTransform X_to_COM (RigidBodyDynamics::Math::Xtrans(com));
832 std::vector<biorbd::utils::Vector3d> h_segment;
833 for (
unsigned int i = 1; i < this->mBodies.size(); i++) {
834 this->Ic[i] = this->I[i];
835 this->hc[i] = this->Ic[i].toMatrix() * this->v[i];
837 RigidBodyDynamics::Math::SpatialVector h = this->X_lambda[i].applyTranspose (this->hc[i]);
838 if (this->lambda[i] != 0) {
842 h = this->X_lambda[j].applyTranspose (h);
843 }
while (this->lambda[j]!=0);
845 h = X_to_COM.applyAdjoint (h);
859 UpdateKinematicsCustom (&Q, &Qdot, &Qddot);
862 biorbd::utils::Scalar mass;
863 RigidBodyDynamics::Math::Vector3d com;
864 RigidBodyDynamics::Utils::CalcCenterOfMass (*
this, Q, Qdot, &Qddot, mass, com,
nullptr,
nullptr,
nullptr,
nullptr,
false);
865 RigidBodyDynamics::Math::SpatialTransform X_to_COM (RigidBodyDynamics::Math::Xtrans(com));
867 std::vector<biorbd::utils::Vector3d> h_segment;
868 for (
unsigned int i = 1; i < this->mBodies.size(); i++) {
869 this->Ic[i] = this->I[i];
870 this->hc[i] = this->Ic[i].toMatrix() * this->v[i];
872 RigidBodyDynamics::Math::SpatialVector h = this->X_lambda[i].applyTranspose (this->hc[i]);
873 if (this->lambda[i] != 0) {
877 h = this->X_lambda[j].applyTranspose (h);
878 }
while (this->lambda[j]!=0);
880 h = X_to_COM.applyAdjoint (h);
903 unsigned int cmpQuat(0);
904 unsigned int cmpDof(0);
905 for (
unsigned int i=0; i<nbSegment(); ++i){
910 Q(Q.size()-*m_nRotAQuat+cmpQuat),
911 Q.block(cmpDof+segment_i.
nbDofTrans(), 0, 3, 1),
915 QDotOut.block(cmpDof, 0, segment_i.
nbDofTrans(), 1)
916 = QDot.block(cmpDof, 0, segment_i.
nbDofTrans(), 1);
920 QDotOut.block(cmpDof+segment_i.
nbDofTrans(), 0, 3, 1) = quat_tp.block(1,0,3,1);
921 QDotOut(Q.size()-*m_nRotAQuat+cmpQuat) = quat_tp(0);
928 QDotOut.block(cmpDof, 0, segment_i.
nbDof(), 1) = QDot.block(cmpDof, 0, segment_i.
nbDof(), 1);
930 cmpDof += segment_i.
nbDof();
939 std::vector<biorbd::utils::SpatialVector>* f_ext) {
941 std::vector<RigidBodyDynamics::Math::SpatialVector>* f_ext_rbdl =
nullptr;
943 f_ext_rbdl =
new std::vector<RigidBodyDynamics::Math::SpatialVector>();
944 for (
unsigned int i=0; i<f_ext->size(); ++i){
945 f_ext_rbdl->push_back( (*f_ext)[i] );
948 RigidBodyDynamics::InverseDynamics(*
this, Q, QDot, QDDot, Tau, f_ext_rbdl);
957 std::vector<biorbd::utils::SpatialVector>* f_ext)
961 std::vector<RigidBodyDynamics::Math::SpatialVector> f_ext_rbdl(dispatchedForce(*f_ext));
962 RigidBodyDynamics::ForwardDynamics(*
this, Q, QDot, Tau, QDDot, &f_ext_rbdl);
965 RigidBodyDynamics::ForwardDynamics(*
this, Q, QDot, Tau, QDDot);
976 std::vector<biorbd::utils::SpatialVector> *f_ext)
981 std::vector<RigidBodyDynamics::Math::SpatialVector> f_ext_rbdl(dispatchedForce(*f_ext));
982 RigidBodyDynamics::ForwardDynamicsConstraintsDirect(*
this, Q, QDot, Tau, CS, QDDot, &f_ext_rbdl);
985 RigidBodyDynamics::ForwardDynamicsConstraintsDirect(*
this, Q, QDot, Tau, CS, QDDot);
994 std::vector<biorbd::utils::SpatialVector> *f_ext)
997 this->ForwardDynamicsConstraintsDirect(Q, QDot, Tau, CS, f_ext);
1005 std::vector<biorbd::utils::SpatialVector> *f_ext)
1011 std::vector<RigidBodyDynamics::Math::SpatialVector> f_ext_rbdl(dispatchedForce(*f_ext));
1012 RigidBodyDynamics::ForwardDynamicsConstraintsDirect(*
this, Q, QDot, Tau, CS, QDDot, &f_ext_rbdl);
1015 RigidBodyDynamics::ForwardDynamicsConstraintsDirect(*
this, Q, QDot, Tau, CS, QDDot);
1032 RigidBodyDynamics::ComputeConstraintImpulsesDirect(*
this, Q, QDotPre, CS, QDotPost);
1041 unsigned int idx = 0;
1043 unsigned int iB = 0;
1048 if (segmentName.compare( (*m_segments)[iB].name() ) )
1049 idx += (*m_segments)[iB].nbDof();
1051 idx += (*m_segments)[iB].getDofIdx(dofName);
1068 checkGeneralizedDimensions(Q, Qdot, Qddot);
1069 RigidBodyDynamics::UpdateKinematicsCustom(*
this, Q, Qdot, Qddot);
1074 unsigned int segmentIdx,
1075 const RigidBodyDynamics::Math::Matrix3d &rotation,
1076 RigidBodyDynamics::Math::MatrixNd &G,
1079 #ifdef RBDL_ENABLE_LOGGING
1080 LOG <<
"-------- " << __func__ <<
" --------" << std::endl;
1085 UpdateKinematicsCustom (&Q,
nullptr,
nullptr);
1088 assert (G.rows() == 9 && G.cols() == this->qdot_size );
1090 std::vector<biorbd::utils::Vector3d> axes;
1094 for (
unsigned int iAxes=0; iAxes<3; ++iAxes){
1095 RigidBodyDynamics::Math::Matrix3d bodyMatRot (
1096 RigidBodyDynamics::CalcBodyWorldOrientation (*
this, Q, segmentIdx,
false).transpose());
1097 RigidBodyDynamics::Math::SpatialTransform point_trans(
1098 RigidBodyDynamics::Math::SpatialTransform (
1099 RigidBodyDynamics::Math::Matrix3d::Identity(), bodyMatRot * rotation * *(axes.begin()+iAxes)));
1102 unsigned int reference_body_id = segmentIdx;
1104 if (this->IsFixedBodyId(segmentIdx)) {
1105 unsigned int fbody_id = segmentIdx - this->fixed_body_discriminator;
1106 reference_body_id = this->mFixedBodies[fbody_id].mMovableParent;
1109 unsigned int j = reference_body_id;
1114 unsigned int q_index = this->mJoints[j].q_index;
1116 #ifdef BIORBD_USE_CASADI_MATH
1117 if (this->S[j].is_zero() && this->S[j](4).is_zero() && this->S[j](5).is_zero())
1119 if (this->S[j](3)!=1.0 && this->S[j](4)!=1.0 && this->S[j](5)!=1.0)
1122 RigidBodyDynamics::Math::SpatialTransform X_base = this->X_base[j];
1125 if (this->mJoints[j].mDoFCount == 3) {
1126 G.block(iAxes*3, q_index, 3, 3) = ((point_trans * X_base.inverse()).toMatrix() * this->multdof3_S[j]).block(3,0,3,3);
1128 G.block(iAxes*3,q_index, 3, 1) = point_trans.apply(X_base.inverse().apply(this->S[j])).block(3,0,3,1);
1131 j = this->lambda[j];
1146 "Wrong size for the Generalized Coordiates");
1150 Qdot->size() == nbQdot(),
1151 "Wrong size for the Generalized Velocities");
1155 Qddot->size() == nbQddot(),
1156 "Wrong size for the Generalized Accelerations");
1161 torque->size() == nbGeneralizedTorque(),
1162 "Wrong size for the Generalized Torques");