blob: 7a74413609c6d75b3ea82823f4901b0f5a5952cf [file] [log] [blame]
James Kuszmauld3f9eb22020-01-12 15:02:07 -08001#include "aos/flatbuffers.h"
2#include "gtest/gtest.h"
3#include "frc971/zeroing/imu_zeroer.h"
4
5namespace frc971::zeroing {
6
James Kuszmaulb1e29372020-02-11 16:55:36 -08007static constexpr int kMinSamplesToZero =
8 2 * ImuZeroer::kSamplesToAverage * ImuZeroer::kRequiredZeroPoints;
9
James Kuszmauld3f9eb22020-01-12 15:02:07 -080010aos::FlatbufferDetachedBuffer<IMUValues> MakeMeasurement(
11 const Eigen::Vector3d &gyro, const Eigen::Vector3d &accel) {
12 flatbuffers::FlatBufferBuilder fbb;
13 fbb.ForceDefaults(1);
14 IMUValuesBuilder builder(fbb);
15 builder.add_gyro_x(gyro.x());
16 builder.add_gyro_y(gyro.y());
17 builder.add_gyro_z(gyro.z());
18 builder.add_accelerometer_x(accel.x());
19 builder.add_accelerometer_y(accel.y());
20 builder.add_accelerometer_z(accel.z());
21 fbb.Finish(builder.Finish());
22 return fbb.Release();
23}
24
25// Tests that when we initialize everything is in a sane state.
26TEST(ImuZeroerTest, InitializeUnzeroed) {
27 ImuZeroer zeroer;
28 ASSERT_FALSE(zeroer.Zeroed());
29 ASSERT_FALSE(zeroer.Faulted());
30 ASSERT_EQ(0.0, zeroer.GyroOffset().norm());
31 ASSERT_EQ(0.0, zeroer.ZeroedGyro().norm());
32 ASSERT_EQ(0.0, zeroer.ZeroedAccel().norm());
33 // A measurement before we are zeroed should just result in the measurement
34 // being passed through without modification.
James Kuszmaulb1e29372020-02-11 16:55:36 -080035 zeroer.ProcessMeasurement(
36 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080037 ASSERT_FALSE(zeroer.Zeroed());
38 ASSERT_FALSE(zeroer.Faulted());
39 ASSERT_EQ(0.0, zeroer.GyroOffset().norm());
James Kuszmaulb1e29372020-02-11 16:55:36 -080040 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().x());
41 ASSERT_FLOAT_EQ(0.02, zeroer.ZeroedGyro().y());
42 ASSERT_FLOAT_EQ(0.03, zeroer.ZeroedGyro().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080043 ASSERT_EQ(4.0, zeroer.ZeroedAccel().x());
44 ASSERT_EQ(5.0, zeroer.ZeroedAccel().y());
45 ASSERT_EQ(6.0, zeroer.ZeroedAccel().z());
46}
47
48// Tests that we zero if we receive a bunch of identical measurements.
49TEST(ImuZeroerTest, ZeroOnConstantData) {
50 ImuZeroer zeroer;
51 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -080052 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
53 zeroer.ProcessMeasurement(
54 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080055 }
56 ASSERT_TRUE(zeroer.Zeroed());
57 ASSERT_FALSE(zeroer.Faulted());
58 // Gyro should be zeroed to {1, 2, 3}.
James Kuszmaulb1e29372020-02-11 16:55:36 -080059 ASSERT_FLOAT_EQ(0.01, zeroer.GyroOffset().x());
60 ASSERT_FLOAT_EQ(0.02, zeroer.GyroOffset().y());
61 ASSERT_FLOAT_EQ(0.03, zeroer.GyroOffset().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080062 ASSERT_EQ(0.0, zeroer.ZeroedGyro().x());
63 ASSERT_EQ(0.0, zeroer.ZeroedGyro().y());
64 ASSERT_EQ(0.0, zeroer.ZeroedGyro().z());
65 // Accelerometer readings should not be affected.
66 ASSERT_EQ(4.0, zeroer.ZeroedAccel().x());
67 ASSERT_EQ(5.0, zeroer.ZeroedAccel().y());
68 ASSERT_EQ(6.0, zeroer.ZeroedAccel().z());
69 // If we get another measurement offset by {1, 1, 1} we should read the result
70 // as {1, 1, 1}.
James Kuszmaulb1e29372020-02-11 16:55:36 -080071 zeroer.ProcessMeasurement(
72 MakeMeasurement({0.02, 0.03, 0.04}, {0, 0, 0}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080073 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -080074 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().x());
75 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().y());
76 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().z());
77}
78
79// Tests that we do not zero if the gyro is producing particularly high
80// magnitude results.
81TEST(ImuZeroerTest, NoZeroOnHighMagnitudeGyro) {
82 ImuZeroer zeroer;
83 ASSERT_FALSE(zeroer.Zeroed());
84 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
85 zeroer.ProcessMeasurement(
86 MakeMeasurement({0.1, 0.2, 0.3}, {4, 5, 6}).message());
87 ASSERT_FALSE(zeroer.Zeroed());
88 }
89 ASSERT_FALSE(zeroer.Faulted());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080090}
91
92// Tests that we tolerate small amounts of noise in the incoming data and can
93// still zero.
94TEST(ImuZeroerTest, ZeroOnLowNoiseData) {
95 ImuZeroer zeroer;
96 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -080097 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080098 const double offset =
James Kuszmaulb1e29372020-02-11 16:55:36 -080099 (static_cast<double>(ii) / (kMinSamplesToZero - 1) - 0.5) * 0.001;
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800100 zeroer.ProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800101 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800102 {4 + offset, 5 + offset, 6 + offset})
103 .message());
104 }
105 ASSERT_TRUE(zeroer.Zeroed());
106 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800107 ASSERT_NEAR(0.01, zeroer.GyroOffset().x(), 1e-3);
108 ASSERT_NEAR(0.02, zeroer.GyroOffset().y(), 1e-3);
109 ASSERT_NEAR(0.03, zeroer.GyroOffset().z(), 1e-3);
110 // If we get another measurement offset by {0.01, 0.01, 0.01} we should read
111 // the result as {0.01, 0.01, 0.01}.
112 zeroer.ProcessMeasurement(
113 MakeMeasurement({0.02, 0.03, 0.04}, {0, 0, 0}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800114 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800115 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().x(), 1e-3);
116 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().y(), 1e-3);
117 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().z(), 1e-3);
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800118 ASSERT_EQ(0.0, zeroer.ZeroedAccel().x());
119 ASSERT_EQ(0.0, zeroer.ZeroedAccel().y());
120 ASSERT_EQ(0.0, zeroer.ZeroedAccel().z());
121}
122
123// Tests that we do not zero if there is too much noise in the input data.
124TEST(ImuZeroerTest, NoZeroOnHighNoiseData) {
125 ImuZeroer zeroer;
126 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800127 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800128 ASSERT_FALSE(zeroer.Zeroed());
129 const double offset =
James Kuszmaulb1e29372020-02-11 16:55:36 -0800130 (static_cast<double>(ii) / (kMinSamplesToZero - 1) - 0.5) * 1.0;
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800131 zeroer.ProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800132 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800133 {4 + offset, 5 + offset, 6 + offset})
134 .message());
135 }
136 ASSERT_FALSE(zeroer.Zeroed());
137 ASSERT_FALSE(zeroer.Faulted());
138}
139
140// Tests that we fault if we successfully rezero and get a significantly offset
141// zero.
142TEST(ImuZeroerTest, FaultOnNewZero) {
143 ImuZeroer zeroer;
144 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800145 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
146 zeroer.ProcessMeasurement(
147 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800148 }
149 ASSERT_TRUE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800150 ASSERT_FALSE(zeroer.Faulted())
151 << "We should not fault until we complete a second cycle of zeroing.";
152 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
153 zeroer.ProcessMeasurement(
154 MakeMeasurement({0.01, 0.05, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800155 }
156 ASSERT_TRUE(zeroer.Faulted());
157}
158
159// Tests that we do not fault if the zero only changes by a small amount.
160TEST(ImuZeroerTest, NoFaultOnSimilarZero) {
161 ImuZeroer zeroer;
162 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800163 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
164 zeroer.ProcessMeasurement(
165 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800166 }
167 ASSERT_TRUE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800168 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800169 zeroer.ProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800170 MakeMeasurement({0.01, 0.020001, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800171 }
172 ASSERT_FALSE(zeroer.Faulted());
173}
174
175} // namespace frc971::zeroing