Cheetah Software  1.0
test_dynamics.cpp File Reference

Test dynamics algorithms. More...

#include "Dynamics/Cheetah3.h"
#include "Dynamics/DynamicsSimulator.h"
#include "Dynamics/FloatingBaseModel.h"
#include "Dynamics/Quadruped.h"
#include "Utilities/utilities.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <stdio.h>
+ Include dependency graph for test_dynamics.cpp:

Go to the source code of this file.

Functions

 TEST (Dynamics, cheetah3model)
 
 TEST (Dynamics, cheetah3ModelTransforms)
 
 TEST (Dynamics, simulatorDynamicsABANoExternalForceCheetah3)
 
 TEST (Dynamics, inverseDynamicsNoContacts)
 
 TEST (Dynamics, contactJacobians)
 
 TEST (Dynamics, simulatorDynamicsWithExternalForceCheetah3)
 
 TEST (Dynamics, simulatorFootPosVelCheetah3)
 

Detailed Description

Test dynamics algorithms.

Test the dynamics algorithms in DynamicsSimulator and models of Cheetah 3

Test the model of Mini Cheetah

Definition in file test_dynamics.cpp.

Function Documentation

TEST ( Dynamics  ,
cheetah3model   
)

Generate a model of the Cheetah 3 and check its total mass, tree structure and sum of all spatial inertias (including rotors) Compared against MATLAB model

Definition at line 26 of file test_dynamics.cpp.

References almostEqual(), FloatingBaseModel< T >::check(), fpEqual(), FloatingBaseModel< T >::getBodyInertiaVector(), FloatingBaseModel< T >::getParentVector(), FloatingBaseModel< T >::getRotorInertiaVector(), FloatingBaseModel< T >::totalNonRotorMass(), FloatingBaseModel< T >::totalRotorMass(), and vectorEqual().

26  {
27  FloatingBaseModel<double> cheetah = buildCheetah3<double>().buildModel();
28  cheetah.check();
29 
30  // check total mass
31  EXPECT_TRUE(fpEqual(41.0737, cheetah.totalNonRotorMass(), .0001));
32  EXPECT_TRUE(fpEqual(6.3215, cheetah.totalRotorMass(), .0001));
33 
34  // check tree structure
35  std::vector<int> parentRef{0, 0, 0, 0, 0, 0, 5, 6, 7,
36  5, 9, 10, 5, 12, 13, 5, 15, 16};
37  EXPECT_TRUE(vectorEqual(parentRef, cheetah.getParentVector()));
38 
39  // this is kind of stupid, but a reasonable sanity check for inertias
40  Mat6<double> inertiaSumRef;
41  inertiaSumRef << 0.4352, -0.0000, -0.0044, 0, 0.6230, -0.0000, -0.0000,
42  1.0730, 0.0000, -0.6230, 0, -0.0822, -0.0044, 0.0000, 1.0071, 0.0000,
43  0.0822, 0, 0, -0.6230, 0.0000, 42.6540, 0, 0, 0.6230, 0, 0.0822, 0,
44  42.6540, 0, -0.0000, -0.0822, 0, 0, 0, 42.6540;
45 
46  Mat6<double> inertiaSum = Mat6<double>::Zero();
47 
48  for (size_t i = 0; i < 18; i++) {
49  inertiaSum += cheetah.getBodyInertiaVector()[i].getMatrix() +
50  cheetah.getRotorInertiaVector()[i].getMatrix() * 0.25;
51  }
52  EXPECT_TRUE(almostEqual(inertiaSum, inertiaSumRef, .0001));
53 }
bool fpEqual(T a, T b, T tol)
Definition: utilities.h:15
typename Eigen::Matrix< T, 6, 6 > Mat6
Definition: cppTypes.h:70
const std::vector< int > & getParentVector()
const std::vector< SpatialInertia< T >, Eigen::aligned_allocator< SpatialInertia< T > > > & getBodyInertiaVector()
const std::vector< SpatialInertia< T >, Eigen::aligned_allocator< SpatialInertia< T > > > & getRotorInertiaVector()
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
bool vectorEqual(const std::vector< T > &a, const std::vector< T > &b)
Definition: utilities.h:23

