blob: e97fbe28c7cd0516c0ecf5945a8253d7039ca5f9 [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;
Austin Schuhd7b15da2020-02-17 15:06:11 -080013 fbb.ForceDefaults(true);
James Kuszmauld3f9eb22020-01-12 15:02:07 -080014 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 Kuszmaulb7f45bb2020-02-26 20:27:48 -080035 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080036 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) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080053 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080054 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 Kuszmaulb7f45bb2020-02-26 20:27:48 -080071 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080072 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) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -080085 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -080086 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 Kuszmaulb7f45bb2020-02-26 20:27:48 -0800100 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800101 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800102 {4 + offset, 5 + offset, 6 + offset}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800103 }
104 ASSERT_TRUE(zeroer.Zeroed());
105 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800106 ASSERT_NEAR(0.01, zeroer.GyroOffset().x(), 1e-3);
107 ASSERT_NEAR(0.02, zeroer.GyroOffset().y(), 1e-3);
108 ASSERT_NEAR(0.03, zeroer.GyroOffset().z(), 1e-3);
109 // If we get another measurement offset by {0.01, 0.01, 0.01} we should read
110 // the result as {0.01, 0.01, 0.01}.
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800111 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800112 MakeMeasurement({0.02, 0.03, 0.04}, {0, 0, 0}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800113 ASSERT_FALSE(zeroer.Faulted());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800114 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().x(), 1e-3);
115 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().y(), 1e-3);
116 ASSERT_NEAR(0.01, zeroer.ZeroedGyro().z(), 1e-3);
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800117 ASSERT_EQ(0.0, zeroer.ZeroedAccel().x());
118 ASSERT_EQ(0.0, zeroer.ZeroedAccel().y());
119 ASSERT_EQ(0.0, zeroer.ZeroedAccel().z());
120}
121
122// Tests that we do not zero if there is too much noise in the input data.
123TEST(ImuZeroerTest, NoZeroOnHighNoiseData) {
124 ImuZeroer zeroer;
125 ASSERT_FALSE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800126 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800127 ASSERT_FALSE(zeroer.Zeroed());
128 const double offset =
James Kuszmaulb1e29372020-02-11 16:55:36 -0800129 (static_cast<double>(ii) / (kMinSamplesToZero - 1) - 0.5) * 1.0;
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800130 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800131 MakeMeasurement({0.01 + offset, 0.02 + offset, 0.03 + offset},
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800132 {4 + offset, 5 + offset, 6 + offset}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800133 }
134 ASSERT_FALSE(zeroer.Zeroed());
135 ASSERT_FALSE(zeroer.Faulted());
136}
137
138// Tests that we fault if we successfully rezero and get a significantly offset
139// zero.
140TEST(ImuZeroerTest, FaultOnNewZero) {
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 Kuszmaulb7f45bb2020-02-26 20:27:48 -0800144 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800145 MakeMeasurement({0.01, 0.02, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800146 }
147 ASSERT_TRUE(zeroer.Zeroed());
James Kuszmaulb1e29372020-02-11 16:55:36 -0800148 ASSERT_FALSE(zeroer.Faulted())
149 << "We should not fault until we complete a second cycle of zeroing.";
150 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800151 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800152 MakeMeasurement({0.01, 0.05, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800153 }
154 ASSERT_TRUE(zeroer.Faulted());
155}
156
157// Tests that we do not fault if the zero only changes by a small amount.
158TEST(ImuZeroerTest, NoFaultOnSimilarZero) {
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 for (size_t ii = 0; ii < kMinSamplesToZero; ++ii) {
James Kuszmaulb7f45bb2020-02-26 20:27:48 -0800167 zeroer.InsertAndProcessMeasurement(
James Kuszmaulb1e29372020-02-11 16:55:36 -0800168 MakeMeasurement({0.01, 0.020001, 0.03}, {4, 5, 6}).message());
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800169 }
170 ASSERT_FALSE(zeroer.Faulted());
171}
172
173} // namespace frc971::zeroing