blob: 2b715eaa86f08389774b5b1dcba8df39ff482994 [file] [log] [blame]
Tyler Chatow3c47f3c2020-01-29 20:45:23 -08001#include "frc971/zeroing/zeroing.h"
2
Adam Snaiderc4b3c192015-02-01 01:30:39 +00003#include <unistd.h>
4
5#include <memory>
Adam Snaiderc4b3c192015-02-01 01:30:39 +00006#include <random>
7
John Park33858a32018-09-28 23:05:48 -07008#include "aos/die.h"
Tyler Chatow3c47f3c2020-01-29 20:45:23 -08009#include "frc971/control_loops/control_loops_generated.h"
Adam Snaiderb4119252015-02-15 01:30:57 +000010#include "frc971/control_loops/position_sensor_sim.h"
Tyler Chatow3c47f3c2020-01-29 20:45:23 -080011#include "gtest/gtest.h"
Adam Snaiderc4b3c192015-02-01 01:30:39 +000012
13namespace frc971 {
14namespace zeroing {
15
Austin Schuhd82068e2019-01-26 20:05:42 -080016using constants::AbsoluteEncoderZeroingConstants;
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000017using constants::EncoderPlusIndexZeroingConstants;
Austin Schuhd82068e2019-01-26 20:05:42 -080018using constants::PotAndAbsoluteEncoderZeroingConstants;
19using constants::PotAndIndexPulseZeroingConstants;
Alex Perrycb7da4b2019-08-28 19:35:56 -070020using control_loops::PositionSensorSimulator;
21using FBB = flatbuffers::FlatBufferBuilder;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000022
Adam Snaiderb4119252015-02-15 01:30:57 +000023static const size_t kSampleSize = 30;
24static const double kAcceptableUnzeroedError = 0.2;
Adam Snaider3cd11c52015-02-16 02:16:09 +000025static const double kIndexErrorFraction = 0.3;
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -080026static const size_t kMovingBufferSize = 3;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000027
Adam Snaiderb4119252015-02-15 01:30:57 +000028class ZeroingTest : public ::testing::Test {
Adam Snaiderc4b3c192015-02-01 01:30:39 +000029 protected:
Alex Perrycb7da4b2019-08-28 19:35:56 -070030 void SetUp() override {}
Adam Snaiderc4b3c192015-02-01 01:30:39 +000031
Tyler Chatowf8f03112017-02-05 14:31:34 -080032 void MoveTo(PositionSensorSimulator *simulator,
33 PotAndIndexPulseZeroingEstimator *estimator,
Adam Snaiderb4119252015-02-15 01:30:57 +000034 double new_position) {
Adam Snaiderb4119252015-02-15 01:30:57 +000035 simulator->MoveTo(new_position);
Alex Perrycb7da4b2019-08-28 19:35:56 -070036 FBB fbb;
37 estimator->UpdateEstimate(
38 *simulator->FillSensorValues<PotAndIndexPosition>(&fbb));
Adam Snaiderb4119252015-02-15 01:30:57 +000039 }
Adam Snaiderc4b3c192015-02-01 01:30:39 +000040
Austin Schuh5f01f152017-02-11 21:34:08 -080041 void MoveTo(PositionSensorSimulator *simulator,
Alex Perrycb7da4b2019-08-28 19:35:56 -070042 AbsoluteEncoderZeroingEstimator *estimator, double new_position) {
Austin Schuhd82068e2019-01-26 20:05:42 -080043 simulator->MoveTo(new_position);
Alex Perrycb7da4b2019-08-28 19:35:56 -070044 FBB fbb;
45 estimator->UpdateEstimate(
46 *simulator->FillSensorValues<AbsolutePosition>(&fbb));
Austin Schuhd82068e2019-01-26 20:05:42 -080047 }
48
49 void MoveTo(PositionSensorSimulator *simulator,
Austin Schuh72db9a12019-01-21 18:02:51 -080050 PotAndAbsoluteEncoderZeroingEstimator *estimator,
Neil Balch16275e32017-02-18 16:38:45 -080051 double new_position) {
Austin Schuh5f01f152017-02-11 21:34:08 -080052 simulator->MoveTo(new_position);
Alex Perrycb7da4b2019-08-28 19:35:56 -070053 FBB fbb;
54 estimator->UpdateEstimate(
55 *simulator->FillSensorValues<PotAndAbsolutePosition>(&fbb));
Austin Schuh5f01f152017-02-11 21:34:08 -080056 }
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000057
58 void MoveTo(PositionSensorSimulator *simulator,
59 PulseIndexZeroingEstimator *estimator, double new_position) {
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000060 simulator->MoveTo(new_position);
Alex Perrycb7da4b2019-08-28 19:35:56 -070061 FBB fbb;
62 estimator->UpdateEstimate(
63 *simulator->FillSensorValues<IndexPosition>(&fbb));
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000064 }
Austin Schuh5f01f152017-02-11 21:34:08 -080065
Austin Schuh55934032017-03-11 12:45:27 -080066 void MoveTo(PositionSensorSimulator *simulator,
67 HallEffectAndPositionZeroingEstimator *estimator,
68 double new_position) {
Austin Schuh55934032017-03-11 12:45:27 -080069 simulator->MoveTo(new_position);
Alex Perrycb7da4b2019-08-28 19:35:56 -070070 FBB fbb;
71 estimator->UpdateEstimate(
72 *simulator->FillSensorValues<HallEffectAndPosition>(&fbb));
Austin Schuh55934032017-03-11 12:45:27 -080073 }
74
Tyler Chatow3c47f3c2020-01-29 20:45:23 -080075 void MoveTo(PositionSensorSimulator *simulator,
76 RelativeEncoderZeroingEstimator *estimator, double new_position) {
77 simulator->MoveTo(new_position);
78 FBB fbb;
79 estimator->UpdateEstimate(
80 *simulator->FillSensorValues<RelativePosition>(&fbb));
81 }
82
Alex Perrycb7da4b2019-08-28 19:35:56 -070083 template <typename T>
84 double GetEstimatorPosition(T *estimator) {
85 FBB fbb;
86 fbb.Finish(estimator->GetEstimatorState(&fbb));
87 return flatbuffers::GetRoot<typename T::State>(fbb.GetBufferPointer())
88 ->position();
89 }
Adam Snaiderc4b3c192015-02-01 01:30:39 +000090};
91
Adam Snaiderb4119252015-02-15 01:30:57 +000092TEST_F(ZeroingTest, TestMovingAverageFilter) {
93 const double index_diff = 1.0;
94 PositionSensorSimulator sim(index_diff);
95 sim.Initialize(3.6 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -080096 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +000097 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +000098
99 // The zeroing code is supposed to perform some filtering on the difference
100 // between the potentiometer value and the encoder value. We assume that 300
101 // samples are sufficient to have updated the filter.
102 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000103 MoveTo(&sim, &estimator, 3.3 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000104 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700105 ASSERT_NEAR(3.3 * index_diff, GetEstimatorPosition(&estimator),
Adam Snaiderb4119252015-02-15 01:30:57 +0000106 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000107
108 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000109 MoveTo(&sim, &estimator, 3.9 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000110 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111 ASSERT_NEAR(3.9 * index_diff, GetEstimatorPosition(&estimator),
Adam Snaiderb4119252015-02-15 01:30:57 +0000112 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000113}
114
Adam Snaiderb4119252015-02-15 01:30:57 +0000115TEST_F(ZeroingTest, NotZeroedBeforeEnoughSamplesCollected) {
116 double index_diff = 0.5;
117 double position = 3.6 * index_diff;
118 PositionSensorSimulator sim(index_diff);
119 sim.Initialize(position, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800120 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000121 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +0000122
123 // Make sure that the zeroing code does not consider itself zeroed until we
124 // collect a good amount of samples. In this case we're waiting until the
125 // moving average filter is full.
126 for (unsigned int i = 0; i < kSampleSize - 1; i++) {
127 MoveTo(&sim, &estimator, position += index_diff);
128 ASSERT_FALSE(estimator.zeroed());
129 }
130
131 MoveTo(&sim, &estimator, position);
132 ASSERT_TRUE(estimator.zeroed());
133}
134
135TEST_F(ZeroingTest, TestLotsOfMovement) {
136 double index_diff = 1.0;
137 PositionSensorSimulator sim(index_diff);
138 sim.Initialize(3.6, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800139 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000140 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000141
142 // The zeroing code is supposed to perform some filtering on the difference
143 // between the potentiometer value and the encoder value. We assume that 300
144 // samples are sufficient to have updated the filter.
145 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000146 MoveTo(&sim, &estimator, 3.6);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000147 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700148 ASSERT_NEAR(3.6, GetEstimatorPosition(&estimator),
Brian Silvermanf37839c2017-02-19 18:07:15 -0800149 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000150
151 // With a single index pulse the zeroing estimator should be able to lock
152 // onto the true value of the position.
Adam Snaiderb4119252015-02-15 01:30:57 +0000153 MoveTo(&sim, &estimator, 4.01);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700154 ASSERT_NEAR(4.01, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000155
Adam Snaiderb4119252015-02-15 01:30:57 +0000156 MoveTo(&sim, &estimator, 4.99);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700157 ASSERT_NEAR(4.99, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000158
Adam Snaiderb4119252015-02-15 01:30:57 +0000159 MoveTo(&sim, &estimator, 3.99);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700160 ASSERT_NEAR(3.99, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000161
Adam Snaiderb4119252015-02-15 01:30:57 +0000162 MoveTo(&sim, &estimator, 3.01);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700163 ASSERT_NEAR(3.01, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000164
Adam Snaiderb4119252015-02-15 01:30:57 +0000165 MoveTo(&sim, &estimator, 13.55);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700166 ASSERT_NEAR(13.55, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000167}
168
Adam Snaiderb4119252015-02-15 01:30:57 +0000169TEST_F(ZeroingTest, TestDifferentIndexDiffs) {
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000170 double index_diff = 0.89;
Adam Snaiderb4119252015-02-15 01:30:57 +0000171 PositionSensorSimulator sim(index_diff);
172 sim.Initialize(3.5 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800173 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000174 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000175
176 // The zeroing code is supposed to perform some filtering on the difference
177 // between the potentiometer value and the encoder value. We assume that 300
178 // samples are sufficient to have updated the filter.
179 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000180 MoveTo(&sim, &estimator, 3.5 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000181 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700182 ASSERT_NEAR(3.5 * index_diff, GetEstimatorPosition(&estimator),
Adam Snaiderb4119252015-02-15 01:30:57 +0000183 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000184
185 // With a single index pulse the zeroing estimator should be able to lock
186 // onto the true value of the position.
Adam Snaiderb4119252015-02-15 01:30:57 +0000187 MoveTo(&sim, &estimator, 4.01);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700188 ASSERT_NEAR(4.01, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000189
Adam Snaiderb4119252015-02-15 01:30:57 +0000190 MoveTo(&sim, &estimator, 4.99);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700191 ASSERT_NEAR(4.99, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000192
Adam Snaiderb4119252015-02-15 01:30:57 +0000193 MoveTo(&sim, &estimator, 3.99);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700194 ASSERT_NEAR(3.99, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000195
Adam Snaiderb4119252015-02-15 01:30:57 +0000196 MoveTo(&sim, &estimator, 3.01);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700197 ASSERT_NEAR(3.01, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000198
Adam Snaiderb4119252015-02-15 01:30:57 +0000199 MoveTo(&sim, &estimator, 13.55);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700200 ASSERT_NEAR(13.55, GetEstimatorPosition(&estimator), 0.001);
Adam Snaiderb4119252015-02-15 01:30:57 +0000201}
202
203TEST_F(ZeroingTest, TestPercentage) {
204 double index_diff = 0.89;
205 PositionSensorSimulator sim(index_diff);
206 sim.Initialize(3.5 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800207 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000208 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +0000209
210 for (unsigned int i = 0; i < kSampleSize / 2; i++) {
211 MoveTo(&sim, &estimator, 3.5 * index_diff);
212 }
213 ASSERT_NEAR(0.5, estimator.offset_ratio_ready(), 0.001);
Austin Schuh7485dbb2016-02-08 00:21:58 -0800214 ASSERT_FALSE(estimator.offset_ready());
215
216 for (unsigned int i = 0; i < kSampleSize / 2; i++) {
217 MoveTo(&sim, &estimator, 3.5 * index_diff);
218 }
219 ASSERT_NEAR(1.0, estimator.offset_ratio_ready(), 0.001);
220 ASSERT_TRUE(estimator.offset_ready());
Adam Snaiderb4119252015-02-15 01:30:57 +0000221}
222
223TEST_F(ZeroingTest, TestOffset) {
224 double index_diff = 0.89;
225 PositionSensorSimulator sim(index_diff);
226 sim.Initialize(3.1 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800227 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000228 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +0000229
Philipp Schrader41d82912015-02-15 03:44:23 +0000230 MoveTo(&sim, &estimator, 3.1 * index_diff);
231
Adam Snaiderb4119252015-02-15 01:30:57 +0000232 for (unsigned int i = 0; i < kSampleSize; i++) {
233 MoveTo(&sim, &estimator, 5.0 * index_diff);
234 }
Philipp Schrader41d82912015-02-15 03:44:23 +0000235
Adam Snaiderb4119252015-02-15 01:30:57 +0000236 ASSERT_NEAR(3.1 * index_diff, estimator.offset(), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000237}
238
Philipp Schrader41d82912015-02-15 03:44:23 +0000239TEST_F(ZeroingTest, WaitForIndexPulseAfterReset) {
240 double index_diff = 0.6;
241 PositionSensorSimulator sim(index_diff);
242 sim.Initialize(3.1 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800243 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000244 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Philipp Schrader41d82912015-02-15 03:44:23 +0000245
246 // Make sure to fill up the averaging filter with samples.
247 for (unsigned int i = 0; i < kSampleSize; i++) {
248 MoveTo(&sim, &estimator, 3.1 * index_diff);
249 }
250
251 // Make sure we're not zeroed until we hit an index pulse.
252 ASSERT_FALSE(estimator.zeroed());
253
254 // Trigger an index pulse; we should now be zeroed.
255 MoveTo(&sim, &estimator, 4.5 * index_diff);
256 ASSERT_TRUE(estimator.zeroed());
257
258 // Reset the zeroing logic and supply a bunch of samples within the current
259 // index segment.
260 estimator.Reset();
261 for (unsigned int i = 0; i < kSampleSize; i++) {
262 MoveTo(&sim, &estimator, 4.2 * index_diff);
263 }
264
265 // Make sure we're not zeroed until we hit an index pulse.
266 ASSERT_FALSE(estimator.zeroed());
267
268 // Trigger another index pulse; we should be zeroed again.
269 MoveTo(&sim, &estimator, 3.1 * index_diff);
270 ASSERT_TRUE(estimator.zeroed());
271}
272
Philipp Schrader030ad182015-02-15 05:40:58 +0000273TEST_F(ZeroingTest, TestNonZeroIndexPulseOffsets) {
274 const double index_diff = 0.9;
275 const double known_index_pos = 3.5 * index_diff;
276 PositionSensorSimulator sim(index_diff);
277 sim.Initialize(3.3 * index_diff, index_diff / 3.0, known_index_pos);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800278 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000279 kSampleSize, index_diff, known_index_pos, kIndexErrorFraction});
Philipp Schrader030ad182015-02-15 05:40:58 +0000280
281 // Make sure to fill up the averaging filter with samples.
282 for (unsigned int i = 0; i < kSampleSize; i++) {
283 MoveTo(&sim, &estimator, 3.3 * index_diff);
284 }
285
286 // Make sure we're not zeroed until we hit an index pulse.
287 ASSERT_FALSE(estimator.zeroed());
288
289 // Trigger an index pulse; we should now be zeroed.
290 MoveTo(&sim, &estimator, 3.7 * index_diff);
291 ASSERT_TRUE(estimator.zeroed());
292 ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700293 ASSERT_DOUBLE_EQ(3.7 * index_diff, GetEstimatorPosition(&estimator));
Philipp Schrader030ad182015-02-15 05:40:58 +0000294
295 // Trigger one more index pulse and check the offset.
296 MoveTo(&sim, &estimator, 4.7 * index_diff);
297 ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
Alex Perrycb7da4b2019-08-28 19:35:56 -0700298 ASSERT_DOUBLE_EQ(4.7 * index_diff, GetEstimatorPosition(&estimator));
Philipp Schrader030ad182015-02-15 05:40:58 +0000299}
300
Philipp Schrader53f4b6d2015-02-15 22:32:08 +0000301TEST_F(ZeroingTest, BasicErrorAPITest) {
302 const double index_diff = 1.0;
Tyler Chatowf8f03112017-02-05 14:31:34 -0800303 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000304 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Philipp Schrader53f4b6d2015-02-15 22:32:08 +0000305 PositionSensorSimulator sim(index_diff);
306 sim.Initialize(1.5 * index_diff, index_diff / 3.0, 0.0);
307
308 // Perform a simple move and make sure that no error occured.
309 MoveTo(&sim, &estimator, 3.5 * index_diff);
310 ASSERT_FALSE(estimator.error());
311
312 // Trigger an error and make sure it's reported.
313 estimator.TriggerError();
314 ASSERT_TRUE(estimator.error());
315
316 // Make sure that it can recover after a reset.
317 estimator.Reset();
318 ASSERT_FALSE(estimator.error());
319 MoveTo(&sim, &estimator, 4.5 * index_diff);
320 MoveTo(&sim, &estimator, 5.5 * index_diff);
321 ASSERT_FALSE(estimator.error());
322}
323
Brian Silvermana10d20a2017-02-19 14:28:53 -0800324// Tests that an error is detected when the starting position changes too much.
325TEST_F(ZeroingTest, TestIndexOffsetError) {
Adam Snaider3cd11c52015-02-16 02:16:09 +0000326 const double index_diff = 0.8;
327 const double known_index_pos = 2 * index_diff;
Austin Schuh5f01f152017-02-11 21:34:08 -0800328 const size_t sample_size = 30;
Adam Snaider3cd11c52015-02-16 02:16:09 +0000329 PositionSensorSimulator sim(index_diff);
330 sim.Initialize(10 * index_diff, index_diff / 3.0, known_index_pos);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800331 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000332 sample_size, index_diff, known_index_pos, kIndexErrorFraction});
333
Austin Schuh5f01f152017-02-11 21:34:08 -0800334 for (size_t i = 0; i < sample_size; i++) {
Adam Snaider3cd11c52015-02-16 02:16:09 +0000335 MoveTo(&sim, &estimator, 13 * index_diff);
336 }
337 MoveTo(&sim, &estimator, 8 * index_diff);
338
339 ASSERT_TRUE(estimator.zeroed());
340 ASSERT_FALSE(estimator.error());
341 sim.Initialize(9.0 * index_diff + 0.31 * index_diff, index_diff / 3.0,
342 known_index_pos);
343 MoveTo(&sim, &estimator, 9 * index_diff);
344 ASSERT_TRUE(estimator.zeroed());
345 ASSERT_TRUE(estimator.error());
346}
347
Austin Schuh5f01f152017-02-11 21:34:08 -0800348// Makes sure that using an absolute encoder lets us zero without moving.
Austin Schuhd82068e2019-01-26 20:05:42 -0800349TEST_F(ZeroingTest, TestPotAndAbsoluteEncoderZeroingWithoutMovement) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800350 const double index_diff = 1.0;
351 PositionSensorSimulator sim(index_diff);
352
353 const double start_pos = 2.1;
354 double measured_absolute_position = 0.3 * index_diff;
355
Brian Silvermana10d20a2017-02-19 14:28:53 -0800356 PotAndAbsoluteEncoderZeroingConstants constants{
357 kSampleSize, index_diff, measured_absolute_position,
358 0.1, kMovingBufferSize, kIndexErrorFraction};
Austin Schuh5f01f152017-02-11 21:34:08 -0800359
360 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
361 constants.measured_absolute_position);
362
Austin Schuh72db9a12019-01-21 18:02:51 -0800363 PotAndAbsoluteEncoderZeroingEstimator estimator(constants);
Austin Schuh5f01f152017-02-11 21:34:08 -0800364
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800365 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800366 MoveTo(&sim, &estimator, start_pos);
367 ASSERT_FALSE(estimator.zeroed());
368 }
369
370 MoveTo(&sim, &estimator, start_pos);
371 ASSERT_TRUE(estimator.zeroed());
372 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
373}
374
Austin Schuhddd08f82018-03-02 20:05:29 -0800375// Makes sure that we ignore a NAN if we get it, but will correctly zero
Austin Schuhd82068e2019-01-26 20:05:42 -0800376// afterwards.
377TEST_F(ZeroingTest, TestPotAndAbsoluteEncoderZeroingIgnoresNAN) {
Austin Schuhddd08f82018-03-02 20:05:29 -0800378 const double index_diff = 1.0;
379 PositionSensorSimulator sim(index_diff);
380
381 const double start_pos = 2.1;
382 double measured_absolute_position = 0.3 * index_diff;
383
384 PotAndAbsoluteEncoderZeroingConstants constants{
385 kSampleSize, index_diff, measured_absolute_position,
386 0.1, kMovingBufferSize, kIndexErrorFraction};
387
388 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
389 constants.measured_absolute_position);
390
Austin Schuh72db9a12019-01-21 18:02:51 -0800391 PotAndAbsoluteEncoderZeroingEstimator estimator(constants);
Austin Schuhddd08f82018-03-02 20:05:29 -0800392
393 // We tolerate a couple NANs before we start.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700394 FBB fbb;
395 fbb.Finish(CreatePotAndAbsolutePosition(
396 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN(), 0.0));
Austin Schuhddd08f82018-03-02 20:05:29 -0800397 for (size_t i = 0; i < kSampleSize - 1; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700398 estimator.UpdateEstimate(
399 *flatbuffers::GetRoot<PotAndAbsolutePosition>(fbb.GetBufferPointer()));
Austin Schuhddd08f82018-03-02 20:05:29 -0800400 }
401
402 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
403 MoveTo(&sim, &estimator, start_pos);
404 ASSERT_FALSE(estimator.zeroed());
405 }
406
407 MoveTo(&sim, &estimator, start_pos);
408 ASSERT_TRUE(estimator.zeroed());
409 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
410}
411
Austin Schuh5f01f152017-02-11 21:34:08 -0800412// Makes sure that using an absolute encoder doesn't let us zero while moving.
Austin Schuhd82068e2019-01-26 20:05:42 -0800413TEST_F(ZeroingTest, TestPotAndAbsoluteEncoderZeroingWithMovement) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800414 const double index_diff = 1.0;
415 PositionSensorSimulator sim(index_diff);
416
417 const double start_pos = 10 * index_diff;
418 double measured_absolute_position = 0.3 * index_diff;
419
Brian Silvermana10d20a2017-02-19 14:28:53 -0800420 PotAndAbsoluteEncoderZeroingConstants constants{
421 kSampleSize, index_diff, measured_absolute_position,
422 0.1, kMovingBufferSize, kIndexErrorFraction};
Austin Schuh5f01f152017-02-11 21:34:08 -0800423
424 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
425 constants.measured_absolute_position);
426
Austin Schuh72db9a12019-01-21 18:02:51 -0800427 PotAndAbsoluteEncoderZeroingEstimator estimator(constants);
Austin Schuh5f01f152017-02-11 21:34:08 -0800428
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800429 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800430 MoveTo(&sim, &estimator, start_pos + i * index_diff);
431 ASSERT_FALSE(estimator.zeroed());
432 }
433 MoveTo(&sim, &estimator, start_pos + 10 * index_diff);
434
435 MoveTo(&sim, &estimator, start_pos);
436 ASSERT_FALSE(estimator.zeroed());
437}
Neil Balch16275e32017-02-18 16:38:45 -0800438
439// Makes sure we detect an error if the ZeroingEstimator gets sent a NaN.
Austin Schuhd82068e2019-01-26 20:05:42 -0800440TEST_F(ZeroingTest, TestPotAndAbsoluteEncoderZeroingWithNaN) {
Neil Balch16275e32017-02-18 16:38:45 -0800441 PotAndAbsoluteEncoderZeroingConstants constants{
Brian Silvermana10d20a2017-02-19 14:28:53 -0800442 kSampleSize, 1, 0.3, 0.1, kMovingBufferSize, kIndexErrorFraction};
Neil Balch16275e32017-02-18 16:38:45 -0800443
Austin Schuh72db9a12019-01-21 18:02:51 -0800444 PotAndAbsoluteEncoderZeroingEstimator estimator(constants);
Neil Balch16275e32017-02-18 16:38:45 -0800445
Alex Perrycb7da4b2019-08-28 19:35:56 -0700446 FBB fbb;
447 fbb.Finish(CreatePotAndAbsolutePosition(
448 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN(), 0.0));
449 const auto sensor_values =
450 flatbuffers::GetRoot<PotAndAbsolutePosition>(fbb.GetBufferPointer());
Austin Schuhddd08f82018-03-02 20:05:29 -0800451 for (size_t i = 0; i < kSampleSize - 1; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700452 estimator.UpdateEstimate(*sensor_values);
Austin Schuhddd08f82018-03-02 20:05:29 -0800453 }
454 ASSERT_FALSE(estimator.error());
Neil Balch16275e32017-02-18 16:38:45 -0800455
Alex Perrycb7da4b2019-08-28 19:35:56 -0700456 estimator.UpdateEstimate(*sensor_values);
Neil Balch16275e32017-02-18 16:38:45 -0800457 ASSERT_TRUE(estimator.error());
458}
459
Brian Silvermana10d20a2017-02-19 14:28:53 -0800460// Tests that an error is detected when the starting position changes too much.
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000461TEST_F(ZeroingTest, TestRelativeEncoderZeroing) {
462 EncoderPlusIndexZeroingConstants constants;
463 constants.index_pulse_count = 3;
464 constants.index_difference = 10.0;
465 constants.measured_index_position = 20.0;
466 constants.known_index_pulse = 1;
Philipp Schrader3f5b6182017-03-25 22:36:37 +0000467 constants.allowable_encoder_error = 0.01;
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000468
469 PositionSensorSimulator sim(constants.index_difference);
470
471 const double start_pos = 2.5 * constants.index_difference;
472
473 sim.Initialize(start_pos, constants.index_difference / 3.0,
474 constants.measured_index_position);
475
476 PulseIndexZeroingEstimator estimator(constants);
477
478 // Should not be zeroed when we stand still.
479 for (int i = 0; i < 300; ++i) {
480 MoveTo(&sim, &estimator, start_pos);
481 ASSERT_FALSE(estimator.zeroed());
482 }
483
484 // Move to 1.5 constants.index_difference and we should still not be zeroed.
485 MoveTo(&sim, &estimator, 1.5 * constants.index_difference);
486 ASSERT_FALSE(estimator.zeroed());
487
488 // Move to 0.5 constants.index_difference and we should still not be zeroed.
489 MoveTo(&sim, &estimator, 0.5 * constants.index_difference);
490 ASSERT_FALSE(estimator.zeroed());
491
492 // Move back to 1.5 constants.index_difference and we should still not be
493 // zeroed.
494 MoveTo(&sim, &estimator, 1.5 * constants.index_difference);
495 ASSERT_FALSE(estimator.zeroed());
496
497 // Move back to 2.5 constants.index_difference and we should still not be
498 // zeroed.
499 MoveTo(&sim, &estimator, 2.5 * constants.index_difference);
500 ASSERT_FALSE(estimator.zeroed());
501
502 // Move back to 3.5 constants.index_difference and we should now be zeroed.
503 MoveTo(&sim, &estimator, 3.5 * constants.index_difference);
504 ASSERT_TRUE(estimator.zeroed());
505
506 ASSERT_DOUBLE_EQ(start_pos, estimator.offset());
Brian Silvermanf37839c2017-02-19 18:07:15 -0800507 ASSERT_DOUBLE_EQ(3.5 * constants.index_difference,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700508 GetEstimatorPosition(&estimator));
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000509
510 MoveTo(&sim, &estimator, 0.5 * constants.index_difference);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800511 ASSERT_DOUBLE_EQ(0.5 * constants.index_difference,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700512 GetEstimatorPosition(&estimator));
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000513}
514
Philipp Schrader3f5b6182017-03-25 22:36:37 +0000515// Tests that we can detect when an index pulse occurs where we didn't expect
516// it to for the PulseIndexZeroingEstimator.
517TEST_F(ZeroingTest, TestRelativeEncoderSlipping) {
518 EncoderPlusIndexZeroingConstants constants;
519 constants.index_pulse_count = 3;
520 constants.index_difference = 10.0;
521 constants.measured_index_position = 20.0;
522 constants.known_index_pulse = 1;
523 constants.allowable_encoder_error = 0.05;
524
525 PositionSensorSimulator sim(constants.index_difference);
526
527 const double start_pos =
528 constants.measured_index_position + 0.5 * constants.index_difference;
529
530 for (double direction : {1.0, -1.0}) {
531 sim.Initialize(start_pos, constants.index_difference / 3.0,
532 constants.measured_index_position);
533
534 PulseIndexZeroingEstimator estimator(constants);
535
536 // Zero the estimator.
537 MoveTo(&sim, &estimator, start_pos - 1 * constants.index_difference);
538 MoveTo(
539 &sim, &estimator,
540 start_pos - constants.index_pulse_count * constants.index_difference);
541 ASSERT_TRUE(estimator.zeroed());
542 ASSERT_FALSE(estimator.error());
543
544 // We have a 5% allowable error so we slip a little bit each time and make
545 // sure that the index pulses are still accepted.
546 for (double error = 0.00;
547 ::std::abs(error) < constants.allowable_encoder_error;
548 error += 0.01 * direction) {
549 sim.Initialize(start_pos, constants.index_difference / 3.0,
550 constants.measured_index_position +
551 error * constants.index_difference);
552 MoveTo(&sim, &estimator, start_pos - constants.index_difference);
553 EXPECT_FALSE(estimator.error());
554 }
555
556 // As soon as we hit cross the error margin, we should trigger an error.
557 sim.Initialize(start_pos, constants.index_difference / 3.0,
558 constants.measured_index_position +
559 constants.allowable_encoder_error * 1.1 *
560 constants.index_difference * direction);
561 MoveTo(&sim, &estimator, start_pos - constants.index_difference);
562 ASSERT_TRUE(estimator.error());
563 }
564}
565
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700566// Test fixture for HallEffectAndPositionZeroingEstimator.
567class HallEffectAndPositionZeroingEstimatorTest : public ZeroingTest {
568 public:
569 // The starting position of the system.
570 static constexpr double kStartPosition = 2.0;
571
572 // Returns a reasonable set of test constants.
573 static constants::HallEffectZeroingConstants MakeConstants() {
574 constants::HallEffectZeroingConstants constants;
575 constants.lower_hall_position = 0.25;
576 constants.upper_hall_position = 0.75;
577 constants.index_difference = 1.0;
578 constants.hall_trigger_zeroing_length = 2;
579 constants.zeroing_move_direction = false;
580 return constants;
581 }
582
583 HallEffectAndPositionZeroingEstimatorTest()
584 : constants_(MakeConstants()), sim_(constants_.index_difference) {
585 // Start the system out at the starting position.
586 sim_.InitializeHallEffectAndPosition(kStartPosition,
587 constants_.lower_hall_position,
588 constants_.upper_hall_position);
589 }
590
591 protected:
592 // Constants, and the simulation using them.
593 const constants::HallEffectZeroingConstants constants_;
594 PositionSensorSimulator sim_;
595};
596
Austin Schuh55934032017-03-11 12:45:27 -0800597// Tests that an error is detected when the starting position changes too much.
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700598TEST_F(HallEffectAndPositionZeroingEstimatorTest, TestHallEffectZeroing) {
599 HallEffectAndPositionZeroingEstimator estimator(constants_);
Austin Schuh55934032017-03-11 12:45:27 -0800600
601 // Should not be zeroed when we stand still.
602 for (int i = 0; i < 300; ++i) {
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700603 MoveTo(&sim_, &estimator, kStartPosition);
Austin Schuh55934032017-03-11 12:45:27 -0800604 ASSERT_FALSE(estimator.zeroed());
605 }
606
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700607 MoveTo(&sim_, &estimator, 1.9);
Austin Schuh55934032017-03-11 12:45:27 -0800608 ASSERT_FALSE(estimator.zeroed());
609
610 // Move to where the hall effect is triggered and make sure it becomes zeroed.
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700611 MoveTo(&sim_, &estimator, 1.5);
Austin Schuh55934032017-03-11 12:45:27 -0800612 EXPECT_FALSE(estimator.zeroed());
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700613 MoveTo(&sim_, &estimator, 1.5);
Austin Schuh55934032017-03-11 12:45:27 -0800614 ASSERT_TRUE(estimator.zeroed());
615
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700616 // Check that the offset is calculated correctly. We should expect to read
617 // 0.5. Since the encoder is reading -0.5 right now, the offset needs to be
618 // 1.
619 EXPECT_DOUBLE_EQ(1.0, estimator.offset());
Austin Schuh55934032017-03-11 12:45:27 -0800620
621 // Make sure triggering errors works.
622 estimator.TriggerError();
623 ASSERT_TRUE(estimator.error());
624
625 // Ensure resetting resets the state of the estimator.
626 estimator.Reset();
627 ASSERT_FALSE(estimator.zeroed());
628 ASSERT_FALSE(estimator.error());
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700629}
Austin Schuh55934032017-03-11 12:45:27 -0800630
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700631// Tests that we don't zero on a too short pulse.
632TEST_F(HallEffectAndPositionZeroingEstimatorTest, TestTooShortPulse) {
633 HallEffectAndPositionZeroingEstimator estimator(constants_);
Austin Schuh55934032017-03-11 12:45:27 -0800634
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700635 // Trigger for 1 cycle.
636 MoveTo(&sim_, &estimator, 0.9);
Austin Schuh55934032017-03-11 12:45:27 -0800637 EXPECT_FALSE(estimator.zeroed());
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700638 MoveTo(&sim_, &estimator, 0.5);
Austin Schuh55934032017-03-11 12:45:27 -0800639 EXPECT_FALSE(estimator.zeroed());
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700640 MoveTo(&sim_, &estimator, 0.9);
Austin Schuh55934032017-03-11 12:45:27 -0800641 EXPECT_FALSE(estimator.zeroed());
642}
643
Austin Schuh1fe4fb42017-10-16 22:35:54 -0700644// Tests that we don't zero when we go the wrong direction.
645TEST_F(HallEffectAndPositionZeroingEstimatorTest, TestWrongDirectionNoZero) {
646 HallEffectAndPositionZeroingEstimator estimator(constants_);
647
648 // Pass through the sensor, lingering long enough that we should zero.
649 MoveTo(&sim_, &estimator, 0.0);
650 ASSERT_FALSE(estimator.zeroed());
651 MoveTo(&sim_, &estimator, 0.4);
652 EXPECT_FALSE(estimator.zeroed());
653 MoveTo(&sim_, &estimator, 0.6);
654 EXPECT_FALSE(estimator.zeroed());
655 MoveTo(&sim_, &estimator, 0.7);
656 EXPECT_FALSE(estimator.zeroed());
657 MoveTo(&sim_, &estimator, 0.9);
658 EXPECT_FALSE(estimator.zeroed());
659}
660
661// Make sure we don't zero if we start in the hall effect's range.
662TEST_F(HallEffectAndPositionZeroingEstimatorTest, TestStartingOnNoZero) {
663 HallEffectAndPositionZeroingEstimator estimator(constants_);
664 MoveTo(&sim_, &estimator, 0.5);
665 estimator.Reset();
666
667 // Stay on the hall effect. We shouldn't zero.
668 EXPECT_FALSE(estimator.zeroed());
669 MoveTo(&sim_, &estimator, 0.5);
670 EXPECT_FALSE(estimator.zeroed());
671 MoveTo(&sim_, &estimator, 0.5);
672 EXPECT_FALSE(estimator.zeroed());
673
674 // Verify moving off the hall still doesn't zero us.
675 MoveTo(&sim_, &estimator, 0.0);
676 EXPECT_FALSE(estimator.zeroed());
677 MoveTo(&sim_, &estimator, 0.0);
678 EXPECT_FALSE(estimator.zeroed());
679}
Austin Schuh55934032017-03-11 12:45:27 -0800680
Austin Schuhd82068e2019-01-26 20:05:42 -0800681// Makes sure that using an absolute encoder lets us zero without moving.
682TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithoutMovement) {
683 const double index_diff = 1.0;
684 PositionSensorSimulator sim(index_diff);
685
686 const double kMiddlePosition = 2.5;
687 const double start_pos = 2.1;
688 double measured_absolute_position = 0.3 * index_diff;
689
690 AbsoluteEncoderZeroingConstants constants{
691 kSampleSize, index_diff, measured_absolute_position,
692 kMiddlePosition, 0.1, kMovingBufferSize,
693 kIndexErrorFraction};
694
695 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
696 constants.measured_absolute_position);
697
698 AbsoluteEncoderZeroingEstimator estimator(constants);
699
700 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
701 MoveTo(&sim, &estimator, start_pos);
702 ASSERT_FALSE(estimator.zeroed());
703 }
704
705 MoveTo(&sim, &estimator, start_pos);
706 ASSERT_TRUE(estimator.zeroed());
707 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
708}
709
710// Makes sure that we ignore a NAN if we get it, but will correctly zero
711// afterwards.
712TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingIgnoresNAN) {
713 const double index_diff = 1.0;
714 PositionSensorSimulator sim(index_diff);
715
716 const double start_pos = 2.1;
717 double measured_absolute_position = 0.3 * index_diff;
718 const double kMiddlePosition = 2.5;
719
720 AbsoluteEncoderZeroingConstants constants{
721 kSampleSize, index_diff, measured_absolute_position,
722 kMiddlePosition, 0.1, kMovingBufferSize,
723 kIndexErrorFraction};
724
725 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
726 constants.measured_absolute_position);
727
728 AbsoluteEncoderZeroingEstimator estimator(constants);
729
730 // We tolerate a couple NANs before we start.
Alex Perrycb7da4b2019-08-28 19:35:56 -0700731 FBB fbb;
732 fbb.Finish(CreateAbsolutePosition(
733 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN()));
734 const auto sensor_values =
735 flatbuffers::GetRoot<AbsolutePosition>(fbb.GetBufferPointer());
Austin Schuhd82068e2019-01-26 20:05:42 -0800736 for (size_t i = 0; i < kSampleSize - 1; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700737 estimator.UpdateEstimate(*sensor_values);
Austin Schuhd82068e2019-01-26 20:05:42 -0800738 }
739
740 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
741 MoveTo(&sim, &estimator, start_pos);
742 ASSERT_FALSE(estimator.zeroed());
743 }
744
745 MoveTo(&sim, &estimator, start_pos);
746 ASSERT_TRUE(estimator.zeroed());
747 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
748}
749
750// Makes sure that using an absolute encoder doesn't let us zero while moving.
751TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithMovement) {
752 const double index_diff = 1.0;
753 PositionSensorSimulator sim(index_diff);
754
755 const double start_pos = 10 * index_diff;
756 double measured_absolute_position = 0.3 * index_diff;
757 const double kMiddlePosition = 2.5;
758
759 AbsoluteEncoderZeroingConstants constants{
760 kSampleSize, index_diff, measured_absolute_position,
761 kMiddlePosition, 0.1, kMovingBufferSize,
762 kIndexErrorFraction};
763
764 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
765 constants.measured_absolute_position);
766
767 AbsoluteEncoderZeroingEstimator estimator(constants);
768
769 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
770 MoveTo(&sim, &estimator, start_pos + i * index_diff);
771 ASSERT_FALSE(estimator.zeroed());
772 }
773 MoveTo(&sim, &estimator, start_pos + 10 * index_diff);
774
775 MoveTo(&sim, &estimator, start_pos);
776 ASSERT_FALSE(estimator.zeroed());
777}
778
779// Makes sure we detect an error if the ZeroingEstimator gets sent a NaN.
780TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithNaN) {
781 AbsoluteEncoderZeroingConstants constants{
782 kSampleSize, 1, 0.3, 1.0, 0.1, kMovingBufferSize, kIndexErrorFraction};
783
784 AbsoluteEncoderZeroingEstimator estimator(constants);
785
Alex Perrycb7da4b2019-08-28 19:35:56 -0700786 FBB fbb;
787 fbb.Finish(CreateAbsolutePosition(
788 fbb, 0.0, ::std::numeric_limits<double>::quiet_NaN()));
789 const auto sensor_values =
790 flatbuffers::GetRoot<AbsolutePosition>(fbb.GetBufferPointer());
Austin Schuhd82068e2019-01-26 20:05:42 -0800791 for (size_t i = 0; i < kSampleSize - 1; ++i) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700792 estimator.UpdateEstimate(*sensor_values);
Austin Schuhd82068e2019-01-26 20:05:42 -0800793 }
794 ASSERT_FALSE(estimator.error());
795
Alex Perrycb7da4b2019-08-28 19:35:56 -0700796 estimator.UpdateEstimate(*sensor_values);
Austin Schuhd82068e2019-01-26 20:05:42 -0800797 ASSERT_TRUE(estimator.error());
798}
799
Tyler Chatow3c47f3c2020-01-29 20:45:23 -0800800TEST_F(ZeroingTest, TestRelativeEncoderZeroingWithoutMovement) {
801 PositionSensorSimulator sim(1.0);
802 RelativeEncoderZeroingEstimator estimator;
803
804 sim.InitializeRelativeEncoder();
805
806 ASSERT_TRUE(estimator.zeroed());
807 ASSERT_TRUE(estimator.offset_ready());
808 EXPECT_DOUBLE_EQ(estimator.offset(), 0.0);
809 EXPECT_DOUBLE_EQ(GetEstimatorPosition(&estimator), 0.0);
810
811 MoveTo(&sim, &estimator, 0.1);
812
813 EXPECT_DOUBLE_EQ(GetEstimatorPosition(&estimator), 0.1);
814}
815
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000816} // namespace zeroing
817} // namespace frc971