+ Here is the call graph for this function:

TEST ( Dynamics  ,
cheetah3ModelTransforms   
)

Test the model transforms

Definition at line 58 of file test_dynamics.cpp.

References FloatingBaseModel< T >::_Xrot, FloatingBaseModel< T >::_Xtree, and almostEqual().

58  {
59  FloatingBaseModel<double> cheetah = buildCheetah3<double>().buildModel();
62  for (size_t i = 0; i < 18; i++) {
63  XTotal = XTotal + cheetah._Xtree[i];
64  XRotTotal = XRotTotal + cheetah._Xrot[i];
65  }
66  Mat6<double> Xtr, Xrtr;
67  Xtr << 11.0000, 0.0000, 0, 0, 0, 0, -0.0000, 11.0000, 0, 0, 0, 0, 0, 0,
68  19.0000, 0, 0, 0, 0, -1.3680, 0, 11.0000, 0.0000, 0, 1.3680, 0, 0.0000,
69  -0.0000, 11.0000, 0, 0.0000, 0, 0, 0, 0, 19.0000;
70  Xrtr << 11.0000, 0.0000, 0, 0, 0, 0, -0.0000, 11.0000, 0, 0, 0, 0, 0, 0,
71  19.0000, 0, 0, 0, 0, 0, 0.0000, 11.0000, 0.0000, 0, 0, 0, 0, -0.0000,
72  11.0000, 0, 0, 0, 0, 0, 0, 19.0000;
73 
74  EXPECT_TRUE(almostEqual(Xtr, XTotal, .0005));
75  EXPECT_TRUE(almostEqual(Xrtr, XRotTotal, .0005));
76 }
vector< Mat6< T >, Eigen::aligned_allocator< Mat6< T > > > _Xrot
typename Eigen::Matrix< T, 6, 6 > Mat6
Definition: cppTypes.h:70
vector< Mat6< T >, Eigen::aligned_allocator< Mat6< T > > > _Xtree
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23

+ Here is the call graph for this function:

TEST ( Dynamics  ,
simulatorDynamicsABANoExternalForceCheetah3   
)

Run the articulated body algorithm (and forward kinematics) on Cheetah 3 Set a weird body orientation, velocity, q, dq, and tau Checks that quatD, pd, vd, and qdd match MATLAB

Definition at line 83 of file test_dynamics.cpp.

References almostEqual(), FBModelState< T >::bodyOrientation, FBModelState< T >::bodyPosition, FBModelState< T >::bodyVelocity, ori::coordinateRotation(), FBModelStateDerivative< T >::dBodyPosition, FBModelStateDerivative< T >::dBodyVelocity, DynamicsSimulator< T >::forwardKinematics(), fpEqual(), DynamicsSimulator< T >::getDState(), DynamicsSimulator< T >::getState(), DynamicsSimulator< T >::integrate(), FBModelState< T >::q, FBModelState< T >::qd, FBModelStateDerivative< T >::qdd, ori::rotationMatrixToQuaternion(), DynamicsSimulator< T >::runABA(), and DynamicsSimulator< T >::setState().

83  {
84  FloatingBaseModel<double> cheetahModel = buildCheetah3<double>().buildModel();
85  DynamicsSimulator<double> sim(cheetahModel, true);
86 
87  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
88  coordinateRotation(CoordinateAxis::Z, .232) *
89  coordinateRotation(CoordinateAxis::Y, .111);
90 
91  SVec<double> bodyVel;
92  bodyVel << 1, 2, 3, 4, 5, 6;
94  DVec<double> q(12);
95  DVec<double> dq(12);
96  DVec<double> tau(12);
97  for (size_t i = 0; i < 12; i++) {
98  q[i] = i + 1;
99  dq[i] = (i + 1) * 2;
100  tau[i] = (i + 1) * -30.;
101  }
102 
103  // set state
104  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
105  x.bodyVelocity = bodyVel;
106  x.bodyPosition = Vec3<double>(6, 7, 8);
107  x.q = q;
108  x.qd = dq;
109 
110  // do aba
111  sim.setState(x);
112  sim.forwardKinematics();
113  sim.runABA(tau);
114 
115  // check:
116  Vec3<double> pdRef(4.3717, 4.8598, 5.8541);
117  SVec<double> vbdRef;
118  vbdRef << 455.5224, 62.1684, -70.56, -11.4505, 10.2354, -15.2394;
119 
120  DVec<double> qddRef(12);
121  qddRef << -0.7924, -0.2205, -0.9163, -1.6136, -0.4328, -1.6911, -2.9878,
122  -0.9358, -2.6194, -3.3773, -1.3235, -3.1598;
123  qddRef *= 1000;
124 
125  EXPECT_TRUE(almostEqual(pdRef, sim.getDState().dBodyPosition, .001));
126  EXPECT_TRUE(almostEqual(vbdRef, sim.getDState().dBodyVelocity, .001));
127 
128  for (size_t i = 0; i < 12; i++) {
129  // the qdd's are large - see qddRef, so we're only accurate to within ~1.
130  EXPECT_TRUE(fpEqual(sim.getDState().qdd[i], qddRef[i], 3.));
131  }
132 
133  // check the integrator for the body (orientation, position, and spatial
134  // velocity). we use a huge timestep here so that any error in the integrator
135  // isn't multiplied by something small
136  sim.integrate(2.);
137 
138  Quat<double> quat2Ref(-0.8962, -0.0994, -0.2610, -0.3446);
139  Vec3<double> x2Ref(14.7433, 16.7196, 19.7083);
140  SVec<double> v2Ref;
141  v2Ref << 912.0449, 126.3367, -138.1201, -18.9011, 25.4709, -24.4788;
142 
143  EXPECT_TRUE(almostEqual(quat2Ref, sim.getState().bodyOrientation, .0002));
144  EXPECT_TRUE(almostEqual(x2Ref, sim.getState().bodyPosition, .0002));
145  EXPECT_TRUE(almostEqual(v2Ref, sim.getState().bodyVelocity, .0002));
146 }
Vec3< T > bodyPosition
bool fpEqual(T a, T b, T tol)
Definition: utilities.h:15
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
typename Eigen::Matrix< T, 4, 1 > Quat
Definition: cppTypes.h:58
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Quat< typename T::Scalar > rotationMatrixToQuaternion(const Eigen::MatrixBase< T > &r1)
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation

+ Here is the call graph for this function:

TEST ( Dynamics  ,
inverseDynamicsNoContacts   
)

Run the RNEA and component H/Cqd/G algorithms on Cheetah 3 Set a weird body orientation, velocity, q, dq, qdd Checks that genForce matches MATLAB, and CRBA/Cqd/G agree the output as well

Definition at line 153 of file test_dynamics.cpp.

References almostEqual(), FBModelState< T >::bodyOrientation, FBModelState< T >::bodyPosition, FBModelState< T >::bodyVelocity, ori::coordinateRotation(), FBModelStateDerivative< T >::dBodyVelocity, FloatingBaseModel< T >::generalizedCoriolisForce(), FloatingBaseModel< T >::generalizedGravityForce(), FloatingBaseModel< T >::inverseDynamics(), FloatingBaseModel< T >::massMatrix(), FBModelState< T >::q, FBModelState< T >::qd, FBModelStateDerivative< T >::qdd, ori::rotationMatrixToQuaternion(), and FloatingBaseModel< T >::setState().

