blob: fdc1fa0915cbd5bb5bb9755e8b580e2bedf69b19 [file] [log] [blame]
Brian Silvermana57b7012020-03-11 20:19:23 -07001#include "frc971/zeroing/absolute_encoder.h"
2
Ravago Jones726deb02021-05-29 14:36:43 -07003#include "gmock/gmock.h"
4#include "gtest/gtest.h"
Brian Silvermana57b7012020-03-11 20:19:23 -07005
Philipp Schrader790cb542023-07-05 21:06:52 -07006#include "frc971/zeroing/zeroing_test.h"
7
Brian Silvermana57b7012020-03-11 20:19:23 -07008namespace frc971 {
9namespace zeroing {
10namespace testing {
11
12using constants::AbsoluteEncoderZeroingConstants;
13
14class AbsoluteEncoderZeroingTest : public ZeroingTest {
15 protected:
16 void MoveTo(PositionSensorSimulator *simulator,
17 AbsoluteEncoderZeroingEstimator *estimator, double new_position) {
18 simulator->MoveTo(new_position);
Ravago Jones726deb02021-05-29 14:36:43 -070019 flatbuffers::FlatBufferBuilder fbb;
Brian Silvermana57b7012020-03-11 20:19:23 -070020 estimator->UpdateEstimate(
21 *simulator->FillSensorValues<AbsolutePosition>(&fbb));
22 }
23};
24
25// Makes sure that using an absolute encoder lets us zero without moving.
26TEST_F(AbsoluteEncoderZeroingTest, TestAbsoluteEncoderZeroingWithoutMovement) {
27 const double index_diff = 1.0;
28 PositionSensorSimulator sim(index_diff);
29
30 const double kMiddlePosition = 2.5;
31 const double start_pos = 2.1;
32 double measured_absolute_position = 0.3 * index_diff;
33
34 AbsoluteEncoderZeroingConstants constants{
35 kSampleSize, index_diff, measured_absolute_position,
36 kMiddlePosition, 0.1, kMovingBufferSize,
37 kIndexErrorFraction};
38
39 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
40 constants.measured_absolute_position);
41
42 AbsoluteEncoderZeroingEstimator estimator(constants);
43
44 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
45 MoveTo(&sim, &estimator, start_pos);
46 ASSERT_FALSE(estimator.zeroed());
47 }
48
49 MoveTo(&sim, &estimator, start_pos);
50 ASSERT_TRUE(estimator.zeroed());
51 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
52}
53
54// Makes sure that we ignore a NAN if we get it, but will correctly zero
55// afterwards.
56TEST_F(AbsoluteEncoderZeroingTest, TestAbsoluteEncoderZeroingIgnoresNAN) {
57 const double index_diff = 1.0;
58 PositionSensorSimulator sim(index_diff);
59
60 const double start_pos = 2.1;
61 double measured_absolute_position = 0.3 * index_diff;
62 const double kMiddlePosition = 2.5;
63
64 AbsoluteEncoderZeroingConstants constants{
65 kSampleSize, index_diff, measured_absolute_position,
66 kMiddlePosition, 0.1, kMovingBufferSize,
67 kIndexErrorFraction};
68
69 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
70 constants.measured_absolute_position);
71
72 AbsoluteEncoderZeroingEstimator estimator(constants);
73
74 // We tolerate a couple NANs before we start.
Ravago Jones726deb02021-05-29 14:36:43 -070075 flatbuffers::FlatBufferBuilder fbb;
Brian Silvermana57b7012020-03-11 20:19:23 -070076 fbb.Finish(CreateAbsolutePosition(
77 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN()));
78 const auto sensor_values =
79 flatbuffers::GetRoot<AbsolutePosition>(fbb.GetBufferPointer());
80 for (size_t i = 0; i < kSampleSize - 1; ++i) {
81 estimator.UpdateEstimate(*sensor_values);
82 }
83
84 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
85 MoveTo(&sim, &estimator, start_pos);
86 ASSERT_FALSE(estimator.zeroed());
87 }
88
89 MoveTo(&sim, &estimator, start_pos);
90 ASSERT_TRUE(estimator.zeroed());
91 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
92}
93
94// Makes sure that using an absolute encoder doesn't let us zero while moving.
95TEST_F(AbsoluteEncoderZeroingTest, TestAbsoluteEncoderZeroingWithMovement) {
96 const double index_diff = 1.0;
97 PositionSensorSimulator sim(index_diff);
98
99 const double start_pos = 10 * index_diff;
100 double measured_absolute_position = 0.3 * index_diff;
101 const double kMiddlePosition = 2.5;
102
103 AbsoluteEncoderZeroingConstants constants{
104 kSampleSize, index_diff, measured_absolute_position,
105 kMiddlePosition, 0.1, kMovingBufferSize,
106 kIndexErrorFraction};
107
108 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
109 constants.measured_absolute_position);
110
111 AbsoluteEncoderZeroingEstimator estimator(constants);
112
113 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
114 MoveTo(&sim, &estimator, start_pos + i * index_diff);
115 ASSERT_FALSE(estimator.zeroed());
116 }
117 MoveTo(&sim, &estimator, start_pos + 10 * index_diff);
118
119 MoveTo(&sim, &estimator, start_pos);
120 ASSERT_FALSE(estimator.zeroed());
121}
122
123// Makes sure we detect an error if the ZeroingEstimator gets sent a NaN.
124TEST_F(AbsoluteEncoderZeroingTest, TestAbsoluteEncoderZeroingWithNaN) {
125 AbsoluteEncoderZeroingConstants constants{
126 kSampleSize, 1, 0.3, 1.0, 0.1, kMovingBufferSize, kIndexErrorFraction};
127
128 AbsoluteEncoderZeroingEstimator estimator(constants);
129
Ravago Jones726deb02021-05-29 14:36:43 -0700130 flatbuffers::FlatBufferBuilder fbb;
Brian Silvermana57b7012020-03-11 20:19:23 -0700131 fbb.Finish(CreateAbsolutePosition(
132 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN()));
133 const auto sensor_values =
134 flatbuffers::GetRoot<AbsolutePosition>(fbb.GetBufferPointer());
135 for (size_t i = 0; i < kSampleSize - 1; ++i) {
136 estimator.UpdateEstimate(*sensor_values);
137 }
138 ASSERT_FALSE(estimator.error());
139
140 estimator.UpdateEstimate(*sensor_values);
141 ASSERT_TRUE(estimator.error());
Ravago Jones726deb02021-05-29 14:36:43 -0700142
143 flatbuffers::FlatBufferBuilder fbb2;
144 fbb2.Finish(estimator.GetEstimatorState(&fbb2));
145
146 const AbsoluteEncoderEstimatorState *state =
147 flatbuffers::GetRoot<AbsoluteEncoderEstimatorState>(
148 fbb2.GetBufferPointer());
149
150 EXPECT_THAT(*state->errors(),
151 ::testing::ElementsAre(ZeroingError::LOST_ABSOLUTE_ENCODER));
Brian Silvermana57b7012020-03-11 20:19:23 -0700152}
153
154} // namespace testing
155} // namespace zeroing
156} // namespace frc971