1 #include <gtest/gtest.h> 24 emulated_model.gravity =
SpatialVector(0., 0., 0., 0., 0., -9.81);
25 multdof3_model.gravity =
SpatialVector(0., 0., 0., 0., 0., -9.81);
26 eulerzyx_model.gravity =
SpatialVector(0., 0., 0., 0., 0., -9.81);
30 joint_rot_zyx =
Joint(
SpatialVector(0., 0., 1., 0., 0., 0.),
SpatialVector(0., 1., 0., 0., 0., 0.),
SpatialVector(1., 0., 0., 0., 0., 0.));
36 emulated_model.appendBody(
Xtrans(
Vector3d(0., 0., 0.)), joint_rot_y, body);
37 emu_body_id = emulated_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_rot_zyx, body);
38 emu_child_id = emulated_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_rot_y, body);
40 multdof3_model.appendBody(
Xtrans(
Vector3d(0., 0., 0.)), joint_rot_y, body);
41 sph_body_id = multdof3_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_spherical, body);
42 sph_child_id = multdof3_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_rot_y, body);
44 eulerzyx_model.appendBody(
Xtrans(
Vector3d(0., 0., 0.)), joint_rot_y, body);
45 eulerzyx_body_id = eulerzyx_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_eulerzyx, body);
46 eulerzyx_child_id = eulerzyx_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_rot_y, body);
48 emuQ = VectorNd::Zero((
size_t)emulated_model.q_size);
49 emuQDot = VectorNd::Zero((
size_t)emulated_model.qdot_size);
50 emuQDDot = VectorNd::Zero((
size_t)emulated_model.qdot_size);
51 emuTau = VectorNd::Zero((
size_t)emulated_model.qdot_size);
53 sphQ = VectorNd::Zero((
size_t)multdof3_model.q_size);
54 sphQDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
55 sphQDDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
56 sphTau = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
58 eulerzyxQ = VectorNd::Zero((
size_t)eulerzyx_model.q_size);
59 eulerzyxQDot = VectorNd::Zero((
size_t)eulerzyx_model.qdot_size);
60 eulerzyxQDDot = VectorNd::Zero((
size_t)eulerzyx_model.qdot_size);
61 eulerzyxTau = VectorNd::Zero((
size_t)eulerzyx_model.qdot_size);
70 unsigned int emu_body_id, emu_child_id, sph_body_id,
sph_child_id, eulerzyx_body_id, eulerzyx_child_id;
95 for (
unsigned int i = 1; i < multdof3_model.
mJoints.size(); i++)
97 unsigned int q_index = multdof3_model.
mJoints[i].q_index;
105 Vector3d(qdot_emulated[q_index], qdot_emulated[q_index + 1], qdot_emulated[q_index + 2]));
107 (*qdot_spherical)[q_index] = omega[0];
108 (*qdot_spherical)[q_index + 1] = omega[1];
109 (*qdot_spherical)[q_index + 2] = omega[2];
113 (*q_spherical)[q_index] = q_emulated[q_index];
114 (*qdot_spherical)[q_index] = qdot_emulated[q_index];
121 double timestep = 0.001;
123 Vector3d zyx_angles_t0(0.1, 0.2, 0.3);
125 Vector3d zyx_angles_t1 = zyx_angles_t0 + timestep * zyx_rates;
140 EXPECT_NEAR(q_zyx_t1.
x(), q_t1.
x(), 1.0e-5);
141 EXPECT_NEAR(q_zyx_t1.
y(), q_t1.
y(), 1.0e-5);
142 EXPECT_NEAR(q_zyx_t1.
z(), q_t1.
z(), 1.0e-5);
143 EXPECT_NEAR(q_zyx_t1.
w(), q_t1.
w(), 1.0e-5);
148 EXPECT_EQ(0u, multdof3_model.mJoints[1].q_index);
149 EXPECT_EQ(1u, multdof3_model.mJoints[2].q_index);
150 EXPECT_EQ(4u, multdof3_model.mJoints[3].q_index);
152 EXPECT_EQ(5u, emulated_model.q_size);
153 EXPECT_EQ(5u, emulated_model.qdot_size);
155 EXPECT_EQ(6u, multdof3_model.q_size);
156 EXPECT_EQ(5u, multdof3_model.qdot_size);
157 EXPECT_EQ(5u, multdof3_model.multdof3_w_index[2]);
162 multdof3_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_spherical, body);
164 sphQ = VectorNd::Zero((
size_t)multdof3_model.q_size);
165 sphQDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
166 sphQDDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
167 sphTau = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
169 EXPECT_EQ(10u, multdof3_model.q_size);
170 EXPECT_EQ(8u, multdof3_model.qdot_size);
172 EXPECT_EQ(0u, multdof3_model.mJoints[1].q_index);
173 EXPECT_EQ(1u, multdof3_model.mJoints[2].q_index);
174 EXPECT_EQ(4u, multdof3_model.mJoints[3].q_index);
175 EXPECT_EQ(5u, multdof3_model.mJoints[4].q_index);
177 EXPECT_EQ(8u, multdof3_model.multdof3_w_index[2]);
178 EXPECT_EQ(9u, multdof3_model.multdof3_w_index[4]);
192 Quaternion quat_1 = multdof3_model.GetQuaternion(2, sphQ);
194 EXPECT_EQ(reference_1.
x(), quat_1.
x());
195 EXPECT_EQ(reference_1.
y(), quat_1.
y());
196 EXPECT_EQ(reference_1.
z(), quat_1.
z());
197 EXPECT_EQ(reference_1.
w(), quat_1.
w());
200 Quaternion quat_3 = multdof3_model.GetQuaternion(4, sphQ);
202 EXPECT_EQ(reference_3.x(), quat_3.
x());
203 EXPECT_EQ(reference_3.y(), quat_3.
y());
204 EXPECT_EQ(reference_3.z(), quat_3.
z());
205 EXPECT_EQ(reference_3.w(), quat_3.
w());
210 multdof3_model.appendBody(
Xtrans(
Vector3d(1., 0., 0.)), joint_spherical, body);
212 sphQ = VectorNd::Zero((
size_t)multdof3_model.q_size);
213 sphQDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
214 sphQDDot = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
215 sphTau = VectorNd::Zero((
size_t)multdof3_model.qdot_size);
218 multdof3_model.SetQuaternion(2, reference_1, sphQ);
219 Quaternion test = multdof3_model.GetQuaternion(2, sphQ);
221 EXPECT_EQ(reference_1.
x(), test.
x());
222 EXPECT_EQ(reference_1.
y(), test.
y());
223 EXPECT_EQ(reference_1.
z(), test.
z());
224 EXPECT_EQ(reference_1.
w(), test.
w());
227 multdof3_model.SetQuaternion(4, reference_2, sphQ);
228 test = multdof3_model.GetQuaternion(4, sphQ);
230 EXPECT_EQ(reference_2.x(), test.
x());
231 EXPECT_EQ(reference_2.y(), test.
y());
232 EXPECT_EQ(reference_2.z(), test.
z());
233 EXPECT_EQ(reference_2.w(), test.
w());
243 for (
unsigned int i = 0; i < emuQ.size(); i++)
250 multdof3_model.SetQuaternion(2, quat, sphQ);
256 multdof3_model.bodyFrames[sph_child_id]->getInverseTransformToRoot().E,
TEST_PREC));
259 multdof3_model.bodyFrames[sph_child_id]->getTransformToRoot().E,
TEST_PREC));
286 Vector3d(emuQDDot[3], emuQDDot[2], emuQDDot[1]));
288 sphQDDot[0] = emuQDDot[0];
292 sphQDDot[4] = emuQDDot[4];
370 VectorNd tau_id(VectorNd::Zero(multdof3_model.qdot_size));
398 MatrixNd H_crba(MatrixNd::Zero(multdof3_model.qdot_size, multdof3_model.qdot_size));
403 MatrixNd H_id(MatrixNd::Zero(multdof3_model.qdot_size, multdof3_model.qdot_size));
404 VectorNd H_col = VectorNd::Zero(multdof3_model.qdot_size);
405 VectorNd QDDot_zero = VectorNd::Zero(multdof3_model.qdot_size);
407 for (
unsigned int i = 0; i < multdof3_model.qdot_size; i++)
410 VectorNd delta_a = VectorNd::Zero(multdof3_model.qdot_size);
414 VectorNd id_delta = VectorNd::Zero(multdof3_model.qdot_size);
418 VectorNd id_zero = VectorNd::Zero(multdof3_model.qdot_size);
421 H_col = id_delta - id_zero;
422 H_id.block(0, i, multdof3_model.qdot_size, 1) = H_col;
450 VectorNd QDDot_aba = VectorNd::Zero(multdof3_model.qdot_size);
451 VectorNd QDDot_lag = VectorNd::Zero(multdof3_model.qdot_size);
469 constraint_set_emu.
bind(emulated_model);
477 constraint_set_sph.
bind(multdof3_model);
495 constraint_set_emu.
bind(emulated_model);
503 constraint_set_sph.
bind(multdof3_model);
533 VectorNd QDDot_emu = VectorNd::Zero(emulated_model.qdot_size);
534 VectorNd QDDot_eulerzyx = VectorNd::Zero(eulerzyx_model.qdot_size);
540 H = RobotDynamics::Math::MatrixNd::Zero(eulerzyx_model.qdot_size, eulerzyx_model.qdot_size);
541 C = RobotDynamics::Math::VectorNd::Zero(eulerzyx_model.qdot_size);
567 VectorNd QDDot_emu = VectorNd::Zero(emulated_model.qdot_size);
568 VectorNd QDDot_eulerzyx = VectorNd::Zero(eulerzyx_model.qdot_size);
571 forwardDynamics(eulerzyx_model, emuQ, emuQDot, emuTau, QDDot_eulerzyx);
596 VectorNd QDDot_emu = VectorNd::Zero(emulated_model.qdot_size);
597 VectorNd QDDot_eulerzyx = VectorNd::Zero(eulerzyx_model.qdot_size);
603 CS_euler.
bind(eulerzyx_model);
609 CS_emulated.
bind(emulated_model);
635 MatrixNd H_emulated(MatrixNd::Zero(emulated_model.q_size, emulated_model.q_size));
636 MatrixNd H_eulerzyx(MatrixNd::Zero(eulerzyx_model.q_size, eulerzyx_model.q_size));
646 Model model_emulated;
649 Body body(1.,
Vector3d(1., 2., 1.),
Matrix3d(1., 0., 0, 0., 1., 0., 0., 0., 1.));
650 Joint joint_emulated(
SpatialVector(0., 0., 0., 1., 0., 0.),
SpatialVector(0., 0., 0., 0., 1., 0.),
SpatialVector(0., 0., 0., 0., 0., 1.));
662 for (
int i = 0; i < q.size(); i++)
664 q[i] = 1.1 * (
static_cast<double>(i + 1));
665 qdot[i] = 0.1 * (
static_cast<double>(i + 1));
666 qddot_3dof[i] = 0.21 * (
static_cast<double>(i + 1));
667 tau[i] = 2.1 * (
static_cast<double>(i + 1));
670 qddot_emulated = qddot_3dof;
682 C = RobotDynamics::Math::VectorNd::Zero(model_3dof.
qdot_size);
687 MatrixNd H_emulated(MatrixNd::Zero(q.size(), q.size()));
688 MatrixNd H_3dof(MatrixNd::Zero(q.size(), q.size()));
698 Model model_emulated;
701 Body body(1.,
Vector3d(1., 2., 1.),
Matrix3d(1., 0., 0, 0., 1., 0., 0., 0., 1.));
702 Joint joint_emulated(
SpatialVector(1., 0., 0., 0., 0., 0.),
SpatialVector(0., 1., 0., 0., 0., 0.),
SpatialVector(0., 0., 1., 0., 0., 0.));
714 for (
int i = 0; i < q.size(); i++)
716 q[i] = 1.1 * (
static_cast<double>(i + 1));
717 qdot[i] = 0.55 * (
static_cast<double>(i + 1));
718 qddot_emulated[i] = 0.23 * (
static_cast<double>(i + 1));
719 qddot_3dof[i] = 0.22 * (
static_cast<double>(i + 1));
720 tau[i] = 2.1 * (
static_cast<double>(i + 1));
734 C = RobotDynamics::Math::VectorNd::Zero(model_3dof.
qdot_size);
739 MatrixNd H_emulated(MatrixNd::Zero(q.size(), q.size()));
740 MatrixNd H_3dof(MatrixNd::Zero(q.size(), q.size()));
750 Model model_emulated;
753 Body body(1.,
Vector3d(1., 2., 1.),
Matrix3d(1., 0., 0, 0., 1., 0., 0., 0., 1.));
754 Joint joint_emulated(
SpatialVector(0., 1., 0., 0., 0., 0.),
SpatialVector(1., 0., 0., 0., 0., 0.),
SpatialVector(0., 0., 1., 0., 0., 0.));
766 for (
int i = 0; i < q.size(); i++)
768 q[i] = 0.4 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
769 qdot[i] = 0.5 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
770 tau[i] = 0.5 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
771 qddot_3dof[i] = 0.5 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
774 qddot_emulated = qddot_3dof;
795 C = RobotDynamics::Math::VectorNd::Zero(model_3dof.
qdot_size);
800 MatrixNd H_emulated(MatrixNd::Zero(q.size(), q.size()));
801 MatrixNd H_3dof(MatrixNd::Zero(q.size(), q.size()));
856 VectorNd qddot_lagrangian(qddot_emulated);
857 VectorNd qddot_kokkevis(qddot_emulated);
877 VectorNd qddot_lagrangian(qddot_emulated);
878 VectorNd qddot_sparse(qddot_emulated);
893 TEST_F(
Human36, TestContactsEmulatedLagrangianNullSpaceLinearSolverPartialPivLU)
897 VectorNd qddot_lagrangian(qddot_emulated);
898 VectorNd qddot_nullspace(qddot_emulated);
919 TEST_F(
Human36, TestContactsEmulatedLagrangianNullSpaceLinearSolverHouseholderQR)
923 VectorNd qddot_lagrangian(qddot_emulated);
924 VectorNd qddot_nullspace(qddot_emulated);
949 VectorNd qddot_lagrangian(qddot_emulated);
950 VectorNd qddot_nullspace(qddot_emulated);
984 for (
unsigned int i = 0; i < q.size(); i++)
986 q[i] = 0.4 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
987 qdot[i] = 0.5 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
988 tau[i] = 0.5 * M_PI *
static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
993 for (
unsigned int i = 0; i < q.size(); i++)
995 EXPECT_EQ(model_emulated->lambda_q[i], model_3dof->lambda_q[i]);
1016 for (
unsigned int i = 0; i < q.size(); i++)
1018 EXPECT_EQ(model_emulated->lambda_q[i], model_3dof->lambda_q[i]);
1021 VectorNd qddot_sparse(qddot_emulated);
1022 VectorNd qddot_kokkevis(qddot_emulated);
1041 VectorNd qddot_kokkevis(qddot_emulated);
1042 VectorNd qddot_kokkevis_2(qddot_emulated);
1077 VectorNd QDDot_emu = VectorNd::Zero(emulated_model.qdot_size);
1078 VectorNd QDDot_eulerzyx = VectorNd::Zero(eulerzyx_model.qdot_size);
1084 H = RobotDynamics::Math::MatrixNd::Zero(eulerzyx_model.qdot_size, eulerzyx_model.qdot_size);
1085 C = RobotDynamics::Math::VectorNd::Zero(eulerzyx_model.qdot_size);
1093 for (
unsigned int i = 0; i < model->dof_count; i++)
1095 q[i] = rand() /
static_cast<double>(RAND_MAX);
1096 tau[i] = rand() /
static_cast<double>(RAND_MAX);
1099 MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
1102 VectorNd qddot_solve_llt = M.llt().solve(tau);
1112 for (
unsigned int i = 0; i < model->dof_count; i++)
1114 q[i] = rand() /
static_cast<double>(RAND_MAX);
1115 tau[i] = rand() /
static_cast<double>(RAND_MAX);
1118 MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
1121 VectorNd qddot_solve_llt = M.llt().solve(tau);
1126 for (
unsigned int j = 0; j < 1; j++)
1128 for (
unsigned int i = 0; i < model->dof_count; i++)
1130 tau[i] = rand() /
static_cast<double>(RAND_MAX);
1134 qddot_solve_llt = M.llt().solve(tau);
1144 ::testing::InitGoogleTest(&argc, argv);
1145 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.
std::vector< Joint > mJoints
All joints.
EIGEN_STRONG_INLINE double & w()
3 DoF joint that uses Euler ZYX convention (faster than emulated
unsigned int sph_child_id
Describes all properties of a single body.
Quaternion timeStep(const Vector3d &omega, double dt)
Vector3d angular_velocity_from_angle_rates(const Vector3d &zyx_angles, const Vector3d &zyx_angle_rates)
Vector3d global_angular_velocity_from_rates(const Vector3d &zyx_angles, const Vector3d &zyx_rates)
void SetQuaternion(unsigned int i, const Math::Quaternion &quat, Math::VectorNd &Q) const
Sets the quaternion for body i (only valid if body i is connected by a JointTypeSpherical joint) ...
SpatialTransform Xtrans(const Vector3d &r)
Get pure translation transform.
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.
static Quaternion toQuaternion(const Vector3d &axis, double angle_rad)
Get quaternion representation of axis and angle.
unsigned int appendBody(const Math::SpatialTransform &joint_frame, const Joint &joint, const Body &body, std::string body_name="")
Adds a Body to the model such that the previously added Body is the Parent.
std::vector< ReferenceFramePtr > bodyFrames
static bool checkMatrix3dEq(const RobotDynamics::Math::Matrix3d &t1, const RobotDynamics::Math::Matrix3d &t2)
static bool checkVector3dEq(const RobotDynamics::Math::Vector3d &v1, const RobotDynamics::Math::Vector3d &v2)
unsigned int q_size
The size of the -vector. For models without spherical joints the value is the same as Model::dof_coun...
Structure that contains both constraint information and workspace memory.
EIGEN_STRONG_INLINE double & y()
Describes a joint relative to the predecessor body.
3 DoF joint that uses Euler XYZ convention (faster than emulated
Vector3d angular_acceleration_from_angle_rates(const Vector3d &zyx_angles, const Vector3d &zyx_angle_rates, const Vector3d &zyx_angle_rates_dot)
Quaternion that are used for singularity free joints.
TEST_F(SphericalJointFixture, TestQuaternionIntegration)
static bool checkMatrixNdEpsilonClose(const RobotDynamics::Math::MatrixNd &t1, const RobotDynamics::Math::MatrixNd &t2, const double epsilon)
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.
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.
EIGEN_STRONG_INLINE double & x()
int main(int argc, char **argv)
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)
static bool checkSpatialVectorsEq(const RobotDynamics::Math::SpatialVector &v1, const RobotDynamics::Math::SpatialVector &v2)
EIGEN_STRONG_INLINE double & z()
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)
3 DoF joint using Quaternions for joint positional variables and
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.
void forwardDynamicsLagrangian(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, Math::VectorNd &QDDot, Math::MatrixNd &H, Math::VectorNd &C, Math::LinearSolver linear_solver=Math::LinearSolverColPivHouseholderQR, Math::SpatialForceV *f_ext=nullptr, bool update_kinematics=true)
Computes forward dynamics by building and solving the full Lagrangian equation.
static Quaternion intrinsicZYXAnglesToQuaternion(double yaw, double pitch, double roll)
Convert YPR angles to quaternion.
void ConvertQAndQDotFromEmulated(const Model &emulated_model, const VectorNd &q_emulated, const VectorNd &qdot_emulated, const Model &multdof3_model, VectorNd *q_spherical, VectorNd *qdot_spherical)
void nonlinearEffects(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &Tau, bool update_kinematics=true)
Computes the coriolis forces.
Namespace for all structures of the RobotDynamics library.
static bool checkMatrix3dEpsilonClose(const RobotDynamics::Math::Matrix3d &t1, const RobotDynamics::Math::Matrix3d &t2, const double epsilon)
unsigned int qdot_size
The size of the.
3 DoF joint that uses Euler YXZ convention (faster than emulated