153  {
154  FloatingBaseModel<double> cheetahModel = buildCheetah3<double>().buildModel();
155 
156  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
157  coordinateRotation(CoordinateAxis::Z, .232) *
158  coordinateRotation(CoordinateAxis::Y, .111);
159  SVec<double> bodyVel;
160  bodyVel << 1, 2, 3, 4, 5, 6;
162  DVec<double> q(12);
163  DVec<double> dq(12);
164  DVec<double> tauref(12);
165  for (size_t i = 0; i < 12; i++) {
166  q[i] = i + 1;
167  dq[i] = (i + 1) * 2;
168  tauref[i] = (i + 1) * -30.;
169  }
170 
171  // set state
172  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
173  x.bodyVelocity = bodyVel;
174  x.bodyPosition = Vec3<double>(6, 7, 8);
175  x.q = q;
176  x.qd = dq;
177  cheetahModel.setState(x);
178 
179  // Construct state derivative
180  SVec<double> vbd;
181  vbd << 455.5224, 62.1684, -70.56, -11.4505, 10.2354, -15.2394;
182 
183  DVec<double> qdd(12);
184  qdd << -0.7924, -0.2205, -0.9163, -1.6136, -0.4328, -1.6911, -2.9878, -0.9358,
185  -2.6194, -3.3773, -1.3235, -3.1598;
186  qdd *= 1000;
187 
189  dx.dBodyVelocity = vbd;
190  dx.qdd = qdd;
191 
192  // Vector form of state derivative
193  DVec<double> nu_dot(18);
194  nu_dot.head(6) = dx.dBodyVelocity;
195  nu_dot.tail(12) = qdd;
196 
197  // Components of the equations
198  DMat<double> H = cheetahModel.massMatrix();
199  DVec<double> Cqd = cheetahModel.generalizedCoriolisForce();
200  DVec<double> G = cheetahModel.generalizedGravityForce();
201 
202  // Compute ID two different ways
203  DVec<double> genForce = cheetahModel.inverseDynamics(dx);
204  DVec<double> component_ID_result = H * nu_dot + Cqd + G;
205 
206  SVec<double> zero6x1 = SVec<double>::Zero();
207  DVec<double> tauReturn = genForce.tail(12);
208  SVec<double> fReturn = genForce.head(6);
209 
210  EXPECT_TRUE(almostEqual(zero6x1, fReturn, .03));
211  EXPECT_TRUE(almostEqual(tauref, tauReturn, .01));
212  EXPECT_TRUE(almostEqual(component_ID_result, genForce, 1e-6));
213 }
Vec3< T > bodyPosition
DVec< T > inverseDynamics(const FBModelStateDerivative< T > &dState)
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
DVec< T > generalizedCoriolisForce()
typename Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > DMat
Definition: cppTypes.h:106
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Quat< typename T::Scalar > rotationMatrixToQuaternion(const Eigen::MatrixBase< T > &r1)
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
void setState(const FBModelState< T > &state)
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
DVec< T > generalizedGravityForce()
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation

+ Here is the call graph for this function:

TEST ( Dynamics  ,
contactJacobians   
)

Computes Jacobians and bias forces for contacts Checks that finite differenced contact positions equal velocities and finite differenced contact velocities equal J*nu_dot + Jdot*nu

Definition at line 220 of file test_dynamics.cpp.

References FloatingBaseModel< T >::_Jc, FloatingBaseModel< T >::_Jcdqd, FloatingBaseModel< T >::_pGC, FloatingBaseModel< T >::_vGC, almostEqual(), FBModelState< T >::bodyOrientation, FBModelState< T >::bodyPosition, FBModelState< T >::bodyVelocity, FloatingBaseModel< T >::contactJacobians(), ori::coordinateRotation(), FBModelStateDerivative< T >::dBodyPosition, FBModelStateDerivative< T >::dBodyVelocity, FBModelState< T >::q, FBModelState< T >::qd, FBModelStateDerivative< T >::qdd, ori::quaternionToRotationMatrix(), ori::quatProduct(), ori::rotationMatrixToQuaternion(), and FloatingBaseModel< T >::setState().

