blob: 566a7b897cfb2f8c0137ed0d4186a669330cf49f [file] [log] [blame]
James Kuszmauld3f9eb22020-01-12 15:02:07 -08001#include "frc971/zeroing/imu_zeroer.h"
2
Philipp Schrader790cb542023-07-05 21:06:52 -07003#include "gtest/gtest.h"
4
5#include "aos/flatbuffers.h"
6
James Kuszmauld3f9eb22020-01-12 15:02:07 -08007namespace frc971::zeroing {
8
James Kuszmaulb1e29372020-02-11 16:55:36 -08009static constexpr int kMinSamplesToZero =
10 2 * ImuZeroer::kSamplesToAverage * ImuZeroer::kRequiredZeroPoints;
11
James Kuszmauld3f9eb22020-01-12 15:02:07 -080012aos::FlatbufferDetachedBuffer<IMUValues> MakeMeasurement(
James Kuszmaulddc69702021-03-24 21:55:03 -070013 const Eigen::Vector3d &gyro, const Eigen::Vector3d &accel,
14 bool faulted = false) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -080015 flatbuffers::FlatBufferBuilder fbb;
Austin Schuhd7b15da2020-02-17 15:06:11 -080016 fbb.ForceDefaults(true);
James Kuszmaulddc69702021-03-24 21:55:03 -070017
18 ADIS16470DiagStatBuilder diag_stat_builder(fbb);
19 diag_stat_builder.add_clock_error(faulted);
20 diag_stat_builder.add_memory_failure(false);
21 diag_stat_builder.add_sensor_failure(false);
22 diag_stat_builder.add_standby_mode(false);
23 diag_stat_builder.add_spi_communication_error(false);
24 diag_stat_builder.add_flash_memory_update_error(false);
25 diag_stat_builder.add_data_path_overrun(false);
26
27 const auto diag_stat_offset = diag_stat_builder.Finish();
28
James Kuszmauld3f9eb22020-01-12 15:02:07 -080029 IMUValuesBuilder builder(fbb);
30 builder.add_gyro_x(gyro.x());
31 builder.add_gyro_y(gyro.y());
32 builder.add_gyro_z(gyro.z());
33 builder.add_accelerometer_x(accel.x());
34 builder.add_accelerometer_y(accel.y());
35 builder.add_accelerometer_z(accel.z());
James Kuszmaulddc69702021-03-24 21:55:03 -070036 builder.add_previous_reading_diag_stat(diag_stat_offset);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080037 fbb.Finish(builder.Finish());
38 return fbb.Release();
39}
40
41// Tests that when we initialize everything is in a sane state.
42TEST(ImuZeroerTest, InitializeUnzeroed) {
43 ImuZeroer zeroer;
44 ASSERT_FALSE(zeroer.Zeroed());
45 ASSERT_FALSE(zeroer.Faulted());
46 ASSERT_EQ(0.0, zeroer.GyroOffset().norm());
James Kuszmaul6d6e1302022-03-12 15:22:48 -080047 ASSERT_EQ(0.0, zeroer.ZeroedGyro().value().norm());
48 ASSERT_EQ(0.0, zeroer.ZeroedAccel().value().norm());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080049 // A measurement before we are zeroed should just result in the measurement
50 // being passed through without modification.
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080051 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080052 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080053 ASSERT_FALSE(zeroer.Zeroed());
54 ASSERT_FALSE(zeroer.Faulted());
55 ASSERT_EQ(0.0, zeroer.GyroOffset().norm());
James Kuszmaul6d6e1302022-03-12 15:22:48 -080056 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().value().x());
57 ASSERT_FLOAT_EQ(0.02, zeroer.ZeroedGyro().value().y());
58 ASSERT_FLOAT_EQ(0.03, zeroer.ZeroedGyro().value().z());
59 ASSERT_EQ(4.0, zeroer.ZeroedAccel().value().x());
60 ASSERT_EQ(5.0, zeroer.ZeroedAccel().value().y());
61 ASSERT_EQ(6.0, zeroer.ZeroedAccel().value().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080062}
63
64// Tests that we zero if we receive a bunch of identical measurements.
65TEST(ImuZeroerTest, ZeroOnConstantData) {
66 ImuZeroer zeroer;
67 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -080068 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080069 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080070 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080071 }
72 ASSERT_TRUE(zeroer.Zeroed());
73 ASSERT_FALSE(zeroer.Faulted());
74 // Gyro should be zeroed to {1, 2, 3}.
James Kuszmaulb1e29372020-02-11 16:55:36 -080075 ASSERT_FLOAT_EQ(0.01, zeroer.GyroOffset().x());
76 ASSERT_FLOAT_EQ(0.02, zeroer.GyroOffset().y());
77 ASSERT_FLOAT_EQ(0.03, zeroer.GyroOffset().z());
James Kuszmaul6d6e1302022-03-12 15:22:48 -080078 ASSERT_EQ(0.0, zeroer.ZeroedGyro().value().x());
79 ASSERT_EQ(0.0, zeroer.ZeroedGyro().value().y());
80 ASSERT_EQ(0.0, zeroer.ZeroedGyro().value().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080081 // Accelerometer readings should not be affected.
James Kuszmaul6d6e1302022-03-12 15:22:48 -080082 ASSERT_EQ(4.0, zeroer.ZeroedAccel().value().x());
83 ASSERT_EQ(5.0, zeroer.ZeroedAccel().value().y());
84 ASSERT_EQ(6.0, zeroer.ZeroedAccel().value().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080085 // If we get another measurement offset by {1, 1, 1} we should read the result
86 // as {1, 1, 1}.
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080087 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080088 MakeMeasurement({0.02, 0.03, 0.04}, {0, 0, 0}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -080089 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaul6d6e1302022-03-12 15:22:48 -080090 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().value().x());
91 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().value().y());
92 ASSERT_FLOAT_EQ(0.01, zeroer.ZeroedGyro().value().z());
James Kuszmaulb1e29372020-02-11 16:55:36 -080093}
94
95// Tests that we do not zero if the gyro is producing particularly high
96// magnitude results.
97TEST(ImuZeroerTest, NoZeroOnHighMagnitudeGyro) {
98 ImuZeroer zeroer;
99 ASSERT_FALSE(zeroer.Zeroed());
100 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800101 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800102 MakeMeasurement({0.1, 0.2, 0.3}, {4, 5, 6}).message());
103 ASSERT_FALSE(zeroer.Zeroed());
104 }
105 ASSERT_FALSE(zeroer.Faulted());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800106}
107
108// Tests that we tolerate small amounts of noise in the incoming data and can
109// still zero.
110TEST(ImuZeroerTest, ZeroOnLowNoiseData) {
111 ImuZeroer zeroer;
112 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800113 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800114 const double offset =
James Kuszmaulb1e29372020-02-11 16:55:36 -0800115 (static_cast<double>(ii) / (kMinSamplesToZero - 1) - 0.5) * 0.001;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800116 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800117 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
Philipp Schrader790cb542023-07-05 21:06:52 -0700118 {4 + offset, 5 + offset, 6 + offset})
119 .message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800120 }
121 ASSERT_TRUE(zeroer.Zeroed());
122 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800123 ASSERT_NEAR(0.01, zeroer.GyroOffset().x(), 1e-3);
124 ASSERT_NEAR(0.02, zeroer.GyroOffset().y(), 1e-3);
125 ASSERT_NEAR(0.03, zeroer.GyroOffset().z(), 1e-3);
126 // If we get another measurement offset by {0.01, 0.01, 0.01} we should read
127 // the result as {0.01, 0.01, 0.01}.
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800128 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800129 MakeMeasurement({0.02, 0.03, 0.04}, {0, 0, 0}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800130 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaul6d6e1302022-03-12 15:22:48 -0800131 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().value().x(), 1e-3);
132 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().value().y(), 1e-3);
133 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().value().z(), 1e-3);
134 ASSERT_EQ(0.0, zeroer.ZeroedAccel().value().x());
135 ASSERT_EQ(0.0, zeroer.ZeroedAccel().value().y());
136 ASSERT_EQ(0.0, zeroer.ZeroedAccel().value().z());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800137}
138
139// Tests that we do not zero if there is too much noise in the input data.
140TEST(ImuZeroerTest, NoZeroOnHighNoiseData) {
141 ImuZeroer zeroer;
142 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800143 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800144 ASSERT_FALSE(zeroer.Zeroed());
145 const double offset =
James Kuszmaulb1e29372020-02-11 16:55:36 -0800146 (static_cast<double>(ii) / (kMinSamplesToZero - 1) - 0.5) * 1.0;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800147 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800148 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
Philipp Schrader790cb542023-07-05 21:06:52 -0700149 {4 + offset, 5 + offset, 6 + offset})
150 .message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800151 }
152 ASSERT_FALSE(zeroer.Zeroed());
153 ASSERT_FALSE(zeroer.Faulted());
154}
155
156// Tests that we fault if we successfully rezero and get a significantly offset
157// zero.
158TEST(ImuZeroerTest, FaultOnNewZero) {
159 ImuZeroer zeroer;
160 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800161 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800162 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800163 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800164 }
165 ASSERT_TRUE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800166 ASSERT_FALSE(zeroer.Faulted())
167 << "We should not fault until we complete a second cycle of zeroing.";
168 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800169 zeroer.InsertAndProcessMeasurement(
James Kuszmaulad2f8db2021-10-24 17:02:57 -0700170 MakeMeasurement({0.01, -0.05, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800171 }
172 ASSERT_TRUE(zeroer.Faulted());
James Kuszmaulddc69702021-03-24 21:55:03 -0700173 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800174}
175
176// Tests that we do not fault if the zero only changes by a small amount.
177TEST(ImuZeroerTest, NoFaultOnSimilarZero) {
178 ImuZeroer zeroer;
179 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800180 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800181 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800182 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800183 }
184 ASSERT_TRUE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800185 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800186 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800187 MakeMeasurement({0.01, 0.020001, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800188 }
189 ASSERT_FALSE(zeroer.Faulted());
190}
191
James Kuszmaulddc69702021-03-24 21:55:03 -0700192// Tests that we fault on a bad diagnostic.
193TEST(ImuZeroerTest, FaultOnBadDiagnostic) {
194 ImuZeroer zeroer;
195 ASSERT_FALSE(zeroer.Zeroed());
196 ASSERT_FALSE(zeroer.Faulted());
197 zeroer.InsertAndProcessMeasurement(
198 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}, true).message());
199 ASSERT_FALSE(zeroer.Zeroed());
200 ASSERT_TRUE(zeroer.Faulted());
201}
202
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800203} // namespace frc971::zeroing