Cheetah Software  1.0
test_ImuSimulator.cpp
Go to the documentation of this file.
1 
8 #include "cppTypes.h"
9 
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 
13 // check the imu data when stationary and at the origin
14 TEST(ImuSimulator, passThrough) {
15  // no noise
17  simParams.vectornav_imu_quat_noise = 0.f;
18  simParams.vectornav_imu_accelerometer_noise = 0.f;
19  simParams.vectornav_imu_gyro_noise = 0.f;
20 
21 
22  ImuSimulator<double> imuSim(simParams, 0);
23 
26 
27  Quat<double> eye;
28  eye << 1, 0, 0, 0;
29 
30  SVec<double> v0;
31  v0 << 0, 0, 0, 0, 0, 0;
32 
33  // stationary, upright
34  xfb.bodyOrientation = eye;
35  xfb.bodyVelocity = v0;
36  xfbd.dBodyVelocity = v0;
37 
39 
40  // update data
41  imuSim.updateVectornav(xfb, xfbd, &vn);
42 
43  Vec3<float> imuZero(0, 0, 0);
44  Vec3<float> imuGravity(0, 0, 9.81);
45  Quat<float> imuLevel;
46  // imuLevel << 1,0,0,0;
47  imuLevel << 0, 0, 0,
48  1; // vectornave quaternion description sequence is (x, y, z, w)
49 
50  EXPECT_TRUE(almostEqual(imuZero, vn.gyro, .00001f));
51  EXPECT_TRUE(almostEqual(imuLevel, vn.quat, .00001f));
52  EXPECT_TRUE(almostEqual(imuGravity, vn.accelerometer, .00001f));
53 }
54 
55 // test with
56 // no omega or body acceleration, but linear, velocity, orientation, and
57 // position
58 TEST(ImuSimulator, orientation) {
59  // no noise
61  simParams.vectornav_imu_quat_noise = 0.f;
62  simParams.vectornav_imu_accelerometer_noise = 0.f;
63  simParams.vectornav_imu_gyro_noise = 0.f;
64 
65  ImuSimulator<double> imuSim(simParams, 0);
66 
69 
70  // pitch the robot down:
71  Quat<double> quat =
72  rotationMatrixToQuaternion(coordinateRotation(CoordinateAxis::Y, .2));
73  Vec3<double> position(2, 4, 3);
74  SVec<double> velocity;
75  velocity << 0, 0, 0, 2, 3, 6;
76  SVec<double> acceleration = SVec<double>::Zero();
77 
78  xfb.bodyVelocity = velocity;
79  xfb.bodyPosition = position;
80  xfb.bodyOrientation = quat;
81  xfbd.dBodyPosition = velocity.tail<3>();
82  xfbd.dBodyVelocity = acceleration;
83 
85 
86  // update data
87  imuSim.updateVectornav(xfb, xfbd, &vn);
88 
89  Vec3<float> imuZero(0, 0, 0);
90  Vec3<float> imuGravity(0, 0, 9.81);
91  // Quat<float> imuLevel = quat.cast<float>();
92  Quat<float> imuLevel;
93  Quat<float> sim_quat = quat.cast<float>();
94  // vectornave quaternion description sequence is (x, y, z, w)
95  imuLevel << sim_quat[1], sim_quat[2], sim_quat[3], sim_quat[0];
96 
97  EXPECT_TRUE(almostEqual(imuZero, vn.gyro, .00001f));
98  EXPECT_TRUE(almostEqual(imuLevel, vn.quat, .00001f));
99  EXPECT_TRUE(vn.accelerometer[0] < .0001f);
100 }
101 
102 // test with omega
104  // no noise
105  SimulatorControlParameters simParams;
106  simParams.vectornav_imu_quat_noise = 0.f;
107  simParams.vectornav_imu_accelerometer_noise = 0.f;
108  simParams.vectornav_imu_gyro_noise = 0.f;
109 
110  ImuSimulator<double> imuSim(simParams, 0);
111 
114 
115  // pitch the robot down:
116  Quat<double> quat =
117  rotationMatrixToQuaternion(coordinateRotation(CoordinateAxis::Y, .2));
118  Vec3<double> position(2, 4, 3);
119  SVec<double> velocity;
120  velocity << 1, 2, 3, 0, 0, 0;
121  SVec<double> acceleration = SVec<double>::Zero();
122 
123  xfb.bodyVelocity = velocity;
124  xfb.bodyPosition = position;
125  xfb.bodyOrientation = quat;
126  xfbd.dBodyPosition = velocity.tail<3>();
127  xfbd.dBodyVelocity = acceleration;
128 
130 
131  // update data
132  imuSim.updateVectornav(xfb, xfbd, &vn);
133 
134  Vec3<float> imuZero(0, 0, 0);
135  Vec3<float> imuGravity(0, 0, 9.81);
136  Quat<float> imuLevel;
137  Quat<float> sim_quat = quat.cast<float>();
138  imuLevel << sim_quat[1], sim_quat[2], sim_quat[3], sim_quat[0];
139  Vec3<float> omegaB = xfb.bodyVelocity.head<3>().cast<float>();
140 
141  EXPECT_TRUE(almostEqual(omegaB, vn.gyro, .00001f));
142  EXPECT_TRUE(almostEqual(imuLevel, vn.quat, .00001f));
143 }
144 
145 // test running in a circle omega cross v terms
146 TEST(ImuSimulator, omegaCrossV) {
147  // no noise
148  SimulatorControlParameters simParams;
149  simParams.vectornav_imu_quat_noise = 0.f;
150  simParams.vectornav_imu_accelerometer_noise = 0.f;
151  simParams.vectornav_imu_gyro_noise = 0.f;
152 
153  ImuSimulator<double> imuSim(simParams, 0);
154 
157 
158  // robot is upright, running in clockwise circle when viewed from above, at 12
159  // o'clock:
161  Vec3<double> position(2, 4, 3);
162  SVec<double> velocity;
163  velocity << 0, 0, -2, 3, 0, 0; // clockwise
164  SVec<double> acceleration =
165  SVec<double>::Zero(); // zero spatial acceleration
166 
167  xfb.bodyVelocity = velocity;
168  xfb.bodyPosition = position;
169  xfb.bodyOrientation = quat;
170  xfbd.dBodyPosition = velocity.tail<3>();
171  xfbd.dBodyVelocity = acceleration;
172 
174 
175  // update data
176  imuSim.updateVectornav(xfb, xfbd, &vn);
177 
178  Vec3<float> imuZero(0, 0, 0);
179  Vec3<float> imuGravity(0, 0, 9.81);
180  Quat<float> imuLevel;
181  Quat<float> sim_quat = quat.cast<float>();
182  imuLevel << sim_quat[1], sim_quat[2], sim_quat[3], sim_quat[0];
183  Vec3<float> omegaB = xfb.bodyVelocity.head<3>().cast<float>();
184 
185  // we should see -y acceleration (man sitting inside robot will feel pulled
186  // toward the outside)
187  Vec3<float> acc_ref(0, -6, 9.81);
188 
189  EXPECT_TRUE(almostEqual(omegaB, vn.gyro, .00001f));
190  EXPECT_TRUE(almostEqual(imuLevel, vn.quat, .00001f));
191  EXPECT_TRUE(almostEqual(vn.accelerometer, acc_ref, .0001f));
192 }
193 
194 // test noise:
196  SimulatorControlParameters simParamsNoise;
197  simParamsNoise.vectornav_imu_quat_noise = 0.005f;
198  simParamsNoise.vectornav_imu_accelerometer_noise = 0.002f;
199  simParamsNoise.vectornav_imu_gyro_noise = 0.005f;
200 
201  SimulatorControlParameters simParams;
202  simParams.vectornav_imu_quat_noise = 0.f;
203  simParams.vectornav_imu_accelerometer_noise = 0.f;
204  simParams.vectornav_imu_gyro_noise = 0.f;
205 
206 
207  ImuSimulator<double> imuSimNoise(simParamsNoise, 0);
208 
211 
213  ori::coordinateRotation(CoordinateAxis::X, 2.34) *
214  ori::coordinateRotation(CoordinateAxis::Y, -5.3) *
215  ori::coordinateRotation(CoordinateAxis::Z, -.3));
216 
217  Vec3<double> position(2, 4, 3);
218  SVec<double> velocity;
219  velocity << 2, 1, -2, 3, 3, 2; // clockwise
220  SVec<double> acceleration =
221  SVec<double>::Zero(); // zero spatial acceleration
222 
223  xfb.bodyVelocity = velocity;
224  xfb.bodyPosition = position;
225  xfb.bodyOrientation = quat;
226  xfbd.dBodyPosition = velocity.tail<3>();
227  xfbd.dBodyVelocity = acceleration;
228 
230 
231  Vec3<float> rpy_ref = ori::quatToRPY(quat.cast<float>());
232  Vec3<float> rpy_avg(0, 0, 0);
233 
234  constexpr size_t nIterations = 1000;
235  for (size_t i = 0; i < nIterations; i++) {
236  imuSimNoise.updateVectornav(xfb, xfbd, &vn);
237  Quat<float> sim_quat;
238  sim_quat << vn.quat[3], vn.quat[0], vn.quat[1], vn.quat[2];
239  Vec3<float> rpy = ori::quatToRPY(sim_quat);
240  rpy_avg += rpy / float(nIterations);
241  }
242 
243  EXPECT_TRUE(almostEqual(rpy_avg, rpy_ref, .01));
244 }
Vec3< T > bodyPosition
SVec< T > bodyVelocity
Mat3< T > coordinateRotation(CoordinateAxis axis, T theta)
Simulated IMU.
TEST(ImuSimulator, passThrough)
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
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
Vec3< float > accelerometer
Definition: IMUTypes.h:14
vn_sensor vn
void updateVectornav(const FBModelState< T > &robotState, const FBModelStateDerivative< T > &robotStateD, VectorNavData *data)
Vec3< typename T::Scalar > quatToRPY(const Eigen::MatrixBase< T > &q)
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
Quat< float > quat
Definition: IMUTypes.h:16
Vec3< float > gyro
Definition: IMUTypes.h:15
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation