Cheetah Software  1.0
test_mini_cheetah_model.cpp
Go to the documentation of this file.
1 
9 #include "Dynamics/MiniCheetah.h"
10 #include "Dynamics/Quadruped.h"
11 #include "Utilities/utilities.h"
12 
13 #include <iostream>
14 
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 
19 
20 using namespace spatial;
21 
25 TEST(MiniCheetah, miniCheetahModel1) {
26  FloatingBaseModel<double> cheetah = buildMiniCheetah<double>().buildModel();
27 
28  // masses
29  EXPECT_TRUE(fpEqual(8.2520, cheetah.totalNonRotorMass(), .0001));
30  EXPECT_TRUE(fpEqual(0.66, cheetah.totalRotorMass(), .0001));
31 
32  // check tree structure
33  std::vector<int> parentRef{0, 0, 0, 0, 0, 0, 5, 6, 7,
34  5, 9, 10, 5, 12, 13, 5, 15, 16};
35  EXPECT_TRUE(vectorEqual(parentRef, cheetah.getParentVector()));
36 
37  // this is kind of stupid, but a reasonable sanity check for inertias
38  Mat6<double> inertiaSumRef;
39  inertiaSumRef <<
40  // 0.0272, 0, 0.0001, 0, 0.0663, 0,
41  // 0, 0.3758, 0.0, -0.0663, 0, 0,
42  // 0.0001, 0.0000, 0.0497, 0, 0, 0,
43  // 0, -0.0663, 0, 8.4170, 0, 0,
44  // 0.0663, 0, 0, 0, 8.4170, 0,
45  // 0, 0, 0, 0, 0, 8.4170;
46 
47  0.0272,
48  0, 0, 0, 0.0663, 0, 0, 0.05, 0, -0.066336, 0, 0, 0, 0, 0.0497, 0, 0, 0, 0,
49  -0.066336, 0, 8.417, 0, 0, 0.066336, 0, 0, 0, 8.417, 0, 0, 0, 0, 0, 0,
50  8.417;
51 
52  Mat6<double> inertiaSum = Mat6<double>::Zero();
53 
54  for (size_t i = 0; i < 18; i++) {
55  inertiaSum += cheetah.getBodyInertiaVector()[i].getMatrix() +
56  cheetah.getRotorInertiaVector()[i].getMatrix() * 0.25;
57  }
58 
59  EXPECT_TRUE(almostEqual(inertiaSum, inertiaSumRef, .0003));
60 }
61 
65 TEST(MiniCheetah, miniCheetahModel2) {
66  FloatingBaseModel<double> cheetah = buildMiniCheetah<double>().buildModel();
69  for (size_t i = 0; i < 18; i++) {
70  XTotal = XTotal + cheetah._Xtree[i];
71  XRotTotal = XRotTotal + cheetah._Xrot[i];
72  }
73  Mat6<double> Xtr, Xrtr;
74  Xtr << 11.0000, 0.0000, 0, 0, 0, 0, -0.0000, 11.0000, 0, 0, 0, 0, 0, 0,
75  19.0000, 0, 0, 0, 0, -0.8360, 0, 11.0000, 0.0000, 0, 0.8360, 0, 0.0000,
76  -0.0000, 11.0000, 0, 0, 0, 0, 0, 0, 19.0000;
77 
78  Xrtr << 11.0000, 0.0000, 0, 0, 0, 0, -0.0000, 11.0000, 0, 0, 0, 0, 0, 0,
79  19.0000, 0, 0, 0, 0, 0, 0, 11.0000, 0.0000, 0, 0, 0, 0.0000, -0.0000,
80  11.0000, 0, 0.0000, 0, 0, 0, 0, 19.0000;
81 
82  EXPECT_TRUE(almostEqual(Xtr, XTotal, .0005));
83  EXPECT_TRUE(almostEqual(Xrtr, XRotTotal, .0005));
84 }
85 
90 TEST(MiniCheetah, simulatorDynamicsDoesntCrashMiniCheetah) {
91  FloatingBaseModel<double> cheetah = buildMiniCheetah<double>().buildModel();
92  DynamicsSimulator<double> sim(cheetah);
93  DVec<double> tau(12);
94  sim.forwardKinematics();
95  sim.runABA(tau);
96 }
97 
103 TEST(MiniCheetah, simulatorDynamicsABANoExternalForceMiniCheetah) {
104  FloatingBaseModel<double> cheetahModel =
105  buildMiniCheetah<double>().buildModel();
106  DynamicsSimulator<double> sim(cheetahModel);
107 
108  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
109  coordinateRotation(CoordinateAxis::Z, .232) *
110  coordinateRotation(CoordinateAxis::Y, .111);
111  SVec<double> bodyVel;
112  bodyVel << 1, 2, 3, 4, 5, 6;
114  DVec<double> q(12);
115  DVec<double> dq(12);
116  DVec<double> tau(12);
117  for (size_t i = 0; i < 12; i++) {
118  q[i] = i + 1;
119  dq[i] = (i + 1) * 2;
120  tau[i] = (i + 1) * -3.;
121  }
122 
123  // set state
124  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
125  x.bodyVelocity = bodyVel;
126  x.bodyPosition = Vec3<double>(6, 7, 8);
127  x.q = q;
128  x.qd = dq;
129 
130  // do aba
131  sim.setState(x);
132  sim.forwardKinematics();
133  sim.runABA(tau);
134 
135  // check:
136  Vec3<double> pdRef(4.3717, 4.8598, 5.8541);
137  SVec<double> vbdRef;
138  vbdRef << 1217.31, -182.793, -171.524, -4.09393, 33.6798, -59.975;
139 
140  DVec<double> qddRef(12);
141  qddRef << -1946.36, -1056.62, -1470.57, -3133.03, -1263.89, -2626.9, -6637.38,
142  -4071.88, -4219.14, -7554.08, -3392.44, -5112.85;
143 
144  EXPECT_TRUE(almostEqual(pdRef, sim.getDState().dBodyPosition, .001));
145  EXPECT_TRUE(almostEqual(vbdRef, sim.getDState().dBodyVelocity, 1));
146 
147  for (size_t i = 0; i < 12; i++) {
148  // the qdd's are large - see qddRef, so we're only accurate to within ~1.
149  EXPECT_TRUE(fpEqual(sim.getDState().qdd[i], qddRef[i], 3.));
150  }
151 }
152 
159 TEST(MiniCheetah, simulatorDynamicsWithExternalForceMiniCheetah) {
160  FloatingBaseModel<double> cheetahModel =
161  buildMiniCheetah<double>().buildModel();
162  DynamicsSimulator<double> sim(cheetahModel, true);
163 
164  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
165  coordinateRotation(CoordinateAxis::Z, .232) *
166  coordinateRotation(CoordinateAxis::Y, .111);
167  SVec<double> bodyVel;
168  bodyVel << 1, 2, 3, 4, 5, 6;
170  DVec<double> q(12);
171  DVec<double> dq(12);
172  DVec<double> tau(12);
173  for (size_t i = 0; i < 12; i++) {
174  q[i] = i + 1;
175  dq[i] = (i + 1) * 2;
176  tau[i] = (i + 1) * -3.;
177  }
178 
179  // set state
180  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
181  x.bodyVelocity = bodyVel;
182  x.bodyPosition = Vec3<double>(6, 7, 8);
183  x.q = q;
184  x.qd = dq;
185 
186  // generate external forces
187  vectorAligned<SVec<double>> forces(18);
188  for (size_t i = 0; i < 18; i++) {
189  for (size_t j = 0; j < 6; j++) {
190  forces[i][j] = .3 * (i + j + 1);
191  }
192  }
193 
194  // do aba
195  sim.setState(x);
196  sim.setAllExternalForces(forces);
197  sim.step(0.0, tau, 5e5, 5e3);
198 
199  // check:
200  Vec3<double> pdRef(4.3717, 4.8598, 5.8541);
201  SVec<double> vbdRef;
202  vbdRef << 3153.46, 42.6931, 264.584, -3.80573, -53.3519, 68.5713;
203 
204  DVec<double> qddRef(12);
205  qddRef << -1211.85, -1167.39, -2024.94, 394.414, -297.854, -2292.29, -1765.92,
206  -4040.78, -4917.41, 149.368, -2508.2, -4969.02;
207 
208  EXPECT_TRUE(almostEqual(pdRef, sim.getDState().dBodyPosition, .001));
209  EXPECT_TRUE(almostEqual(vbdRef, sim.getDState().dBodyVelocity, .01));
210 
211  for (size_t i = 0; i < 12; i++) {
212  // the qdd's are large - see qddRef, so we're only accurate to within ~1.
213  EXPECT_TRUE(fpEqual(sim.getDState().qdd[i], qddRef[i], 3.));
214  }
215 }
216 
222 TEST(MiniCheetah, simulatorFootPosVelMiniCheetah) {
223  FloatingBaseModel<double> cheetahModel =
224  buildMiniCheetah<double>().buildModel();
225  DynamicsSimulator<double> sim(cheetahModel);
226 
227  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, .123) *
228  coordinateRotation(CoordinateAxis::Z, .232) *
229  coordinateRotation(CoordinateAxis::Y, .111);
230  SVec<double> bodyVel;
231  bodyVel << 1, 2, 3, 4, 5, 6;
233  DVec<double> q(12);
234  DVec<double> dq(12);
235  DVec<double> tau(12);
236  for (size_t i = 0; i < 12; i++) {
237  q[i] = i + 1;
238  dq[i] = (i + 1) * 2;
239  tau[i] = (i + 1) * -30.;
240  }
241 
242  // set state
243  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
244  x.bodyVelocity = bodyVel;
245  x.bodyPosition = Vec3<double>(6, 7, 8);
246  x.q = q;
247  x.qd = dq;
248 
249  // generate external forces
250  vectorAligned<SVec<double>> forces(18);
251  for (size_t i = 0; i < 18; i++) {
252  for (size_t j = 0; j < 6; j++) {
253  forces[i][j] = i + j + 1;
254  }
255  }
256 
257  // fwd kin is included in this
258  sim.setState(x);
259  sim.setAllExternalForces(forces);
260  sim.step(0.0, tau, 5e5, 5e3);
261 
262  Vec3<double> footpRefML(5.4937, 7.1459, 7.8096);
263  Vec3<double> footvRefML(-2.5284, 2.0944, 16.3732);
264 
265  // I add the body points in a different order, so comparing them is kind of
266  // annoying. this just one foot point.
267  EXPECT_TRUE(almostEqual(footpRefML, sim.getModel()._pGC.at(15), .0005));
268  EXPECT_TRUE(almostEqual(footvRefML, sim.getModel()._vGC.at(15), .0005));
269 }
270 
274 TEST(MiniCheetah, hipLocationConvention) {
275  Vec3<double> hipLocationRef[4];
276  hipLocationRef[0] = Vec3<double>(0.19, -0.049, 0.0);
277  hipLocationRef[1] = Vec3<double>(0.19, 0.049, 0.0);
278  hipLocationRef[2] = Vec3<double>(-0.19, -0.049, 0.0);
279  hipLocationRef[3] = Vec3<double>(-0.19, 0.049, 0.0);
280 
281  Vec3<double> hipLocations[4];
282 
283  auto quadruped = buildMiniCheetah<double>();
284 
285  for (int i = 0; i < 4; i++) {
286  hipLocations[i] = quadruped.getHipLocation(i);
287  }
288 
289  for (int i = 0; i < 4; i++) {
290  // std::cout << "ref: " << hipLocationRef[i].transpose() << "\nact: " <<
291  // hipLocations[i].transpose() << "\n\n";
292  EXPECT_TRUE(almostEqual(hipLocations[i], hipLocationRef[i], .0001));
293  }
294 }
295 
296 TEST(MiniCheetah, ContactPositionVelocity) {
297  FloatingBaseModel<double> cheetahModel =
298  buildMiniCheetah<double>().buildModel();
299  DynamicsSimulator<double> sim(cheetahModel);
300 
301  RotMat<double> rBody = coordinateRotation(CoordinateAxis::X, 0.0) *
302  coordinateRotation(CoordinateAxis::Z, 0.0) *
303  coordinateRotation(CoordinateAxis::Y, 0.0);
304 
305  SVec<double> bodyVel;
306  bodyVel << 0., 0., 0., 1.0, 0., 0.;
308  DVec<double> q(12);
309  DVec<double> dq(12);
310  DVec<double> tau(12);
311  for (size_t i = 0; i < 12; i++) {
312  q[i] = i + 1;
313  dq[i] = (i + 1) * 2;
314  tau[i] = (i + 1) * -30.;
315  }
316 
317  // set state
318  x.bodyOrientation = rotationMatrixToQuaternion(rBody.transpose());
319  x.bodyVelocity = bodyVel;
320  x.bodyPosition = Vec3<double>(6, 7, 8);
321  x.q = q;
322  x.qd = dq;
323 
324  // generate external forces
325  vectorAligned<SVec<double>> forces(18);
326  for (size_t i = 0; i < 18; i++) {
327  for (size_t j = 0; j < 6; j++) {
328  forces[i][j] = i + j + 1;
329  }
330  }
331 
332  // fwd kin is included in this
333  cheetahModel.setState(x);
334  cheetahModel.forwardKinematics(); // compute forward kinematics
335 
336  double length(0.19);
337  double width(0.049);
338 
339  Vec3<double> FR_abd_ref(x.bodyPosition[0] + length, x.bodyPosition[1] - width,
340  x.bodyPosition[2]);
341 
342  Vec3<double> FL_abd_ref(x.bodyPosition[0] + length, x.bodyPosition[1] + width,
343  x.bodyPosition[2]);
344 
345  Vec3<double> HR_abd_ref(x.bodyPosition[0] - length, x.bodyPosition[1] - width,
346  x.bodyPosition[2]);
347 
348  Vec3<double> HL_abd_ref(x.bodyPosition[0] - length, x.bodyPosition[1] + width,
349  x.bodyPosition[2]);
350 
351  // for(size_t i(0); i<8; ++i){
352  // printf("%lu th\n", i);
353  // pretty_print(cheetahModel._pGC.at(i), std::cout, "cp pos");
354  //}
355 
356  // I add the body points in a different order, so comparing them is kind of
357  // annoying. this just one foot point.
358  EXPECT_TRUE(
359  almostEqual(FR_abd_ref, cheetahModel._pGC.at(linkID::FR_abd), .0005));
360  EXPECT_TRUE(
361  almostEqual(FL_abd_ref, cheetahModel._pGC.at(linkID::FL_abd), .0005));
362  EXPECT_TRUE(
363  almostEqual(HR_abd_ref, cheetahModel._pGC.at(linkID::HR_abd), .0005));
364  EXPECT_TRUE(
365  almostEqual(HL_abd_ref, cheetahModel._pGC.at(linkID::HL_abd), .0005));
366 }
367 
368 TEST(MiniCheetah, InertiaProperty) {
369  FloatingBaseModel<double> cheetahModel =
370  buildMiniCheetah<double>().buildModel();
371 
372  SVec<double> bodyVel;
374  DVec<double> q(12);
375  DVec<double> dq(12);
376  DVec<double> tau(12);
377 
378  for (size_t i = 0; i < 12; i++) {
379  q[i] = 0.;
380  dq[i] = 0.;
381  tau[i] = 0.;
382  }
383  q[1] = -M_PI / 2.;
384  q[4] = -M_PI / 2.;
385  q[7] = M_PI / 2.;
386  q[10] = M_PI / 2.;
387 
388  Vec3<double> rpy_ori;
389  rpy_ori.setZero();
390  // set state
391  x.bodyOrientation = ori::rpyToQuat(rpy_ori);
392  x.bodyVelocity.setZero();
393  x.bodyPosition.setZero();
394  x.q = q;
395  x.qd = dq;
396 
397  cheetahModel.setState(x);
398  cheetahModel.massMatrix();
399 
400  DMat<double> H = cheetahModel.getMassMatrix();
401 
402  // pretty_print(H, std::cout, "H");
403  // exit(0);
404 }
Vec3< T > bodyPosition
vector< Mat6< T >, Eigen::aligned_allocator< Mat6< T > > > _Xrot
bool fpEqual(T a, T b, T tol)
Definition: utilities.h:15
void forwardKinematics()
Do forward kinematics for feet.
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
typename Eigen::Matrix< T, 6, 6 > Mat6
Definition: cppTypes.h:70
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Vec3< T > dBodyPosition
Data structure containing parameters for quadruped robot.
typename Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > DMat
Definition: cppTypes.h:106
TEST(MiniCheetah, miniCheetahModel1)
const std::vector< int > & getParentVector()
vector< Mat6< T >, Eigen::aligned_allocator< Mat6< T > > > _Xtree
Utility function to build a Mini Cheetah Quadruped object.
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
const std::vector< SpatialInertia< T >, Eigen::aligned_allocator< SpatialInertia< T > > > & getBodyInertiaVector()
vector< Vec3< T > > _vGC
void setState(const FBModelState< T > &state)
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
const DMat< T > & getMassMatrix() const
const std::vector< SpatialInertia< T >, Eigen::aligned_allocator< SpatialInertia< T > > > & getRotorInertiaVector()
void setAllExternalForces(const vectorAligned< SVec< T >> &forces)
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 step(T dt, const DVec< T > &tau, T kp, T kd)
Initialize simulator with given model.
void runABA(const DVec< T > &tau)
Simulate forward one step.
bool vectorEqual(const std::vector< T > &a, const std::vector< T > &b)
Definition: utilities.h:23
void setState(const FBModelState< T > &state)
Quat< typename T::Scalar > rpyToQuat(const Eigen::MatrixBase< T > &rpy)
typename std::vector< T, Eigen::aligned_allocator< T >> vectorAligned
Definition: cppTypes.h:118
vector< Vec3< T > > _pGC
const FBModelStateDerivative< T > & getDState() const
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
Rigid Body Dynamics Simulator with Collisions.
const FloatingBaseModel< T > & getModel()
typename Eigen::Matrix< T, 3, 3 > RotMat
Definition: cppTypes.h:18
Implementation of Rigid Body Floating Base model data structure.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation