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