3 #include <gtest/gtest.h> 86 S = MatrixNd::Zero(6, 1);
88 d_u = MatrixNd::Zero(mDoFCount, 1);
89 S_o = MatrixNd::Zero(6, 1);
95 model.
v_J[joint_id][0] = qdot[model.
mJoints[joint_id].q_index];
97 model.
bodyFrames[joint_id]->setTransformFromParent(model.
X_J[joint_id] * model.
X_T[joint_id]);
116 S = MatrixNd::Zero(6, 3);
117 S_o = MatrixNd::Zero(6, 3);
118 d_u = MatrixNd::Zero(mDoFCount, 1);
123 double q0 = q[model.
mJoints[joint_id].q_index];
124 double q1 = q[model.
mJoints[joint_id].q_index + 1];
125 double q2 = q[model.
mJoints[joint_id].q_index + 2];
134 model.
X_J[joint_id].E =
135 Matrix3d(c0 * c1, s0 * c1, -s1, c0 * s1 * s2 - s0 * c2, s0 * s1 * s2 + c0 * c2, c1 * s2, c0 * s1 * c2 + s0 * s2, s0 * s1 * c2 - c0 * s2, c1 * c2);
147 double qdot0 = qdot[model.
mJoints[joint_id].q_index];
148 double qdot1 = qdot[model.
mJoints[joint_id].q_index + 1];
149 double qdot2 = qdot[model.
mJoints[joint_id].q_index + 2];
151 Vector3d qdotv(qdot0, qdot1, qdot2);
152 model.
v_J[joint_id].set(S * qdotv);
154 S_o(0, 0) = -c1 * qdot1;
155 S_o(1, 0) = -s1 * s2 * qdot1 + c1 * c2 * qdot2;
156 S_o(1, 1) = -s2 * qdot2;
157 S_o(2, 0) = -s1 * c2 * qdot1 - c1 * s2 * qdot2;
158 S_o(2, 1) = -c2 * qdot2;
160 model.
c_J[joint_id] = S_o * qdotv;
162 model.
bodyFrames[joint_id]->setTransformFromParent(model.
X_J[joint_id] * model.
X_T[joint_id]);
168 double q0 = q[model.
mJoints[joint_id].q_index];
169 double q1 = q[model.
mJoints[joint_id].q_index + 1];
170 double q2 = q[model.
mJoints[joint_id].q_index + 2];
180 c0 * s1 * c2 + s0 * s2, s0 * s1 * c2 - c0 * s2, c1 * c2),
182 model.
X_T[joint_id]);
232 Matrix3d inertia0 = Matrix3d::Identity(3, 3);
239 unsigned int custom_body_id0 = custom0->addBodyCustomJoint(0,
SpatialTransform(), &custom_joint0, body0);
241 VectorNd q0 = VectorNd::Zero(reference0->q_size);
242 VectorNd qdot0 = VectorNd::Zero(reference0->qdot_size);
243 VectorNd qddot0 = VectorNd::Zero(reference0->qdot_size);
244 VectorNd tau0 = VectorNd::Zero(reference0->qdot_size);
246 reference_model.at(0) = reference0;
247 custom_model.at(0) = custom0;
249 reference_body_id.at(0) = (reference_body_id0);
250 custom_body_id.at(0) = (custom_body_id0);
252 body.at(0) = (body0);
253 custom_joint.at(0) = (&custom_joint0);
256 qdot.at(0) = (qdot0);
257 qddot.at(0) = (qddot0);
270 unsigned int custom_body_id1 = custom1->addBodyCustomJoint(0,
SpatialTransform(), &custom_joint1, body0);
272 VectorNd q1 = VectorNd::Zero(reference1->q_size);
273 VectorNd qdot1 = VectorNd::Zero(reference1->qdot_size);
274 VectorNd qddot1 = VectorNd::Zero(reference1->qdot_size);
275 VectorNd tau1 = VectorNd::Zero(reference1->qdot_size);
277 reference_model.at(1) = (reference1);
278 custom_model.at(1) = (custom1);
280 reference_body_id.at(1) = (reference_body_id1);
281 custom_body_id.at(1) = (custom_body_id1);
283 body.at(1) = (body0);
284 custom_joint.at(1) = (&custom_joint1);
287 qdot.at(1) = (qdot1);
288 qddot.at(1) = (qddot1);
294 for (
unsigned int i = 0; i < reference_model.size(); i++)
299 for (
unsigned int i = 0; i < custom_model.size(); i++)
341 int dof = reference_model.at(idx)->dof_count;
342 for (
unsigned int i = 0; i < dof; i++)
344 q.at(idx)[i] = i * 0.1;
345 qdot.at(idx)[i] = i * 0.15;
346 qddot.at(idx)[i] = i * 0.17;
349 updateKinematics(*reference_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx));
350 updateKinematics(*custom_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx));
353 custom_model.at(idx)->bodyFrames[custom_body_id.at(idx)]->getInverseTransformToRoot().E,
368 int dof = reference_model.at(idx)->dof_count;
369 for (
unsigned int i = 0; i < dof; i++)
371 q.at(idx)[i] = i * 9.133758561390194e-01;
372 qdot.at(idx)[i] = i * 6.323592462254095e-01;
373 qddot.at(idx)[i] = i * 9.754040499940952e-02;
380 custom_model.at(idx)->bodyFrames[custom_body_id.at(idx)]->getInverseTransformToRoot().E,
403 int dof = reference_model.at(idx)->dof_count;
405 for (
unsigned int i = 0; i < dof; i++)
407 q.at(idx)[i] = i * 9.133758561390194e-01;
408 qdot.at(idx)[i] = i * 6.323592462254095e-01;
409 qddot.at(idx)[i] = i * 9.754040499940952e-02;
413 updateKinematics(*reference_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx));
414 updateKinematics(*custom_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx));
417 MatrixNd Gref =
MatrixNd(MatrixNd::Zero(6, reference_model.at(idx)->dof_count));
419 MatrixNd Gcus =
MatrixNd(MatrixNd::Zero(6, reference_model.at(idx)->dof_count));
424 for (
int i = 0; i < 6; ++i)
426 for (
int j = 0; j < dof; ++j)
428 EXPECT_NEAR(Gref(i, j), Gcus(i, j),
TEST_PREC);
433 Vector3d point_position(1.1, 1.2, 2.1);
435 calcPointJacobian6D(*reference_model.at(idx), q.at(idx), reference_body_id.at(idx), point_position, Gref);
436 calcPointJacobian6D(*custom_model.at(idx), q.at(idx), custom_body_id.at(idx), point_position, Gcus);
438 for (
int i = 0; i < 6; ++i)
440 for (
int j = 0; j < dof; ++j)
442 EXPECT_NEAR(Gref(i, j), Gcus(i, j),
TEST_PREC);
447 MatrixNd GrefPt = MatrixNd::Constant(3, reference_model.at(idx)->dof_count, 0.);
448 MatrixNd GcusPt = MatrixNd::Constant(3, reference_model.at(idx)->dof_count, 0.);
450 calcPointJacobian(*reference_model.at(idx), q.at(idx), reference_body_id.at(idx), point_position, GrefPt);
451 calcPointJacobian(*custom_model.at(idx), q.at(idx), custom_body_id.at(idx), point_position, GcusPt);
453 for (
int i = 0; i < 3; ++i)
455 for (
int j = 0; j < dof; ++j)
457 EXPECT_NEAR(GrefPt(i, j), GcusPt(i, j),
TEST_PREC);
462 MatrixNd GDotrefPt = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
463 MatrixNd GDotcusPt = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
468 for (
int i = 0; i < GDotcusPt.rows(); ++i)
470 for (
int j = 0; j < GDotcusPt.cols(); ++j)
472 EXPECT_NEAR(GDotrefPt(i, j), GDotcusPt(i, j),
TEST_PREC);
476 GDotrefPt = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
477 GDotcusPt = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
479 calcPointJacobianDot6D(*reference_model.at(idx), q.at(idx), qdot.at(idx), reference_body_id.at(idx), point_position, GDotrefPt);
480 calcPointJacobianDot6D(*custom_model.at(idx), q.at(idx), qdot.at(idx), custom_body_id.at(idx), point_position, GDotcusPt);
482 for (
int i = 0; i < GDotcusPt.rows(); ++i)
484 for (
int j = 0; j < GDotcusPt.cols(); ++j)
486 EXPECT_NEAR(GDotrefPt(i, j), GDotcusPt(i, j),
TEST_PREC);
490 GDotrefPt = MatrixNd::Constant(3, reference_model.at(idx)->dof_count, 0.);
491 GDotcusPt = MatrixNd::Constant(3, reference_model.at(idx)->dof_count, 0.);
493 calcPointJacobianDot(*reference_model.at(idx), q.at(idx), qdot.at(idx), reference_body_id.at(idx), point_position, GDotrefPt);
494 calcPointJacobianDot(*custom_model.at(idx), q.at(idx), qdot.at(idx), custom_body_id.at(idx), point_position, GDotcusPt);
496 for (
int i = 0; i < GDotcusPt.rows(); ++i)
498 for (
int j = 0; j < GDotcusPt.cols(); ++j)
500 EXPECT_NEAR(GDotrefPt(i, j), GDotcusPt(i, j),
TEST_PREC);
504 MatrixNd Aref = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
505 MatrixNd Acus = MatrixNd::Constant(6, reference_model.at(idx)->dof_count, 0.);
518 int dof = reference_model.at(idx)->dof_count;
520 for (
unsigned int i = 0; i < dof; i++)
522 q.at(idx)[i] = i * 9.133758561390194e-01;
523 qdot.at(idx)[i] = i * 6.323592462254095e-01;
524 qddot.at(idx)[i] = i * 9.754040499940952e-02;
528 MatrixNd ADotref =
MatrixNd(MatrixNd::Zero(6, reference_model.at(idx)->qdot_size));
529 MatrixNd ADotcus =
MatrixNd(MatrixNd::Zero(6, reference_model.at(idx)->qdot_size));
542 int dof = reference_model.at(idx)->dof_count;
544 for (
unsigned int i = 0; i < dof; i++)
546 q.at(idx)[i] = i * 9.133758561390194e-01;
547 qdot.at(idx)[i] = i * 6.323592462254095e-01;
548 qddot.at(idx)[i] = i * 9.754040499940952e-02;
553 VectorNd tauRef = VectorNd::Zero(reference_model.at(idx)->qdot_size);
554 VectorNd tauCus = VectorNd::Zero(reference_model.at(idx)->qdot_size);
556 inverseDynamics(*reference_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx), tauRef);
557 inverseDynamics(*custom_model.at(idx), q.at(idx), qdot.at(idx), qddot.at(idx), tauCus);
567 int dof = reference_model.at(idx)->dof_count;
569 for (
unsigned int i = 0; i < dof; i++)
571 q.at(idx)[i] = (i + 0.1) * 9.133758561390194e-01;
572 qdot.at(idx)[i] = (i + 0.1) * 6.323592462254095e-01;
573 tau.at(idx)[i] = (i + 0.1) * 9.754040499940952e-02;
576 MatrixNd h_ref = MatrixNd::Constant(dof, dof, 0.);
577 VectorNd c_ref = VectorNd::Constant(dof, 0.);
578 VectorNd qddot_zero_ref = VectorNd::Constant(dof, 0.);
579 VectorNd qddot_crba_ref = VectorNd::Constant(dof, 0.);
581 MatrixNd h_cus = MatrixNd::Constant(dof, dof, 0.);
582 VectorNd c_cus = VectorNd::Constant(dof, 0.);
583 VectorNd qddot_zero_cus = VectorNd::Constant(dof, 0.);
584 VectorNd qddot_crba_cus = VectorNd::Constant(dof, 0.);
586 VectorNd qddotRef = VectorNd::Zero(dof);
587 VectorNd qddotCus = VectorNd::Zero(dof);
590 forwardDynamics(*reference_model.at(idx), q.at(idx), qdot.at(idx), tau.at(idx), qddotRef);
592 inverseDynamics(*reference_model.at(idx), q.at(idx), qdot.at(idx), qddot_zero_ref, c_ref);
596 forwardDynamics(*custom_model.at(idx), q.at(idx), qdot.at(idx), tau.at(idx), qddotCus);
598 inverseDynamics(*custom_model.at(idx), q.at(idx), qdot.at(idx), qddot_zero_cus, c_cus);
609 int dof = reference_model.at(idx)->dof_count;
611 for (
unsigned int i = 0; i < dof; i++)
613 q.at(idx)[i] = (i + 0.1) * 9.133758561390194e-01;
614 qdot.at(idx)[i] = (i + 0.1) * 6.323592462254095e-01;
615 qddot.at(idx)[i] = (i + 0.1) * 2.323592499940952e-01;
616 tau.at(idx)[i] = (i + 0.1) * 9.754040499940952e-02;
619 VectorNd qddotRef = VectorNd::Zero(reference_model.at(idx)->qdot_size);
620 VectorNd qddotCus = VectorNd::Zero(reference_model.at(idx)->qdot_size);
622 forwardDynamics(*reference_model.at(idx), q.at(idx), qdot.at(idx), tau.at(idx), qddotRef);
623 forwardDynamics(*custom_model.at(idx), q.at(idx), qdot.at(idx), tau.at(idx), qddotCus);
633 int dof = reference_model.at(idx)->dof_count;
635 for (
unsigned int i = 0; i < dof; i++)
637 q.at(idx)[i] = (i + 0.1) * 9.133758561390194e-01;
638 tau.at(idx)[i] = (i + 0.1) * 9.754040499940952e-02;
642 VectorNd qddot_minv_ref = VectorNd::Zero(dof);
643 calcMInvTimesTau(*reference_model.at(idx), q.at(idx), tau.at(idx), qddot_minv_ref,
true);
646 VectorNd qddot_minv_cus = VectorNd::Zero(dof);
647 calcMInvTimesTau(*custom_model.at(idx), q.at(idx), tau.at(idx), qddot_minv_cus,
true);
657 int dof = reference_model.at(idx)->dof_count;
663 for (
unsigned int i = 0; i < dof; i++)
665 q.at(idx)[i] = (i + 0.1) * 9.133758561390194e-01;
666 qdot.at(idx)[i] = (i + 0.1) * 6.323592462254095e-01;
668 tau.at(idx)[i] = (i + 0.1) * 9.754040499940952e-02;
671 VectorNd qddot_ref = VectorNd::Zero(dof);
672 VectorNd qddot_cus = VectorNd::Zero(dof);
674 VectorNd qdot_plus_ref = VectorNd::Zero(dof);
675 VectorNd qdot_plus_cus = VectorNd::Zero(dof);
683 constraint_set_ref.
addConstraint(reference_body_id.at(idx), contact_point,
Vector3d(1., 0., 0.),
"ground_x");
684 constraint_set_ref.
addConstraint(reference_body_id.at(idx), contact_point,
Vector3d(0., 1., 0.),
"ground_y");
685 constraint_set_ref.
bind(*reference_model.at(idx));
688 constraint_set_cus.
addConstraint(custom_body_id.at(idx), contact_point,
Vector3d(1., 0., 0.),
"ground_x");
689 constraint_set_cus.
addConstraint(custom_body_id.at(idx), contact_point,
Vector3d(0., 1., 0.),
"ground_y");
690 constraint_set_cus.
bind(*custom_model.at(idx));
698 VectorNd qdot_plus_error = qdot_plus_ref - qdot_plus_cus;
699 VectorNd qddot_error = qddot_ref - qddot_cus;
708 int main(
int argc,
char** argv)
710 ::testing::InitGoogleTest(&argc, argv);
711 return RUN_ALL_TESTS();
static bool checkVectorNdEpsilonClose(const RobotDynamics::Math::VectorNd &v1, const RobotDynamics::Math::VectorNd &v2, const double epsilon)
void compositeRigidBodyAlgorithm(Model &model, const Math::VectorNd &Q, Math::MatrixNd &H, bool update_kinematics=true)
Computes the joint space inertia matrix by using the Composite Rigid Body Algorithm.
void calcPointJacobian(Model &model, const Math::VectorNd &Q, unsigned int body_id, const Math::Vector3d &point_position, Math::MatrixNd &G, bool update_kinematics=true)
Computes the 3D point jacobian for a point on a body.
std::vector< Joint > mJoints
All joints.
3 DoF joint that uses Euler ZYX convention (faster than emulated
Describes all properties of a single body.
std::vector< Math::SpatialVector > c_J
vector< unsigned int > custom_body_id
CustomJoint is a struct used to create a joint with user defined parameters. This is accomplished by ...
std::shared_ptr< Model > ModelPtr
CustomJointTypeRevoluteX custom_joint1
bool linSolveGaussElimPivot(MatrixNd A, VectorNd b, VectorNd &x)
Solves a linear system using gaussian elimination with pivoting.
CustomJointTypeRevoluteX()
CustomEulerZYXJoint custom_joint0
void calcPointJacobianDot(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, unsigned int body_id, const Math::Vector3d &point_position, Math::MatrixNd &G, bool update_kinematics=true)
Computes the time derivative of the linear components the a point jacobian on a body.
unsigned int addConstraint(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &world_normal, const char *constraint_name=NULL, double normal_acceleration=0.)
Adds a constraint to the constraint set.
bool checkModelZeroVectorsAndMatrices(RobotDynamics::Model &model)
virtual void jcalc(Model &model, unsigned int joint_id, const Math::VectorNd &q, const Math::VectorNd &qdot)
virtual void jcalc_X_lambda_S(Model &model, unsigned int joint_id, const Math::VectorNd &q)
std::vector< ReferenceFramePtr > bodyFrames
vector< unsigned int > reference_body_id
void calcPointJacobian6D(Model &model, const Math::VectorNd &Q, Math::MatrixNd &G, ReferenceFramePtr frame, bool update_kinematics=true)
Compute the 6D point jacobian of the origin of a reference frame If a position of a point is computed...
virtual void jcalc_X_lambda_S(Model &model, unsigned int joint_id, const Math::VectorNd &q)
Structure that contains both constraint information and workspace memory.
virtual void jcalc(Model &model, unsigned int joint_id, const Math::VectorNd &q, const Math::VectorNd &qdot)
void calcPointJacobianDot6D(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, RobotDynamics::ReferenceFramePtr frame, Math::MatrixNd &G, bool update_kinematics=true)
Computes the time derivative of a point jacobian of a point on a body.
const int NUMBER_OF_MODELS
unsigned int custom_joint_index
void calcCentroidalMomentumMatrixDot(Model &model, const Math::VectorNd &q, const Math::VectorNd &qdot, Math::MatrixNd &Adot, bool update_kinematics=true)
Calculates the time derivative of the centroidal momentum matrix, i.e. the matrix computed by RobotDy...
Describes a joint relative to the predecessor body.
void calcBodySpatialJacobianDot(Model &model, const Math::VectorNd &Q, const Math::VectorNd QDot, unsigned int body_id, Math::MatrixNd &G, const bool update_kinematics=true)
Computes the time derivative of the spatial jacobian for a body. The result will be returned via the ...
SpatialTransform Xrotx(const double &xrot)
Get transform with zero translation and pure rotation about x axis.
static bool checkMatrixNdEpsilonClose(const RobotDynamics::Math::MatrixNd &t1, const RobotDynamics::Math::MatrixNd &t2, const double epsilon)
void calcBodySpatialJacobian(Model &model, const Math::VectorNd &Q, unsigned int body_id, Math::MatrixNd &G, bool update_kinematics=true)
Computes the spatial jacobian for a body. The result will be returned via the G argument and represen...
void updateKinematics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &QDDot)
Updates and computes velocities and accelerations of the bodies.
std::vector< CustomJoint * > mCustomJoints
void calcCentroidalMomentumMatrix(Model &model, const Math::VectorNd &q, Math::MatrixNd &A, bool update_kinematics=true)
Calculates the centroidal momentum matrix, for a model. The centroidal momentum matrix is a matrix ...
vector< ModelPtr > custom_model
TEST_F(CustomJointSingleBodyFixture, UpdateKinematics)
void calcMInvTimesTau(Model &model, const Math::VectorNd &Q, const Math::VectorNd &Tau, Math::VectorNd &QDDot, bool update_kinematics=true)
Computes the effect of multiplying the inverse of the joint space inertia matrix with a vector in lin...
Contains all information about the rigid body model.
void updateKinematicsCustom(Model &model, const Math::VectorNd *Q, const Math::VectorNd *QDot=nullptr, const Math::VectorNd *QDDot=nullptr)
Selectively updates model internal states of body positions, velocities and/or accelerations.
bool bind(const Model &model)
Initializes and allocates memory for the constraint set.
Math types such as vectors and matrices and utility functions.
static bool checkSpatialVectorsEpsilonClose(const RobotDynamics::Math::SpatialVector &v1, const RobotDynamics::Math::SpatialVector &v2, const double epsilon)
vector< ModelPtr > reference_model
CustomJointSingleBodyFixture()
void inverseDynamics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &QDDot, Math::VectorNd &Tau, Math::SpatialForceV *f_ext=nullptr, bool update_kinematics=true)
void forwardDynamics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, Math::VectorNd &QDDot, Math::SpatialForceV *f_ext=nullptr, bool update_kinematics=true)
Computes forward dynamics with the Articulated Body Algorithm.
vector< CustomJoint * > custom_joint
std::vector< Math::SpatialTransform > X_J
int main(int argc, char **argv)
Namespace for all structures of the RobotDynamics library.
std::vector< Math::SpatialTransform > X_T
Transformations from the parent body to the frame of the joint.
static bool checkMatrix3dEpsilonClose(const RobotDynamics::Math::Matrix3d &t1, const RobotDynamics::Math::Matrix3d &t2, const double epsilon)