blob: 38ce069763ffb71f26eeece2171f40bf1aaa0256 [file] [log] [blame]
Brian Silvermana57b7012020-03-11 20:19:23 -07001#include "frc971/zeroing/absolute_encoder.h"
2
3#include "gtest/gtest.h"
4
5#include "frc971/zeroing/zeroing_test.h"
6
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);
18 FBB fbb;
19 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.
74 FBB fbb;
75 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
129 FBB fbb;
130 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());
141}
142
143} // namespace testing
144} // namespace zeroing
145} // namespace frc971