RdlDynamicsTests.cpp
Go to the documentation of this file.
1 #include <gtest/gtest.h>
2 
3 #include "UnitTestUtils.hpp"
4 
5 #include "rdl_dynamics/Model.h"
9 
10 #include "Fixtures.h"
11 #include "Human36Fixture.h"
12 
13 using namespace std;
14 using namespace RobotDynamics;
15 using namespace RobotDynamics::Math;
16 
17 const double TEST_PREC = 1.0e-13;
18 
19 struct RdlDynamicsFixture : public testing::Test
20 {
22  {
23  srand(time(nullptr));
24  }
25 
26  void SetUp()
27  {
28  model = new Model;
29  model->gravity = SpatialVector(0., 0., 0., 0., -9.81, 0.);
30  }
31 
32  void TearDown()
33  {
35  delete model;
36  }
37 
39 };
40 
41 // Kinda a silly test, but it was a bug, so a test for it anyway.
42 TEST_F(Human36, TestNonlinearEffects)
43 {
44  randomizeStates();
45  q.setZero();
46  qddot.setZero();
47 
48  VectorNd tau1 = VectorNd::Zero(model->qdot_size);
49  VectorNd tau2 = VectorNd::Zero(model->qdot_size);
50 
51  nonlinearEffects(*model, q, qdot, tau2);
52 
53  EXPECT_TRUE(unit_test_utils::checkSpatialVectorsEpsilonClose(model->a[0], SpatialVector(0., 0., 0., 0., 0., 9.81), unit_test_utils::TEST_PREC));
54  EXPECT_TRUE(unit_test_utils::checkSpatialVectorsEpsilonClose(model->a[1], SpatialVector(0., 0., 0., 0., 0., 9.81), unit_test_utils::TEST_PREC));
55 }
56 
57 TEST_F(RdlDynamicsFixture, TestCalcDynamicSingleChain)
58 {
59  Body body(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
60  Joint joint(SpatialVector(0., 0., 1., 0., 0., 0.));
61 
62  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint, body);
63 
64  // Initialization of the input vectors
65  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
66  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
67  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
68  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
69 
70  forwardDynamics(*model, Q, QDot, Tau, QDDot);
71 
72  EXPECT_EQ(-4.905, QDDot[0]);
73 }
74 
75 TEST_F(RdlDynamicsFixture, TestCalcDynamicSpatialInertiaSingleChain)
76 {
77  // This function checks the value for a non-trivial spatial inertia
78  Body body(1., Vector3d(1.5, 1., 1.), Vector3d(2., 2., 3.));
79 
80  Joint joint(SpatialVector(0., 0., 1., 0., 0., 0.));
81 
82  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint, body);
83 
84  // Initialization of the input vectors
85  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
86  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
87  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
88  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
89 
90  forwardDynamics(*model, Q, QDot, Tau, QDDot);
91 
92  EXPECT_EQ(-2.3544, QDDot[0]);
93 }
94 
95 TEST_F(RdlDynamicsFixture, TestCalcDynamicDoubleChain)
96 {
97  Body body_a(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
98  Joint joint_a(SpatialVector(0., 0., 1., 0., 0., 0.));
99 
100  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
101 
102  Body body_b(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
103  Joint joint_b(SpatialVector(0., 0., 1., 0., 0., 0.));
104 
105  model->addBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
106 
107  // Initialization of the input vectors
108  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
109  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
110  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
111  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
112 
113  // cout << "--- Double Chain ---" << endl;
114 
115  forwardDynamics(*model, Q, QDot, Tau, QDDot);
116 
117  EXPECT_NEAR(-5.88600000000000E+00, QDDot[0], TEST_PREC);
118  EXPECT_NEAR(3.92400000000000E+00, QDDot[1], TEST_PREC);
119 }
120 
121 TEST_F(RdlDynamicsFixture, TestCalcDynamicTripleChain)
122 {
123  Body body_a(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
124  Joint joint_a(SpatialVector(0., 0., 1., 0., 0., 0.));
125 
126  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
127 
128  Body body_b(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
129  Joint joint_b(SpatialVector(0., 0., 1., 0., 0., 0.));
130 
131  model->addBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
132 
133  Body body_c(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
134  Joint joint_c(SpatialVector(0., 0., 1., 0., 0., 0.));
135 
136  model->addBody(2, Xtrans(Vector3d(1., 0., 0.)), joint_c, body_c);
137 
138  // Initialization of the input vectors
139  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
140  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
141  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
142  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
143 
144  // cout << "--- Triple Chain ---" << endl;
145 
146  forwardDynamics(*model, Q, QDot, Tau, QDDot);
147 
148  EXPECT_NEAR(-6.03692307692308E+00, QDDot[0], TEST_PREC);
149  EXPECT_NEAR(3.77307692307692E+00, QDDot[1], TEST_PREC);
150  EXPECT_NEAR(1.50923076923077E+00, QDDot[2], TEST_PREC);
151 }
152 
153 TEST_F(RdlDynamicsFixture, TestCalcDynamicDoubleChain3D)
154 {
155  Body body_a(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
156  Joint joint_a(SpatialVector(0., 0., 1., 0., 0., 0.));
157 
158  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
159 
160  Body body_b(1., Vector3d(0., 1., 0.), Vector3d(1., 1., 1.));
161  Joint joint_b(SpatialVector(0., 1., 0., 0., 0., 0.));
162 
163  model->addBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
164 
165  // Initialization of the input vectors
166  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
167  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
168  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
169  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
170 
171  // cout << "--- Double Chain 3D ---" << endl;
172 
173  forwardDynamics(*model, Q, QDot, Tau, QDDot);
174 
175  // cout << LogOutput.str() << endl;
176 
177  EXPECT_NEAR(-3.92400000000000E+00, QDDot[0], TEST_PREC);
178  EXPECT_NEAR(0.00000000000000E+00, QDDot[1], TEST_PREC);
179 }
180 
181 TEST_F(RdlDynamicsFixture, TestCalcDynamicSimpleTree3D)
182 {
183  Body body_a(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
184  Joint joint_a(SpatialVector(0., 0., 1., 0., 0., 0.));
185 
186  model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
187 
188  Body body_b1(1., Vector3d(0., 1., 0.), Vector3d(1., 1., 1.));
189  Joint joint_b1(SpatialVector(0., 1., 0., 0., 0., 0.));
190 
191  model->addBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b1, body_b1);
192 
193  Body body_c1(1., Vector3d(0., 0., 1.), Vector3d(1., 1., 1.));
194  Joint joint_c1(SpatialVector(1., 0., 0., 0., 0., 0.));
195 
196  model->addBody(2, Xtrans(Vector3d(0., 1., 0.)), joint_c1, body_c1);
197 
198  Body body_b2(1., Vector3d(0., 1., 0.), Vector3d(1., 1., 1.));
199  Joint joint_b2(SpatialVector(0., 1., 0., 0., 0., 0.));
200 
201  model->addBody(1, Xtrans(Vector3d(-0.5, 0., 0.)), joint_b2, body_b2);
202 
203  Body body_c2(1., Vector3d(0., 0., 1.), Vector3d(1., 1., 1.));
204  Joint joint_c2(SpatialVector(1., 0., 0., 0., 0., 0.));
205 
206  model->addBody(4, Xtrans(Vector3d(0., -0.5, 0.)), joint_c2, body_c2);
207 
208  // Initialization of the input vectors
209  VectorNd Q = VectorNd::Constant((size_t)model->dof_count, 0.);
210  VectorNd QDot = VectorNd::Constant((size_t)model->dof_count, 0.);
211  VectorNd QDDot = VectorNd::Constant((size_t)model->dof_count, 0.);
212  VectorNd Tau = VectorNd::Constant((size_t)model->dof_count, 0.);
213 
214  // cout << "--- SimpleTree ---" << endl;
215 
216  forwardDynamics(*model, Q, QDot, Tau, QDDot);
217 
218  // cout << LogOutput.str() << endl;
219 
220  EXPECT_NEAR(-1.60319066147860E+00, QDDot[0], TEST_PREC);
221  EXPECT_NEAR(-5.34396887159533E-01, QDDot[1], TEST_PREC);
222  EXPECT_NEAR(4.10340466926070E+00, QDDot[2], TEST_PREC);
223  EXPECT_NEAR(2.67198443579767E-01, QDDot[3], TEST_PREC);
224  EXPECT_NEAR(5.30579766536965E+00, QDDot[4], TEST_PREC);
225 }
226 
227 TEST_F(RdlDynamicsFixture, TestForwardDynamicsLagrangian)
228 {
229  Model model;
230  Body base_body(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
231 
232  model.addBody(0, SpatialTransform(),
233  Joint(SpatialVector(0., 0., 0., 1., 0., 0.), SpatialVector(0., 0., 0., 0., 1., 0.), SpatialVector(0., 0., 0., 0., 0., 1.),
234  SpatialVector(0., 0., 1., 0., 0., 0.), SpatialVector(0., 1., 0., 0., 0., 0.), SpatialVector(1., 0., 0., 0., 0., 0.)),
235  base_body);
236 
237  // Initialization of the input vectors
238  VectorNd Q = VectorNd::Zero(model.dof_count);
239  VectorNd QDot = VectorNd::Zero(model.dof_count);
240  VectorNd Tau = VectorNd::Zero(model.dof_count);
241 
242  VectorNd QDDot_aba = VectorNd::Zero(model.dof_count);
243  VectorNd QDDot_lagrangian = VectorNd::Zero(model.dof_count);
244 
245  Q[0] = 1.1;
246  Q[1] = 1.2;
247  Q[2] = 1.3;
248  Q[3] = 0.1;
249  Q[4] = 0.2;
250  Q[5] = 0.3;
251 
252  QDot[0] = 1.1;
253  QDot[1] = -1.2;
254  QDot[2] = 1.3;
255  QDot[3] = -0.1;
256  QDot[4] = 0.2;
257  QDot[5] = -0.3;
258 
259  Tau[0] = 2.1;
260  Tau[1] = 2.2;
261  Tau[2] = 2.3;
262  Tau[3] = 1.1;
263  Tau[4] = 1.2;
264  Tau[5] = 1.3;
265 
268 
269  forwardDynamics(model, Q, QDot, Tau, QDDot_aba);
270  forwardDynamicsLagrangian(model, Q, QDot, Tau, QDDot_lagrangian, H, C);
271 
272  EXPECT_EQ(QDDot_aba.size(), QDDot_lagrangian.size());
273  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDot_aba, QDDot_lagrangian, TEST_PREC));
274 
276 }
277 
278 TEST_F(RdlDynamicsFixture, TestForwardDynamicsLagrangianNoKinematics)
279 {
280  Model model;
281  Body base_body(1., Vector3d(1., 0., 0.), Vector3d(1., 1., 1.));
282 
283  model.addBody(0, SpatialTransform(),
284  Joint(SpatialVector(0., 0., 0., 1., 0., 0.), SpatialVector(0., 0., 0., 0., 1., 0.), SpatialVector(0., 0., 0., 0., 0., 1.),
285  SpatialVector(0., 0., 1., 0., 0., 0.), SpatialVector(0., 1., 0., 0., 0., 0.), SpatialVector(1., 0., 0., 0., 0., 0.)),
286  base_body);
287 
288  // Initialization of the input vectors
289  VectorNd Q = VectorNd::Zero(model.dof_count);
290  VectorNd QDot = VectorNd::Zero(model.dof_count);
291  VectorNd Tau = VectorNd::Zero(model.dof_count);
292 
293  VectorNd QDDot_aba = VectorNd::Zero(model.dof_count);
294  VectorNd QDDot_lagrangian = VectorNd::Zero(model.dof_count);
295 
296  Q[0] = 1.1;
297  Q[1] = 1.2;
298  Q[2] = 1.3;
299  Q[3] = 0.1;
300  Q[4] = 0.2;
301  Q[5] = 0.3;
302 
303  QDot[0] = 1.1;
304  QDot[1] = -1.2;
305  QDot[2] = 1.3;
306  QDot[3] = -0.1;
307  QDot[4] = 0.2;
308  QDot[5] = -0.3;
309 
310  Tau[0] = 2.1;
311  Tau[1] = 2.2;
312  Tau[2] = 2.3;
313  Tau[3] = 1.1;
314  Tau[4] = 1.2;
315  Tau[5] = 1.3;
316 
319 
320  updateKinematicsCustom(model, &Q, &QDot, nullptr);
321  forwardDynamicsLagrangian(model, Q, QDot, Tau, QDDot_lagrangian, H, C, Math::LinearSolverColPivHouseholderQR, nullptr, false);
322  forwardDynamics(model, Q, QDot, Tau, QDDot_aba);
323 
324  EXPECT_EQ(QDDot_aba.size(), QDDot_lagrangian.size());
325  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDot_aba, QDDot_lagrangian, TEST_PREC));
326 
328 }
329 
330 /*
331  * A simple test for a model with 3 rotational dof. The reference value was
332  * computed with Featherstones spatial_v1 code. This test was written
333  * because my benchmark tool showed up inconsistencies, however this was
334  * due to the missing gravity term. But as the test now works, I just leave
335  * it here.
336  */
337 TEST_F(RdlDynamicsFixture, TestForwardDynamics3DoFModel)
338 {
339  Model model;
340 
341  model.gravity = SpatialVector(0., 0., 0., 0., -9.81, 0.);
342 
343  Body null_body(0., Vector3d(0., 0., 0.), Vector3d(0., 0., 0.));
344  null_body.mIsVirtual = true;
345  Body base_body(1., Vector3d(0., 0.5, 0.), Vector3d(1., 1., 1.));
346 
347  Joint joint_rot_z(SpatialVector(0., 0., 1., 0., 0., 0.));
348  Joint joint_rot_y(SpatialVector(0., 1., 0., 0., 0., 0.));
349  Joint joint_rot_x(SpatialVector(1., 0., 0., 0., 0., 0.));
350 
351  unsigned int base_id_rot_z, base_id_rot_y;
352 
353  // we can reuse both bodies and joints as they are copied
354  base_id_rot_z = model.addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, null_body);
355  base_id_rot_y = model.addBody(base_id_rot_z, Xtrans(Vector3d(0., 0., 0.)), joint_rot_y, null_body);
356  model.addBody(base_id_rot_y, Xtrans(Vector3d(0., 0., 0.)), joint_rot_x, base_body);
357 
358  // Initialization of the input vectors
359  VectorNd Q = VectorNd::Constant((size_t)model.dof_count, 0.);
360  VectorNd QDot = VectorNd::Constant((size_t)model.dof_count, 0.);
361  VectorNd Tau = VectorNd::Constant((size_t)model.dof_count, 0.);
362 
363  VectorNd QDDot = VectorNd::Constant((size_t)model.dof_count, 0.);
364  VectorNd QDDot_ref = VectorNd::Constant((size_t)model.dof_count, 0.);
365 
366  Q[0] = 1.;
367 
368  forwardDynamics(model, Q, QDot, Tau, QDDot);
369 
370  QDDot_ref[0] = 3.301932144386186;
371 
372  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDot_ref, QDDot, TEST_PREC));
374 }
375 
376 /*
377  * Another simple 3 dof model test which showed some problems when
378  * computing forward dynamics with the Lagrangian formulation. A proplem
379  * occured as the CRBA does not update the kinematics of the model, hence
380  * invalid body transformations and joint axis were used in the CRBA.
381  * Running the CRBA after the InverseDynamics calculation fixes this. This
382  * test ensures that the error does not happen when calling ForwardLagrangian.
383  */
384 TEST_F(RdlDynamicsFixture, TestForwardDynamics3DoFModelLagrangian)
385 {
386  Model model;
387 
388  model.gravity = SpatialVector(0., 0., 0., 0., -9.81, 0.);
389 
390  Body null_body(0., Vector3d(0., 0., 0.), Vector3d(0., 0., 0.));
391  null_body.mIsVirtual = true;
392  Body base_body(1., Vector3d(0., 0.5, 0.), Vector3d(1., 1., 1.));
393 
394  Joint joint_rot_z(SpatialVector(0., 0., 1., 0., 0., 0.));
395  Joint joint_rot_y(SpatialVector(0., 1., 0., 0., 0., 0.));
396  Joint joint_rot_x(SpatialVector(1., 0., 0., 0., 0., 0.));
397 
398  unsigned int base_id_rot_z, base_id_rot_y;
399 
400  // we can reuse both bodies and joints as they are copied
401  base_id_rot_z = model.addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, null_body);
402  base_id_rot_y = model.addBody(base_id_rot_z, Xtrans(Vector3d(0., 0., 0.)), joint_rot_y, null_body);
403  model.addBody(base_id_rot_y, Xtrans(Vector3d(0., 0., 0.)), joint_rot_x, base_body);
404 
405  // Initialization of the input vectors
406  VectorNd Q = VectorNd::Constant((size_t)model.dof_count, 0.);
407  VectorNd QDot = VectorNd::Constant((size_t)model.dof_count, 0.);
408  VectorNd Tau = VectorNd::Constant((size_t)model.dof_count, 0.);
409 
410  VectorNd QDDot_ab = VectorNd::Constant((size_t)model.dof_count, 0.);
411  VectorNd QDDot_lagrangian = VectorNd::Constant((size_t)model.dof_count, 0.);
412 
413  Q[1] = 1.;
414 
415  Q[0] = 0.;
416  Q[1] = 1.;
417  Q[2] = 0.;
420 
421  forwardDynamicsLagrangian(model, Q, QDot, Tau, QDDot_lagrangian, H, C);
422  forwardDynamics(model, Q, QDot, Tau, QDDot_ab);
423 
424  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDot_ab, QDDot_lagrangian, TEST_PREC));
425 
426  Q[0] = 0.;
427  Q[1] = 0.;
428  Q[2] = 1.;
429  forwardDynamicsLagrangian(model, Q, QDot, Tau, QDDot_lagrangian, H, C);
430  forwardDynamics(model, Q, QDot, Tau, QDDot_ab);
431 
432  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDot_ab, QDDot_lagrangian, TEST_PREC));
434 }
435 
436 /*
437  * This is a test for a model where I detected incosistencies between the
438  * Lagragian method and the ABA.
439  */
440 TEST_F(RdlDynamicsFixture, TestForwardDynamicsTwoLegModelLagrangian)
441 {
442  Model* model = NULL;
443 
444  unsigned int hip_id, foot_right_id, foot_left_id;
446 
447  Joint joint_rot_z, joint_rot_y, joint_rot_x;
448  Joint joint_trans_z, joint_trans_y, joint_trans_x;
449 
450  ConstraintSet CS_right;
451  ConstraintSet CS_left;
452  ConstraintSet CS_both;
453 
454  model = new Model();
455 
456  model->gravity = SpatialVector(0., 0., 0., 0., -9.81, 0.);
457 
458  joint_rot_z = Joint(SpatialVector(0., 0., 1., 0., 0., 0.));
459  joint_rot_y = Joint(SpatialVector(0., 1., 0., 0., 0., 0.));
460  joint_rot_x = Joint(SpatialVector(1., 0., 0., 0., 0., 0.));
461 
462  joint_trans_z = Joint(SpatialVector(0., 0., 0., 0., 0., 1.));
463  joint_trans_y = Joint(SpatialVector(0., 0., 0., 0., 1., 0.));
464  joint_trans_x = Joint(SpatialVector(0., 0., 0., 1., 0., 0.));
465 
466  Body null_body(0., Vector3d(0., 0., 0.), Vector3d(0., 0., 0.));
467  null_body.mIsVirtual = true;
468 
469  // hip
470  hip_body = Body(1., Vector3d(0., 0., 0.), Vector3d(1., 1., 1.));
471 
472  // lateral right
473  upper_leg_right_body = Body(1., Vector3d(0., -0.25, 0.), Vector3d(1., 1., 1.));
474  lower_leg_right_body = Body(1., Vector3d(0., -0.25, 0.), Vector3d(1., 1., 1.));
475  foot_right_body = Body(1., Vector3d(0.15, -0.1, 0.), Vector3d(1., 1., 1.));
476 
477  // lateral left
478  upper_leg_left_body = Body(1., Vector3d(0., -0.25, 0.), Vector3d(1., 1., 1.));
479  lower_leg_left_body = Body(1., Vector3d(0., -0.25, 0.), Vector3d(1., 1., 1.));
480  foot_left_body = Body(1., Vector3d(0.15, -0.1, 0.), Vector3d(1., 1., 1.));
481 
482  // temporary value to store most recent body id
483  unsigned int temp_id;
484 
485  // add hip to the model (planar, 3 DOF)
486  temp_id = model->addBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_trans_x, null_body);
487  temp_id = model->addBody(temp_id, Xtrans(Vector3d(0., 0., 0.)), joint_trans_y, null_body);
488  hip_id = model->addBody(temp_id, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, hip_body);
489 
490  //
491  // right leg
492  //
493 
494  // add right upper leg
495  temp_id = model->addBody(hip_id, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, upper_leg_right_body);
496 
497  // add the right lower leg (only one DOF)
498  temp_id = model->addBody(temp_id, Xtrans(Vector3d(0., -0.5, 0.)), joint_rot_z, lower_leg_right_body);
499 
500  // add the right foot (1 DOF)
501  temp_id = model->addBody(temp_id, Xtrans(Vector3d(0., -0.5, 0.)), joint_rot_z, foot_right_body);
502  foot_right_id = temp_id;
503 
504  //
505  // left leg
506  //
507 
508  // add left upper leg
509  temp_id = model->addBody(hip_id, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, upper_leg_left_body);
510 
511  // add the left lower leg (only one DOF)
512  temp_id = model->addBody(temp_id, Xtrans(Vector3d(0., -0.5, 0.)), joint_rot_z, lower_leg_left_body);
513 
514  // add the left foot (1 DOF)
515  temp_id = model->addBody(temp_id, Xtrans(Vector3d(0., -0.5, 0.)), joint_rot_z, foot_left_body);
516  foot_left_id = temp_id;
517 
518  // contact data
519  CS_right.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(1., 0., 0.), "foot_right_x");
520  CS_right.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(0., 1., 0.), "foot_right_y");
521  CS_right.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(0., 0., 1.), "foot_right_z");
522 
523  CS_left.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(1., 0., 0.), "foot_left_x");
524  CS_left.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(0., 1., 0.), "foot_left_y");
525  CS_left.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(0., 0., 1.), "foot_left_z");
526 
527  CS_both.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(1., 0., 0.), "foot_right_x");
528  CS_both.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(0., 1., 0.), "foot_right_y");
529  CS_both.addConstraint(foot_right_id, Vector3d(0., 0., 0.), Vector3d(0., 0., 1.), "foot_right_z");
530  CS_both.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(1., 0., 0.), "foot_left_x");
531  CS_both.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(0., 1., 0.), "foot_left_y");
532  CS_both.addConstraint(foot_left_id, Vector3d(0., 0., 0.), Vector3d(0., 0., 1.), "foot_left_z");
533 
534  CS_right.bind(*model);
535  CS_left.bind(*model);
536  CS_both.bind(*model);
537 
538  VectorNd Q(model->dof_count);
539  VectorNd QDot(model->dof_count);
540  VectorNd Tau(model->dof_count);
541  VectorNd QDDot(model->dof_count);
542  VectorNd QDDotABA(model->dof_count);
543 
544  Q[0] = 0.8;
545  Q[1] = -7.76326e-06;
546  Q[2] = -1.58205e-07;
547  Q[3] = 1.57391e-07;
548  Q[4] = -1.03029e-09;
549  Q[5] = 7.92143e-08;
550  Q[6] = 1.57391e-07;
551  Q[7] = -1.03029e-09;
552  Q[8] = 7.92143e-08;
553 
554  QDot[0] = -1.77845e-06;
555  QDot[1] = -0.00905283;
556  QDot[2] = -0.000184484;
557  QDot[3] = 0.000183536;
558  QDot[4] = -1.20144e-06;
559  QDot[5] = 9.23727e-05;
560  QDot[6] = 0.000183536;
561  QDot[7] = -1.20144e-06;
562  QDot[8] = 9.23727e-05;
563 
564  Tau[0] = 0;
565  Tau[1] = 0;
566  Tau[2] = 0;
567  Tau[3] = 0.1;
568  Tau[4] = 0.1;
569  Tau[5] = 0.1;
570  Tau[6] = 0.1;
571  Tau[7] = 0.1;
572  Tau[8] = 0.1;
573 
576  H.setZero();
577  C.setZero();
578 
579  forwardDynamics(*model, Q, QDot, Tau, QDDotABA);
580  forwardDynamicsLagrangian(*model, Q, QDot, Tau, QDDot, H, C);
581 
582  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDotABA, QDDot, TEST_PREC));
584 
585  // run it again to make sure the calculations give the same results and
586  // no invalid state information lingering in the model structure is being used
587  forwardDynamics(*model, Q, QDot, Tau, QDDotABA);
588  forwardDynamicsLagrangian(*model, Q, QDot, Tau, QDDot, H, C);
589 
590  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(QDDotABA, QDDot, TEST_PREC));
592 
593  delete model;
594 }
595 
596 TEST_F(FixedAndMovableJoint, TestInverseDynamicsFixedJoint)
597 {
598  Q_fixed[0] = 1.1;
599  Q_fixed[1] = 2.2;
600 
601  QDot_fixed[0] = -3.2;
602  QDot_fixed[1] = -2.3;
603 
604  QDDot_fixed[0] = 1.2;
605  QDDot_fixed[1] = 2.1;
606 
607  Q = CreateDofVectorFromReducedVector(Q_fixed);
608  QDot = CreateDofVectorFromReducedVector(QDot_fixed);
609  QDDot = CreateDofVectorFromReducedVector(QDDot_fixed);
610 
611  inverseDynamics(*model_movable, Q, QDot, QDDot, Tau);
612  inverseDynamics(*model_fixed, Q_fixed, QDot_fixed, QDDot_fixed, Tau_fixed);
613 
614  VectorNd Tau_2dof(2);
615  Tau_2dof[0] = Tau[0];
616  Tau_2dof[1] = Tau[2];
617 
618  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(Tau_2dof, Tau_fixed, TEST_PREC));
619 }
620 
621 TEST_F(FloatingBase12DoF, TestForwardDynamicsLagrangianPrealloc)
622 {
623  for (unsigned int i = 0; i < model->dof_count; i++)
624  {
625  Q[i] = static_cast<double>(i + 1) * 0.1;
626  QDot[i] = static_cast<double>(i + 1) * 1.1;
627  Tau[i] = static_cast<double>(i + 1) * -1.2;
628  }
629 
630  MatrixNd H(MatrixNd::Zero(model->dof_count, model->dof_count));
631  VectorNd C(VectorNd::Zero(model->dof_count));
632 
634 
635  H = MatrixNd::Zero(model->dof_count, model->dof_count);
636  C = VectorNd::Zero(model->dof_count);
637  VectorNd QDDot_prealloc(VectorNd::Zero(model->dof_count));
638  forwardDynamicsLagrangian(*model, Q, QDot, Tau, QDDot_prealloc, H, C, Math::LinearSolverPartialPivLU, NULL);
639 
640  EXPECT_TRUE(unit_test_utils::checkVectorNdEq(QDDot, QDDot_prealloc));
641 }
642 
643 TEST_F(FixedBase3DoF, SolveMInvTimesTau)
644 {
645  for (unsigned int i = 0; i < model->dof_count; i++)
646  {
647  Q[i] = rand() / static_cast<double>(RAND_MAX);
648  QDot[i] = rand() / static_cast<double>(RAND_MAX);
649  Tau[i] = rand() / static_cast<double>(RAND_MAX);
650  }
651 
652  MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
653  compositeRigidBodyAlgorithm(*model, Q, M);
654 
655  VectorNd qddot_solve_llt = M.llt().solve(Tau);
656 
657  VectorNd qddot_minv(Q);
658  calcMInvTimesTau(*model, Q, Tau, qddot_minv);
659 
660  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC));
661 }
662 
663 TEST_F(FixedBase3DoF, SolveMInvTimesTauNoKinematics)
664 {
665  for (unsigned int i = 0; i < model->dof_count; i++)
666  {
667  Q[i] = rand() / static_cast<double>(RAND_MAX);
668  QDot[i] = rand() / static_cast<double>(RAND_MAX);
669  Tau[i] = rand() / static_cast<double>(RAND_MAX);
670  }
671 
672  updateKinematicsCustom(*model, &Q, &QDot, nullptr);
673  MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
674  compositeRigidBodyAlgorithm(*model, Q, M, false);
675 
676  VectorNd qddot_solve_llt = M.llt().solve(Tau);
677 
678  VectorNd qddot_minv(Q);
679  calcMInvTimesTau(*model, Q, Tau, qddot_minv, false);
680 
681  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC));
682 
683  M.setZero();
684  compositeRigidBodyAlgorithm(*model, Q, M, false);
685 
686  qddot_solve_llt.setZero();
687 
688  qddot_solve_llt = M.llt().solve(Tau);
689 
690  qddot_minv.setZero();
691  calcMInvTimesTau(*model, Q, Tau, qddot_minv, false);
692 
693  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC));
694 }
695 
696 TEST_F(FixedBase3DoF, SolveMInvTimesTauReuse)
697 {
698  for (unsigned int i = 0; i < model->dof_count; i++)
699  {
700  Q[i] = rand() / static_cast<double>(RAND_MAX);
701  Tau[i] = rand() / static_cast<double>(RAND_MAX);
702  }
703 
704  MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
705  compositeRigidBodyAlgorithm(*model, Q, M);
706 
707  VectorNd qddot_solve_llt = M.llt().solve(Tau);
708 
709  VectorNd qddot_minv(Q);
710  calcMInvTimesTau(*model, Q, Tau, qddot_minv);
711 
712  for (unsigned int j = 0; j < 1; j++)
713  {
714  for (unsigned int i = 0; i < model->dof_count; i++)
715  {
716  Tau[i] = rand() / static_cast<double>(RAND_MAX);
717  }
718 
719  compositeRigidBodyAlgorithm(*model, Q, M);
720  qddot_solve_llt = M.llt().solve(Tau);
721 
722  calcMInvTimesTau(*model, Q, Tau, qddot_minv, false);
723  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC));
724  }
725 }
726 
727 TEST_F(FixedBase3DoF, SolveMInvTimesTauReuseNoKinematics)
728 {
729  for (unsigned int i = 0; i < model->dof_count; i++)
730  {
731  Q[i] = rand() / static_cast<double>(RAND_MAX);
732  QDot[i] = rand() / static_cast<double>(RAND_MAX);
733  Tau[i] = rand() / static_cast<double>(RAND_MAX);
734  }
735 
736  updateKinematicsCustom(*model, &Q, &QDot, nullptr);
737  MatrixNd M(MatrixNd::Zero(model->dof_count, model->dof_count));
738  compositeRigidBodyAlgorithm(*model, Q, M);
739 
740  VectorNd qddot_solve_llt = M.llt().solve(Tau);
741 
742  VectorNd qddot_minv(Q);
743 
744  for (unsigned int j = 0; j < 1; j++)
745  {
746  for (unsigned int i = 0; i < model->dof_count; i++)
747  {
748  Tau[i] = rand() / static_cast<double>(RAND_MAX);
749  }
750 
751  compositeRigidBodyAlgorithm(*model, Q, M, false);
752  qddot_solve_llt = M.llt().solve(Tau);
753 
754  calcMInvTimesTau(*model, Q, Tau, qddot_minv, false);
755  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC));
756  }
757 }
758 
759 TEST_F(Human36, GravityEffects)
760 {
761  randomizeStates();
762 
763  updateKinematics(*model, q, qdot, qddot);
764 
765  RobotDynamics::Math::VectorNd G1 = RobotDynamics::Math::VectorNd::Zero(model->dof_count);
766  RobotDynamics::Math::VectorNd G2 = RobotDynamics::Math::VectorNd::Zero(model->dof_count);
767 
768  qdot.setZero();
769  nonlinearEffects(*model, q, qdot, G1);
770  gravityEffects(*model, G2);
771 
772  EXPECT_TRUE(G1.isApprox(G2, unit_test_utils::TEST_PREC));
773 
774  updateKinematics(*model_3dof, q, qdot, qddot);
775 
776  G1 = RobotDynamics::Math::VectorNd::Zero(model->dof_count);
777  G2 = RobotDynamics::Math::VectorNd::Zero(model->dof_count);
778 
779  qdot.setZero();
780  nonlinearEffects(*model_3dof, q, qdot, G1);
781  gravityEffects(*model_3dof, G2);
782 
783  EXPECT_TRUE(G1.isApprox(G2, unit_test_utils::TEST_PREC));
784 }
785 
786 TEST_F(RdlDynamicsFixture, gravityWrenchSimple)
787 {
788  RobotDynamics::Body b(1., Vector3d(0., 1., 0.), Vector3d(1., 1., 1.));
790  model->gravity = MotionVector(0., 0., 0., 0., 0., -9.81);
791 
792  unsigned int id1 = model->appendBody(RobotDynamics::Math::SpatialTransform(), j, b, "b1");
793  unsigned int id2 = model->appendBody(RobotDynamics::Math::Xtrans(RobotDynamics::Math::Vector3d(0., 2., 0.)), j, b, "b2");
794  RobotDynamics::Math::VectorNd q = RobotDynamics::Math::VectorNd::Zero(model->q_size);
795  updateKinematicsCustom(*model, &q, nullptr, nullptr);
796 
798  calcBodyGravityWrench(*model, id2, wrench);
799 
800  EXPECT_TRUE(wrench.isApprox(RobotDynamics::Math::ForceVector(-9.81, 0., 0., 0., 0., -9.81), unit_test_utils::TEST_PREC));
801 }
802 
803 TEST_F(Human36, GravityWrench)
804 {
805  for (unsigned i = 1; i < model->mBodies.size() - 1; i++)
806  {
807  randomizeStates();
808  qdot.setZero();
809  updateKinematicsCustom(*model, &q, nullptr, nullptr);
810 
811  RobotDynamics::Math::VectorNd G = RobotDynamics::Math::VectorNd::Zero(model->dof_count);
812 
814  gravityEffects(*model, G);
815 
816  calcBodyGravityWrench(*model, i, wrench);
817 
818  if (model->mJoints[i].mJointType != JointTypeCustom)
819  {
820  if (model->mJoints[i].mDoFCount == 1)
821  {
822  EXPECT_NEAR(G[model->mJoints[i].q_index], -model->S[i].dot(wrench), unit_test_utils::TEST_PREC);
823  }
824  else if (model->mJoints[i].mDoFCount == 3)
825  {
826  G.block<3, 1>(model->mJoints[i].q_index, 0).isApprox(-model->multdof3_S[i].transpose() * wrench, unit_test_utils::TEST_PREC);
827  }
828  }
829  else if (model->mJoints[i].mJointType == JointTypeCustom)
830  {
831  unsigned int k = model->mJoints[i].custom_joint_index;
832  G.block(model->mJoints[i].q_index, 0, model->mCustomJoints[k]->mDoFCount, 1)
833  .isApprox(-model->mCustomJoints[k]->S.transpose() * wrench, unit_test_utils::TEST_PREC);
834  }
835  }
836 }
837 
838 TEST_F(Human36, TestForwardDynamicsWithExternalForces)
839 {
840  randomizeStates();
841 
842  MatrixNd M(model_emulated->qdot_size, model_emulated->qdot_size);
843  VectorNd N(model_emulated->qdot_size);
844  M.setZero();
845  N.setZero();
846 
847  unsigned int foot_r_id = model_emulated->GetBodyId("foot_r");
848  SpatialForce F(model_emulated->bodyFrames[foot_r_id], 0.1, 0.3, -0.8, 82., -23., 500.1);
849 
850  MatrixNd J_r_foot(6, model_emulated->qdot_size);
851  J_r_foot.setZero();
852 
853  updateKinematics(*model_emulated, q, qdot, qddot);
854  calcBodySpatialJacobian(*model_emulated, q, foot_r_id, J_r_foot, false);
855  compositeRigidBodyAlgorithm(*model_emulated, q, M);
856  nonlinearEffects(*model_emulated, q, qdot, N);
857 
858  VectorNd qddot_cf(model_emulated->qdot_size), qddot_fd(model_emulated->qdot_size), qddot_test(model_emulated->qdot_size);
859  qddot_cf.setZero();
860 
861  qddot_cf = M.inverse() * (tau + J_r_foot.transpose() * F - N);
862 
863  std::shared_ptr<Math::SpatialForceV> f_ext(new Math::SpatialForceV(model_emulated->mBodies.size()));
864 
865  for (int i = 0; i < model_emulated->mBodies.size(); i++)
866  {
867  (*f_ext)[i].setIncludingFrame(model_emulated->bodyFrames[i], 0., 0., 0., 0., 0., 0.);
868  if (i == foot_r_id)
869  {
870  (*f_ext)[i].fx() = F.fx();
871  (*f_ext)[i].fy() = F.fy();
872  (*f_ext)[i].fz() = F.fz();
873  (*f_ext)[i].mx() = F.mx();
874  (*f_ext)[i].my() = F.my();
875  (*f_ext)[i].mz() = F.mz();
876  }
877  }
878 
879  forwardDynamics(*model_emulated, q, qdot, tau, qddot_fd, f_ext.get());
880 
881  if (!unit_test_utils::checkVectorNdEpsilonClose(qddot_cf, qddot_fd, 1e-7))
882  {
883  std::cout << (qddot_cf - qddot_fd).transpose();
884  }
885 
886  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_cf, qddot_fd, 1e-8));
887 }
888 
889 TEST_F(Human36, TestForwardDynamicsWithExternalForcesNoKinematics)
890 {
891  randomizeStates();
892 
893  MatrixNd M(model_emulated->qdot_size, model_emulated->qdot_size);
894  VectorNd N(model_emulated->qdot_size);
895  M.setZero();
896  N.setZero();
897 
898  unsigned int foot_r_id = model_emulated->GetBodyId("foot_r");
899  SpatialForce F(model_emulated->bodyFrames[foot_r_id], 0.1, 0.3, -0.8, 82., -23., 500.1);
900 
901  MatrixNd J_r_foot(6, model_emulated->qdot_size);
902  J_r_foot.setZero();
903 
904  updateKinematics(*model_emulated, q, qdot, qddot);
905  calcBodySpatialJacobian(*model_emulated, q, foot_r_id, J_r_foot, false);
906  compositeRigidBodyAlgorithm(*model_emulated, q, M, false);
907  nonlinearEffects(*model_emulated, q, qdot, N, false);
908 
909  VectorNd qddot_cf(model_emulated->qdot_size), qddot_fd(model_emulated->qdot_size), qddot_test(model_emulated->qdot_size);
910  qddot_cf.setZero();
911 
912  qddot_cf = M.inverse() * (tau + J_r_foot.transpose() * F - N);
913 
914  std::shared_ptr<Math::SpatialForceV> f_ext(new Math::SpatialForceV(model_emulated->mBodies.size()));
915 
916  for (int i = 0; i < model_emulated->mBodies.size(); i++)
917  {
918  (*f_ext)[i].setIncludingFrame(model_emulated->bodyFrames[i], 0., 0., 0., 0., 0., 0.);
919  if (i == foot_r_id)
920  {
921  (*f_ext)[i].fx() = F.fx();
922  (*f_ext)[i].fy() = F.fy();
923  (*f_ext)[i].fz() = F.fz();
924  (*f_ext)[i].mx() = F.mx();
925  (*f_ext)[i].my() = F.my();
926  (*f_ext)[i].mz() = F.mz();
927  }
928  }
929 
930  forwardDynamics(*model_emulated, q, qdot, tau, qddot_fd, f_ext.get(), false);
931 
932  if (!unit_test_utils::checkVectorNdEpsilonClose(qddot_cf, qddot_fd, 1e-7))
933  {
934  std::cout << (qddot_cf - qddot_fd).transpose();
935  }
936 
937  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_cf, qddot_fd, 1e-8));
938 }
939 
940 TEST_F(Human36, TestMInvTimesTau)
941 {
942  randomizeStates();
943 
944  MatrixNd M(MatrixNd::Zero(model_3dof->dof_count, model_3dof->dof_count));
945  compositeRigidBodyAlgorithm(*model_3dof, q, M);
946 
947  VectorNd qddot_solve_llt = M.llt().solve(tau);
948 
949  VectorNd qddot_minv(q);
950  calcMInvTimesTau(*model_3dof, q, tau, qddot_minv);
951 
952  for (unsigned int j = 0; j < 10; j++)
953  {
954  randomizeStates();
955 
956  compositeRigidBodyAlgorithm(*model_3dof, q, M);
957  qddot_solve_llt = M.llt().solve(tau);
958 
959  calcMInvTimesTau(*model_3dof, q, tau, qddot_minv);
960 
961  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC * qddot_solve_llt.norm()));
962  }
963 }
964 
966 {
967  model->gravity.SpatialVector::set(0., 0., 0., 0., 0., -9.81);
968 
969  RobotDynamics::Math::Vector3d b1_center(0.0, 0., 0.1);
970  double b1_mass = 0.1;
971  RobotDynamics::Body b(b1_mass, b1_center, RobotDynamics::Math::Vector3d(0.1, 0.1, 0.1));
975 
976  model->appendBody(Xtrans(Vector3d(0., 0., 0.)), RobotDynamics::Joint(JointTypeFloatingBase), b, "floating_base");
977  model->appendBody(Xtrans(Vector3d(0., 0., 0.)), j_x, b, "body1");
978  model->appendBody(Xtrans(Vector3d(1., 0., 0.)), j_y, b, "body2");
979  model->appendBody(Xtrans(Vector3d(0.1, 0.2, 0.3)), RobotDynamics::Joint(RobotDynamics::JointTypeEulerZYX), b, "euler_body");
980  model->appendBody(Xtrans(Vector3d(0., 1., -1.)), j_z, b, "body3");
981 
982  RobotDynamics::Math::VectorNd q(model->q_size);
983  RobotDynamics::Math::VectorNd qdot(model->qdot_size);
984 
985  Math::VectorNd N = Math::VectorNd::Zero(model->qdot_size);
986  Math::VectorNd G = Math::VectorNd::Zero(model->qdot_size);
987  Math::VectorNd C = Math::VectorNd::Zero(model->qdot_size);
988  N.setZero();
989  G.setZero();
990  C.setZero();
991 
992  q.setZero();
993  qdot.setZero();
994 
995  for (unsigned int i = 0; i < model->qdot_size; i++)
996  {
997  // At q=0, com is directly vertical and aligned with the joint
998  q[i] = 0.3 * M_PI * (static_cast<double>(rand()) / static_cast<double>(RAND_MAX)) - 0.3;
999  qdot[i] = 0.5 * (static_cast<double>(rand()) / static_cast<double>(RAND_MAX)) - 1.0;
1000  }
1001 
1002  nonlinearEffects(*model, q, qdot, N, true);
1003  coriolisEffects(*model, q, qdot, C, true);
1004  gravityEffects(*model, G);
1005 
1007 }
1008 
1010 {
1011  randomizeStates();
1012  model_emulated->gravity.SpatialVector::set(0., 0., 0., 0., 0., -9.81);
1013 
1014  Math::VectorNd N = Math::VectorNd::Zero(model_emulated->qdot_size);
1015  Math::VectorNd G = Math::VectorNd::Zero(model_emulated->qdot_size);
1016  Math::VectorNd C = Math::VectorNd::Zero(model_emulated->qdot_size);
1017  N.setZero();
1018  G.setZero();
1019  C.setZero();
1020 
1021  nonlinearEffects(*model_emulated, q, qdot, N, true);
1022  coriolisEffects(*model_emulated, q, qdot, C, true);
1023  gravityEffects(*model_emulated, G);
1024 
1026 }
1027 
1028 TEST_F(Human36, TestMInvTimesTauNoKinematics)
1029 {
1030  randomizeStates();
1031 
1032  MatrixNd M(MatrixNd::Zero(model_3dof->dof_count, model_3dof->dof_count));
1033  updateKinematicsCustom(*model_3dof, &q, nullptr, nullptr);
1034  compositeRigidBodyAlgorithm(*model_3dof, q, M, false);
1035 
1036  VectorNd qddot_solve_llt = M.llt().solve(tau);
1037 
1038  VectorNd qddot_minv(q);
1039  calcMInvTimesTau(*model_3dof, q, tau, qddot_minv);
1040 
1041  for (unsigned int j = 0; j < 10; j++)
1042  {
1043  randomizeStates();
1044 
1045  updateKinematicsCustom(*model_3dof, &q, nullptr, nullptr);
1046  compositeRigidBodyAlgorithm(*model_3dof, q, M, false);
1047  qddot_solve_llt = M.llt().solve(tau);
1048 
1049  calcMInvTimesTau(*model_3dof, q, tau, qddot_minv);
1050 
1051  EXPECT_TRUE(unit_test_utils::checkVectorNdEpsilonClose(qddot_solve_llt, qddot_minv, TEST_PREC * qddot_solve_llt.norm()));
1052  }
1053 }
1054 
1055 int main(int argc, char** argv)
1056 {
1057  ::testing::InitGoogleTest(&argc, argv);
1058  return RUN_ALL_TESTS();
1059 }
Joint joint_rot_z(SpatialVector(0., 0., 1., 0., 0., 0.))
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.
Definition: Dynamics.cc:302
std::vector< SpatialForce, Eigen::aligned_allocator< SpatialForce > > SpatialForceV
3 DoF joint that uses Euler ZYX convention (faster than emulated
Definition: Joint.h:197
Describes all properties of a single body.
Definition: Body.h:30
VectorNd Tau
unsigned int foot_left_id
User defined joints of varying size.
Definition: Joint.h:213
VectorNd QDDot
VectorNd QDot
Fixture that contains two models of which one has one joint fixed.
Definition: Fixtures.h:676
const double TEST_PREC
void coriolisEffects(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &Tau, bool update_kinematics=true)
Computes the coriolis forces.
Definition: Dynamics.cc:141
VectorNd Q
SpatialTransform Xtrans(const Vector3d &r)
Get pure translation transform.
A ForceVector is a SpatialVector containing 3 moments and 3 linear forces.
Definition: ForceVector.hpp:27
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.
Definition: Contacts.cc:27
bool checkModelZeroVectorsAndMatrices(RobotDynamics::Model &model)
EIGEN_STRONG_INLINE double & fy()
Get reference to y-linear component.
Body lower_leg_left_body
Math::MotionVector gravity
the cartesian vector of the gravity
Definition: Model.h:196
Body upper_leg_left_body
unsigned int hip_id
Body lower_leg_right_body
EIGEN_STRONG_INLINE double & fx()
Get reference to x-linear component.
const double TEST_PREC
unsigned int addBody(const unsigned int parent_id, const Math::SpatialTransform &joint_frame, const Joint &joint, const Body &body, std::string body_name="")
Connects a given body to the model.
Definition: Model.cc:271
EIGEN_STRONG_INLINE double & fz()
Get reference to z-linear component.
Body foot_right_body
EIGEN_STRONG_INLINE double & my()
Get reference to y-angular component.
Compact representation of spatial transformations.
Structure that contains both constraint information and workspace memory.
Definition: Contacts.h:168
Describes a joint relative to the predecessor body.
Definition: Joint.h:228
void calcBodyGravityWrench(Model &model, unsigned int body_id, RobotDynamics::Math::SpatialForce &gravity_wrench)
Calculate the wrench due to gravity on a body.
Definition: Dynamics.cc:207
Eigen::VectorXd VectorNd
Definition: rdl_eigenmath.h:25
EIGEN_STRONG_INLINE double & mz()
Get reference to z-angular component.
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...
Definition: Kinematics.cc:1310
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.
Definition: Kinematics.cc:25
Body hip_body
unsigned int foot_right_id
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...
Definition: Dynamics.cc:596
Contains all information about the rigid body model.
Definition: Model.h:121
A 6-DoF joint for floating-base (or freeflyer) systems.
Definition: Joint.h:204
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.
Definition: Kinematics.cc:72
bool bind(const Model &model)
Initializes and allocates memory for the constraint set.
Definition: Contacts.cc:62
Math types such as vectors and matrices and utility functions.
Definition: ForceVector.hpp:21
static bool checkSpatialVectorsEpsilonClose(const RobotDynamics::Math::SpatialVector &v1, const RobotDynamics::Math::SpatialVector &v2, const double epsilon)
Eigen::MatrixXd MatrixNd
Definition: rdl_eigenmath.h:26
A SpatialForce is a spatial vector with the angular part being three moments and the linear part bein...
void gravityEffects(Model &model, Math::VectorNd &Tau)
Computes the gravity vector.
Definition: Dynamics.cc:100
EIGEN_STRONG_INLINE double & mx()
Get reference to x-angular component.
Definition: ForceVector.hpp:96
TEST_F(Human36, TestNonlinearEffects)
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)
Definition: Dynamics.cc:23
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.
Definition: Dynamics.cc:455
static bool checkVectorNdEq(const RobotDynamics::Math::VectorNd &v1, const RobotDynamics::Math::VectorNd &v2)
Body foot_left_body
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.
Definition: Dynamics.cc:579
void nonlinearEffects(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &Tau, bool update_kinematics=true)
Computes the coriolis forces.
Definition: Dynamics.cc:236
unsigned int dof_count
number of degrees of freedoms of the model
Definition: Model.h:169
Namespace for all structures of the RobotDynamics library.
Definition: Body.h:21
Body upper_leg_right_body
int main(int argc, char **argv)


rdl_dynamics
Author(s):
autogenerated on Tue Apr 20 2021 02:25:27