220  {
221  FloatingBaseModel<double> cheetahModel = buildCheetah3<double>().buildModel();
222 
223  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
224  coordinateRotation(CoordinateAxis::Z, .232) *
225  coordinateRotation(CoordinateAxis::Y, .111);
226  SVec<double> bodyVel;
227  bodyVel << 1, 2, 3, 4, 5, 6;
229  DVec<double> q(12);
230  DVec<double> dq(12);
231  DVec<double> tauref(12);
232  for (size_t i = 0; i < 12; i++) {
233  q[i] = i + 1;
234  dq[i] = (i + 1) * 2;
235  tauref[i] = (i + 1) * -30.;
236  }
237 
238  // set state
239  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
240  x.bodyVelocity = bodyVel;
241  x.bodyPosition = Vec3<double>(6, 7, 8);
242  x.q = q;
243  x.qd = dq;
244  cheetahModel.setState(x);
245 
246  // Construct state derivative
247  SVec<double> vbd;
248  vbd << 45.5224, 62.1684, -70.56, -11.4505, 10.2354, -15.2394;
249 
250  DVec<double> qdd(12);
251  qdd << -0.7924, -0.2205, -0.9163, -1.6136, -0.4328, -1.6911, -2.9878, -0.9358,
252  -2.6194, -3.3773, -1.3235, -3.1598;
253  qdd *= 400;
254 
256  dx.dBodyVelocity = vbd;
257  dx.qdd = qdd;
258 
259  // Vector form of state derivative
260  DVec<double> nu(18), nu_dot(18);
261  nu.head(6) = x.bodyVelocity;
262  nu.tail(12) = x.qd;
263 
264  nu_dot.head(6) = dx.dBodyVelocity;
265  nu_dot.tail(12) = qdd;
266 
267  cheetahModel.contactJacobians();
268 
269  // Compute Positions
270  Vec3<double> pos0, posf, vel0, vel0_fromJ, velf, acc0, J0dqd;
271  pos0 = cheetahModel._pGC[15];
272  vel0 = cheetahModel._vGC[15];
273  D3Mat<double> J0 = cheetahModel._Jc[15];
274  vel0_fromJ = J0 * nu;
275  acc0 = J0 * nu_dot + cheetahModel._Jcdqd[15];
276 
277  double dt = 1e-9;
278 
279  // Integrate the state
281  dx.dBodyPosition = Rup.transpose() * x.bodyVelocity.tail(3);
282 
283  Vec3<double> omega0 = Rup.transpose() * x.bodyVelocity.head(3);
284  Vec3<double> axis;
285  double ang = omega0.norm();
286  axis = omega0 / ang;
287 
288  ang *= dt;
289  Vec3<double> ee = std::sin(ang / 2) * axis;
290  Quat<double> quatD(std::cos(ang / 2), ee[0], ee[1], ee[2]);
291  Quat<double> quatNew = quatProduct(quatD, x.bodyOrientation);
292  quatNew = quatNew / quatNew.norm();
293 
294  // actual integration
295  x.q += x.qd * dt;
296  x.qd += dx.qdd * dt;
297  x.bodyVelocity += dx.dBodyVelocity * dt;
298  x.bodyPosition += dx.dBodyPosition * dt;
299  x.bodyOrientation = quatNew;
300 
301  cheetahModel.setState(x);
302  cheetahModel.contactJacobians();
303 
304  // Final
305  posf = cheetahModel._pGC[15];
306  velf = cheetahModel._vGC[15];
307 
308  // Finite Difference
309  Vec3<double> vel_fd, acc_fd;
310  vel_fd = (posf - pos0) / dt;
311  acc_fd = (velf - vel0) / dt;
312 
313  EXPECT_TRUE(almostEqual(vel0, vel0_fromJ, 1e-6));
314  EXPECT_TRUE(almostEqual(vel_fd, vel0, 1e-5));
315  EXPECT_TRUE(almostEqual(acc_fd, acc0, 1e-3));
316 }
Vec3< T > bodyPosition
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Vec3< T > dBodyPosition
typename Eigen::Matrix< T, 3, 3 > Mat3
Definition: cppTypes.h:54
typename Eigen::Matrix< T, 4, 1 > Quat
Definition: cppTypes.h:58
vectorAligned< Vec3< T > > _Jcdqd
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
vector< Vec3< T > > _vGC
typename Eigen::Matrix< T, 3, Eigen::Dynamic > D3Mat
Definition: cppTypes.h:114
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Quat< typename T::Scalar > rotationMatrixToQuaternion(const Eigen::MatrixBase< T > &r1)
Quat< typename T::Scalar > quatProduct(const Eigen::MatrixBase< T > &q1, const Eigen::MatrixBase< T > &q2)
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
void setState(const FBModelState< T > &state)
vector< Vec3< T > > _pGC
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
vectorAligned< D3Mat< T > > _Jc
Mat3< typename T::Scalar > quaternionToRotationMatrix(const Eigen::MatrixBase< T > &q)
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation

+ Here is the call graph for this function:

TEST ( Dynamics  ,
simulatorDynamicsWithExternalForceCheetah3   
)

Run the articulated body algorithm (and forward kinematics) on Cheetah 3 Set a weird body orientation, velocity, q, dq, and tau Sets external spatial forces on all bodies Checks that quatD, pd, vd, and qdd match MATLAB

Definition at line 324 of file test_dynamics.cpp.

References almostEqual(), FBModelState< T >::bodyOrientation, FBModelState< T >::bodyPosition, FBModelState< T >::bodyVelocity, ori::coordinateRotation(), FBModelStateDerivative< T >::dBodyPosition, FBModelStateDerivative< T >::dBodyVelocity, fpEqual(), DynamicsSimulator< T >::getDState(), FBModelState< T >::q, FBModelState< T >::qd, FBModelStateDerivative< T >::qdd, ori::rotationMatrixToQuaternion(), DynamicsSimulator< T >::setAllExternalForces(), DynamicsSimulator< T >::setState(), and DynamicsSimulator< T >::step().

324  {
325  FloatingBaseModel<double> cheetahModel = buildCheetah3<double>().buildModel();
326  DynamicsSimulator<double> sim(cheetahModel, true);
327 
328  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
329  coordinateRotation(CoordinateAxis::Z, .232) *
330  coordinateRotation(CoordinateAxis::Y, .111);
331  SVec<double> bodyVel;
332  bodyVel << 1, 2, 3, 4, 5, 6;
334  DVec<double> q(12);
335  DVec<double> dq(12);
336  DVec<double> tau(12);
337  for (size_t i = 0; i < 12; i++) {
338  q[i] = i + 1;
339  dq[i] = (i + 1) * 2;
340  tau[i] = (i + 1) * -30.;
341  }
342 
343  // set state
344  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
345  x.bodyVelocity = bodyVel;
346  x.bodyPosition = Vec3<double>(6, 7, 8);
347  x.q = q;
348  x.qd = dq;
349 
350  // generate external forces
351  vectorAligned<SVec<double>> forces(18);
352  for (size_t i = 0; i < 18; i++) {
353  for (size_t j = 0; j < 6; j++) {
354  forces[i][j] = i + j + 1;
355  }
356  }
357 
358  // do aba
359  sim.setState(x);
360  sim.setAllExternalForces(forces);
361  sim.step(0.0, tau, 5e5, 5e3);
362 
363  // check:
364  Vec3<double> pdRef(4.3717, 4.8598, 5.8541);
365  SVec<double> vbdRef;
366  vbdRef << 806.6664, 44.1266, 33.8287, -10.1360, 2.1066, 12.1677;
367 
368  DVec<double> qddRef(12);
369  qddRef << -0.5630, -0.1559, -1.0182, -0.9012, -0.3585, -1.6170, -2.0995,
370  -0.8959, -2.7325, -2.0808, -1.3134, -3.1206;
371  qddRef *= 1000;
372 
373  EXPECT_TRUE(almostEqual(pdRef, sim.getDState().dBodyPosition, .001));
374  EXPECT_TRUE(almostEqual(vbdRef, sim.getDState().dBodyVelocity, .001));
375 
376  for (size_t i = 0; i < 12; i++) {
377  // the qdd's are large - see qddRef, so we're only accurate to within ~1.
378  EXPECT_TRUE(fpEqual(sim.getDState().qdd[i], qddRef[i], 3.));
379  }
380 }
Vec3< T > bodyPosition
bool fpEqual(T a, T b, T tol)
Definition: utilities.h:15
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Quat< typename T::Scalar > rotationMatrixToQuaternion(const Eigen::MatrixBase< T > &r1)
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
typename std::vector< T, Eigen::aligned_allocator< T >> vectorAligned
Definition: cppTypes.h:118
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation

+ Here is the call graph for this function:

TEST ( Dynamics  ,
simulatorFootPosVelCheetah3   
)

Run the articulated body algorithm (and forward kinematics) on Cheetah 3 Set a weird body orientation, velocity, q, dq, and tau Checks that foot position and velocities match MATLAB

Definition at line 387 of file test_dynamics.cpp.

References FloatingBaseModel< T >::_pGC, FloatingBaseModel< T >::_vGC, almostEqual(), FBModelState< T >::bodyOrientation, FBModelState< T >::bodyPosition, FBModelState< T >::bodyVelocity, ori::coordinateRotation(), DynamicsSimulator< T >::getModel(), FBModelState< T >::q, FBModelState< T >::qd, ori::rotationMatrixToQuaternion(), DynamicsSimulator< T >::setAllExternalForces(), DynamicsSimulator< T >::setState(), and DynamicsSimulator< T >::step().

387  {
388  FloatingBaseModel<double> cheetahModel = buildCheetah3<double>().buildModel();
389  DynamicsSimulator<double> sim(cheetahModel);
390 
391  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
392  coordinateRotation(CoordinateAxis::Z, .232) *
393  coordinateRotation(CoordinateAxis::Y, .111);
394  SVec<double> bodyVel;
395  bodyVel << 1, 2, 3, 4, 5, 6;
397  DVec<double> q(12);
398  DVec<double> dq(12);
399  DVec<double> tau(12);
400  for (size_t i = 0; i < 12; i++) {
401  q[i] = i + 1;
402  dq[i] = (i + 1) * 2;
403  tau[i] = (i + 1) * -30.;
404  }
405 
406  // set state
407  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
408  x.bodyVelocity = bodyVel;
409  x.bodyPosition = Vec3<double>(6, 7, 8);
410  x.q = q;
411  x.qd = dq;
412 
413  // generate external forces
414  vectorAligned<SVec<double>> forces(18);
415  for (size_t i = 0; i < 18; i++) {
416  for (size_t j = 0; j < 6; j++) {
417  forces[i][j] = i + j + 1;
418  }
419  }
420 
421  // fwd kin is included in this
422  sim.setState(x);
423  sim.setAllExternalForces(forces);
424  sim.step(0.0, tau, 5e5, 5e3);
425 
426  // Vec3<double> bodypRef1ML(6.25, 6.8271, 8.155);
427  Vec3<double> bodypRef1ML(6.260735, 6.812413, 8.056675);
428  Vec3<double> footpRefML(5.1594, 7.3559, 7.674);
429  // Vec3<double> bodyvRef1ML(5.1989, 5.4008, 5.1234);
430  Vec3<double> bodyvRef1ML(5.028498, 5.540016, 5.083884);
431  Vec3<double> footvRefML(-9.3258, -0.1926, 26.3323);
432 
433  // I add the body points in a different order, so comparing them is kind of
434  // annoying. this just tests one body point and one foot point.
435  EXPECT_TRUE(almostEqual(bodypRef1ML, sim.getModel()._pGC.at(2), .0005));
436  EXPECT_TRUE(almostEqual(footpRefML, sim.getModel()._pGC.at(15), .0005));
437  EXPECT_TRUE(almostEqual(bodyvRef1ML, sim.getModel()._vGC.at(2), .0005));
438  EXPECT_TRUE(almostEqual(footvRefML, sim.getModel()._vGC.at(15), .0005));
439 }
Vec3< T > bodyPosition
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Quat< typename T::Scalar > rotationMatrixToQuaternion(const Eigen::MatrixBase< T > &r1)
bool almostEqual(const Eigen::MatrixBase< T > &a, const Eigen::MatrixBase< T > &b, T2 tol)
Definition: MathUtilities.h:23
typename std::vector< T, Eigen::aligned_allocator< T >> vectorAligned
Definition: cppTypes.h:118
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation

+ Here is the call graph for this function: