blob: e5c681396d542c8ec3695251611810d5cf676b19 [file] [log] [blame]
Adam Snaiderc4b3c192015-02-01 01:30:39 +00001#include <unistd.h>
2
3#include <memory>
4
5#include <random>
6
7#include "gtest/gtest.h"
Adam Snaiderc4b3c192015-02-01 01:30:39 +00008#include "frc971/zeroing/zeroing.h"
Adam Snaiderb4119252015-02-15 01:30:57 +00009#include "frc971/control_loops/control_loops.q.h"
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050010#include "aos/testing/test_shm.h"
Adam Snaiderc4b3c192015-02-01 01:30:39 +000011#include "aos/common/util/thread.h"
12#include "aos/common/die.h"
Adam Snaiderb4119252015-02-15 01:30:57 +000013#include "frc971/control_loops/position_sensor_sim.h"
Adam Snaiderc4b3c192015-02-01 01:30:39 +000014
15namespace frc971 {
16namespace zeroing {
17
Adam Snaiderb4119252015-02-15 01:30:57 +000018using control_loops::PositionSensorSimulator;
Tyler Chatowf8f03112017-02-05 14:31:34 -080019using constants::PotAndIndexPulseZeroingConstants;
Austin Schuh5f01f152017-02-11 21:34:08 -080020using constants::PotAndAbsoluteEncoderZeroingConstants;
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000021using constants::EncoderPlusIndexZeroingConstants;
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:
30 void SetUp() override { aos::SetDieTestMode(true); }
31
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) {
Brian Silvermandc4eb102017-02-05 17:34:41 -080035 PotAndIndexPosition sensor_values;
Adam Snaiderb4119252015-02-15 01:30:57 +000036 simulator->MoveTo(new_position);
Brian Silvermandc4eb102017-02-05 17:34:41 -080037 simulator->GetSensorValues(&sensor_values);
38 estimator->UpdateEstimate(sensor_values);
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,
Neil Balch16275e32017-02-18 16:38:45 -080042 PotAndAbsEncoderZeroingEstimator *estimator,
43 double new_position) {
Austin Schuh5f01f152017-02-11 21:34:08 -080044 PotAndAbsolutePosition sensor_values_;
45 simulator->MoveTo(new_position);
46 simulator->GetSensorValues(&sensor_values_);
47 estimator->UpdateEstimate(sensor_values_);
48 }
Isaac Wilcove0851ffd2017-02-16 04:13:14 +000049
50 void MoveTo(PositionSensorSimulator *simulator,
51 PulseIndexZeroingEstimator *estimator, double new_position) {
52 IndexPosition sensor_values_;
53 simulator->MoveTo(new_position);
54 simulator->GetSensorValues(&sensor_values_);
55 estimator->UpdateEstimate(sensor_values_);
56 }
Austin Schuh5f01f152017-02-11 21:34:08 -080057
Brian Silvermanf5f8d8e2015-12-06 18:39:12 -050058 ::aos::testing::TestSharedMemory my_shm_;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000059};
60
Adam Snaiderb4119252015-02-15 01:30:57 +000061TEST_F(ZeroingTest, TestMovingAverageFilter) {
62 const double index_diff = 1.0;
63 PositionSensorSimulator sim(index_diff);
64 sim.Initialize(3.6 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -080065 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +000066 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +000067
68 // The zeroing code is supposed to perform some filtering on the difference
69 // between the potentiometer value and the encoder value. We assume that 300
70 // samples are sufficient to have updated the filter.
71 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +000072 MoveTo(&sim, &estimator, 3.3 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +000073 }
Brian Silvermanf37839c2017-02-19 18:07:15 -080074 ASSERT_NEAR(3.3 * index_diff, estimator.GetEstimatorState().position,
Adam Snaiderb4119252015-02-15 01:30:57 +000075 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +000076
77 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +000078 MoveTo(&sim, &estimator, 3.9 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +000079 }
Brian Silvermanf37839c2017-02-19 18:07:15 -080080 ASSERT_NEAR(3.9 * index_diff, estimator.GetEstimatorState().position,
Adam Snaiderb4119252015-02-15 01:30:57 +000081 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +000082}
83
Adam Snaiderb4119252015-02-15 01:30:57 +000084TEST_F(ZeroingTest, NotZeroedBeforeEnoughSamplesCollected) {
85 double index_diff = 0.5;
86 double position = 3.6 * index_diff;
87 PositionSensorSimulator sim(index_diff);
88 sim.Initialize(position, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -080089 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +000090 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +000091
92 // Make sure that the zeroing code does not consider itself zeroed until we
93 // collect a good amount of samples. In this case we're waiting until the
94 // moving average filter is full.
95 for (unsigned int i = 0; i < kSampleSize - 1; i++) {
96 MoveTo(&sim, &estimator, position += index_diff);
97 ASSERT_FALSE(estimator.zeroed());
98 }
99
100 MoveTo(&sim, &estimator, position);
101 ASSERT_TRUE(estimator.zeroed());
102}
103
104TEST_F(ZeroingTest, TestLotsOfMovement) {
105 double index_diff = 1.0;
106 PositionSensorSimulator sim(index_diff);
107 sim.Initialize(3.6, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800108 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000109 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000110
111 // The zeroing code is supposed to perform some filtering on the difference
112 // between the potentiometer value and the encoder value. We assume that 300
113 // samples are sufficient to have updated the filter.
114 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000115 MoveTo(&sim, &estimator, 3.6);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000116 }
Brian Silvermanf37839c2017-02-19 18:07:15 -0800117 ASSERT_NEAR(3.6, estimator.GetEstimatorState().position,
118 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000119
120 // With a single index pulse the zeroing estimator should be able to lock
121 // onto the true value of the position.
Adam Snaiderb4119252015-02-15 01:30:57 +0000122 MoveTo(&sim, &estimator, 4.01);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800123 ASSERT_NEAR(4.01, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000124
Adam Snaiderb4119252015-02-15 01:30:57 +0000125 MoveTo(&sim, &estimator, 4.99);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800126 ASSERT_NEAR(4.99, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000127
Adam Snaiderb4119252015-02-15 01:30:57 +0000128 MoveTo(&sim, &estimator, 3.99);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800129 ASSERT_NEAR(3.99, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000130
Adam Snaiderb4119252015-02-15 01:30:57 +0000131 MoveTo(&sim, &estimator, 3.01);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800132 ASSERT_NEAR(3.01, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000133
Adam Snaiderb4119252015-02-15 01:30:57 +0000134 MoveTo(&sim, &estimator, 13.55);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800135 ASSERT_NEAR(13.55, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000136}
137
Adam Snaiderb4119252015-02-15 01:30:57 +0000138TEST_F(ZeroingTest, TestDifferentIndexDiffs) {
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000139 double index_diff = 0.89;
Adam Snaiderb4119252015-02-15 01:30:57 +0000140 PositionSensorSimulator sim(index_diff);
141 sim.Initialize(3.5 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800142 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000143 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000144
145 // The zeroing code is supposed to perform some filtering on the difference
146 // between the potentiometer value and the encoder value. We assume that 300
147 // samples are sufficient to have updated the filter.
148 for (int i = 0; i < 300; i++) {
Adam Snaiderb4119252015-02-15 01:30:57 +0000149 MoveTo(&sim, &estimator, 3.5 * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000150 }
Brian Silvermanf37839c2017-02-19 18:07:15 -0800151 ASSERT_NEAR(3.5 * index_diff, estimator.GetEstimatorState().position,
Adam Snaiderb4119252015-02-15 01:30:57 +0000152 kAcceptableUnzeroedError * index_diff);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000153
154 // With a single index pulse the zeroing estimator should be able to lock
155 // onto the true value of the position.
Adam Snaiderb4119252015-02-15 01:30:57 +0000156 MoveTo(&sim, &estimator, 4.01);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800157 ASSERT_NEAR(4.01, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000158
Adam Snaiderb4119252015-02-15 01:30:57 +0000159 MoveTo(&sim, &estimator, 4.99);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800160 ASSERT_NEAR(4.99, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000161
Adam Snaiderb4119252015-02-15 01:30:57 +0000162 MoveTo(&sim, &estimator, 3.99);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800163 ASSERT_NEAR(3.99, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000164
Adam Snaiderb4119252015-02-15 01:30:57 +0000165 MoveTo(&sim, &estimator, 3.01);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800166 ASSERT_NEAR(3.01, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000167
Adam Snaiderb4119252015-02-15 01:30:57 +0000168 MoveTo(&sim, &estimator, 13.55);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800169 ASSERT_NEAR(13.55, estimator.GetEstimatorState().position, 0.001);
Adam Snaiderb4119252015-02-15 01:30:57 +0000170}
171
172TEST_F(ZeroingTest, TestPercentage) {
173 double index_diff = 0.89;
174 PositionSensorSimulator sim(index_diff);
175 sim.Initialize(3.5 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800176 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000177 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +0000178
179 for (unsigned int i = 0; i < kSampleSize / 2; i++) {
180 MoveTo(&sim, &estimator, 3.5 * index_diff);
181 }
182 ASSERT_NEAR(0.5, estimator.offset_ratio_ready(), 0.001);
Austin Schuh7485dbb2016-02-08 00:21:58 -0800183 ASSERT_FALSE(estimator.offset_ready());
184
185 for (unsigned int i = 0; i < kSampleSize / 2; i++) {
186 MoveTo(&sim, &estimator, 3.5 * index_diff);
187 }
188 ASSERT_NEAR(1.0, estimator.offset_ratio_ready(), 0.001);
189 ASSERT_TRUE(estimator.offset_ready());
Adam Snaiderb4119252015-02-15 01:30:57 +0000190}
191
192TEST_F(ZeroingTest, TestOffset) {
193 double index_diff = 0.89;
194 PositionSensorSimulator sim(index_diff);
195 sim.Initialize(3.1 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800196 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000197 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Adam Snaiderb4119252015-02-15 01:30:57 +0000198
Philipp Schrader41d82912015-02-15 03:44:23 +0000199 MoveTo(&sim, &estimator, 3.1 * index_diff);
200
Adam Snaiderb4119252015-02-15 01:30:57 +0000201 for (unsigned int i = 0; i < kSampleSize; i++) {
202 MoveTo(&sim, &estimator, 5.0 * index_diff);
203 }
Philipp Schrader41d82912015-02-15 03:44:23 +0000204
Adam Snaiderb4119252015-02-15 01:30:57 +0000205 ASSERT_NEAR(3.1 * index_diff, estimator.offset(), 0.001);
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000206}
207
Philipp Schrader41d82912015-02-15 03:44:23 +0000208TEST_F(ZeroingTest, WaitForIndexPulseAfterReset) {
209 double index_diff = 0.6;
210 PositionSensorSimulator sim(index_diff);
211 sim.Initialize(3.1 * index_diff, index_diff / 3.0);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800212 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000213 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Philipp Schrader41d82912015-02-15 03:44:23 +0000214
215 // Make sure to fill up the averaging filter with samples.
216 for (unsigned int i = 0; i < kSampleSize; i++) {
217 MoveTo(&sim, &estimator, 3.1 * index_diff);
218 }
219
220 // Make sure we're not zeroed until we hit an index pulse.
221 ASSERT_FALSE(estimator.zeroed());
222
223 // Trigger an index pulse; we should now be zeroed.
224 MoveTo(&sim, &estimator, 4.5 * index_diff);
225 ASSERT_TRUE(estimator.zeroed());
226
227 // Reset the zeroing logic and supply a bunch of samples within the current
228 // index segment.
229 estimator.Reset();
230 for (unsigned int i = 0; i < kSampleSize; i++) {
231 MoveTo(&sim, &estimator, 4.2 * index_diff);
232 }
233
234 // Make sure we're not zeroed until we hit an index pulse.
235 ASSERT_FALSE(estimator.zeroed());
236
237 // Trigger another index pulse; we should be zeroed again.
238 MoveTo(&sim, &estimator, 3.1 * index_diff);
239 ASSERT_TRUE(estimator.zeroed());
240}
241
Philipp Schrader030ad182015-02-15 05:40:58 +0000242TEST_F(ZeroingTest, TestNonZeroIndexPulseOffsets) {
243 const double index_diff = 0.9;
244 const double known_index_pos = 3.5 * index_diff;
245 PositionSensorSimulator sim(index_diff);
246 sim.Initialize(3.3 * index_diff, index_diff / 3.0, known_index_pos);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800247 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000248 kSampleSize, index_diff, known_index_pos, kIndexErrorFraction});
Philipp Schrader030ad182015-02-15 05:40:58 +0000249
250 // Make sure to fill up the averaging filter with samples.
251 for (unsigned int i = 0; i < kSampleSize; i++) {
252 MoveTo(&sim, &estimator, 3.3 * index_diff);
253 }
254
255 // Make sure we're not zeroed until we hit an index pulse.
256 ASSERT_FALSE(estimator.zeroed());
257
258 // Trigger an index pulse; we should now be zeroed.
259 MoveTo(&sim, &estimator, 3.7 * index_diff);
260 ASSERT_TRUE(estimator.zeroed());
261 ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
Brian Silvermanf37839c2017-02-19 18:07:15 -0800262 ASSERT_DOUBLE_EQ(3.7 * index_diff, estimator.GetEstimatorState().position);
Philipp Schrader030ad182015-02-15 05:40:58 +0000263
264 // Trigger one more index pulse and check the offset.
265 MoveTo(&sim, &estimator, 4.7 * index_diff);
266 ASSERT_DOUBLE_EQ(3.3 * index_diff, estimator.offset());
Brian Silvermanf37839c2017-02-19 18:07:15 -0800267 ASSERT_DOUBLE_EQ(4.7 * index_diff, estimator.GetEstimatorState().position);
Philipp Schrader030ad182015-02-15 05:40:58 +0000268}
269
Philipp Schrader53f4b6d2015-02-15 22:32:08 +0000270TEST_F(ZeroingTest, BasicErrorAPITest) {
271 const double index_diff = 1.0;
Tyler Chatowf8f03112017-02-05 14:31:34 -0800272 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000273 kSampleSize, index_diff, 0.0, kIndexErrorFraction});
Philipp Schrader53f4b6d2015-02-15 22:32:08 +0000274 PositionSensorSimulator sim(index_diff);
275 sim.Initialize(1.5 * index_diff, index_diff / 3.0, 0.0);
276
277 // Perform a simple move and make sure that no error occured.
278 MoveTo(&sim, &estimator, 3.5 * index_diff);
279 ASSERT_FALSE(estimator.error());
280
281 // Trigger an error and make sure it's reported.
282 estimator.TriggerError();
283 ASSERT_TRUE(estimator.error());
284
285 // Make sure that it can recover after a reset.
286 estimator.Reset();
287 ASSERT_FALSE(estimator.error());
288 MoveTo(&sim, &estimator, 4.5 * index_diff);
289 MoveTo(&sim, &estimator, 5.5 * index_diff);
290 ASSERT_FALSE(estimator.error());
291}
292
Adam Snaider3cd11c52015-02-16 02:16:09 +0000293// I want to test that the the zeroing class can
294// detect an error when the starting position
295// changes too much. I do so by creating the
296// simulator at an 'X' positon, making sure
297// that the estimator is zeroed, and then
298// initializing the simulator at another
299// position. After making sure it's zeroed,
300// if the error() function returns true,
301// then, it works.
302TEST_F(ZeroingTest, TestOffsetError) {
303 const double index_diff = 0.8;
304 const double known_index_pos = 2 * index_diff;
Austin Schuh5f01f152017-02-11 21:34:08 -0800305 const size_t sample_size = 30;
Adam Snaider3cd11c52015-02-16 02:16:09 +0000306 PositionSensorSimulator sim(index_diff);
307 sim.Initialize(10 * index_diff, index_diff / 3.0, known_index_pos);
Tyler Chatowf8f03112017-02-05 14:31:34 -0800308 PotAndIndexPulseZeroingEstimator estimator(PotAndIndexPulseZeroingConstants{
Adam Snaider3cd11c52015-02-16 02:16:09 +0000309 sample_size, index_diff, known_index_pos, kIndexErrorFraction});
310
Austin Schuh5f01f152017-02-11 21:34:08 -0800311 for (size_t i = 0; i < sample_size; i++) {
Adam Snaider3cd11c52015-02-16 02:16:09 +0000312 MoveTo(&sim, &estimator, 13 * index_diff);
313 }
314 MoveTo(&sim, &estimator, 8 * index_diff);
315
316 ASSERT_TRUE(estimator.zeroed());
317 ASSERT_FALSE(estimator.error());
318 sim.Initialize(9.0 * index_diff + 0.31 * index_diff, index_diff / 3.0,
319 known_index_pos);
320 MoveTo(&sim, &estimator, 9 * index_diff);
321 ASSERT_TRUE(estimator.zeroed());
322 ASSERT_TRUE(estimator.error());
323}
324
Austin Schuh5f01f152017-02-11 21:34:08 -0800325// Makes sure that using an absolute encoder lets us zero without moving.
326TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithoutMovement) {
327 const double index_diff = 1.0;
328 PositionSensorSimulator sim(index_diff);
329
330 const double start_pos = 2.1;
331 double measured_absolute_position = 0.3 * index_diff;
332
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800333 PotAndAbsoluteEncoderZeroingConstants constants{kSampleSize, index_diff,
334 measured_absolute_position,
335 0.1, kMovingBufferSize};
Austin Schuh5f01f152017-02-11 21:34:08 -0800336
337 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
338 constants.measured_absolute_position);
339
340 PotAndAbsEncoderZeroingEstimator estimator(constants);
341
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800342 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800343 MoveTo(&sim, &estimator, start_pos);
344 ASSERT_FALSE(estimator.zeroed());
345 }
346
347 MoveTo(&sim, &estimator, start_pos);
348 ASSERT_TRUE(estimator.zeroed());
349 EXPECT_DOUBLE_EQ(start_pos, estimator.offset());
350}
351
352// Makes sure that using an absolute encoder doesn't let us zero while moving.
353TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithMovement) {
354 const double index_diff = 1.0;
355 PositionSensorSimulator sim(index_diff);
356
357 const double start_pos = 10 * index_diff;
358 double measured_absolute_position = 0.3 * index_diff;
359
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800360 PotAndAbsoluteEncoderZeroingConstants constants{kSampleSize, index_diff,
361 measured_absolute_position,
362 0.1, kMovingBufferSize};
Austin Schuh5f01f152017-02-11 21:34:08 -0800363
364 sim.Initialize(start_pos, index_diff / 3.0, 0.0,
365 constants.measured_absolute_position);
366
367 PotAndAbsEncoderZeroingEstimator estimator(constants);
368
Diana Vandenberg8fea6ea2017-02-18 17:24:45 -0800369 for (size_t i = 0; i < kSampleSize + kMovingBufferSize - 1; ++i) {
Austin Schuh5f01f152017-02-11 21:34:08 -0800370 MoveTo(&sim, &estimator, start_pos + i * index_diff);
371 ASSERT_FALSE(estimator.zeroed());
372 }
373 MoveTo(&sim, &estimator, start_pos + 10 * index_diff);
374
375 MoveTo(&sim, &estimator, start_pos);
376 ASSERT_FALSE(estimator.zeroed());
377}
Neil Balch16275e32017-02-18 16:38:45 -0800378
379// Makes sure we detect an error if the ZeroingEstimator gets sent a NaN.
380TEST_F(ZeroingTest, TestAbsoluteEncoderZeroingWithNaN) {
381 PotAndAbsoluteEncoderZeroingConstants constants{
382 kSampleSize, 1, 0.3, 0.1, kMovingBufferSize};
383
384 PotAndAbsEncoderZeroingEstimator estimator(constants);
385
386 PotAndAbsolutePosition sensor_values_;
387 sensor_values_.absolute_encoder = ::std::numeric_limits<double>::quiet_NaN();
388 sensor_values_.encoder = 0.0;
389 sensor_values_.pot = 0.0;
390 estimator.UpdateEstimate(sensor_values_);
391
392 ASSERT_TRUE(estimator.error());
393}
394
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000395// Makes sure that using only a relative encoder with index pulses allows us to
396// successfully zero.
397// We pretend that there are index pulses at 10, 20, and 30.
398TEST_F(ZeroingTest, TestRelativeEncoderZeroing) {
399 EncoderPlusIndexZeroingConstants constants;
400 constants.index_pulse_count = 3;
401 constants.index_difference = 10.0;
402 constants.measured_index_position = 20.0;
403 constants.known_index_pulse = 1;
404
405 PositionSensorSimulator sim(constants.index_difference);
406
407 const double start_pos = 2.5 * constants.index_difference;
408
409 sim.Initialize(start_pos, constants.index_difference / 3.0,
410 constants.measured_index_position);
411
412 PulseIndexZeroingEstimator estimator(constants);
413
414 // Should not be zeroed when we stand still.
415 for (int i = 0; i < 300; ++i) {
416 MoveTo(&sim, &estimator, start_pos);
417 ASSERT_FALSE(estimator.zeroed());
418 }
419
420 // Move to 1.5 constants.index_difference and we should still not be zeroed.
421 MoveTo(&sim, &estimator, 1.5 * constants.index_difference);
422 ASSERT_FALSE(estimator.zeroed());
423
424 // Move to 0.5 constants.index_difference and we should still not be zeroed.
425 MoveTo(&sim, &estimator, 0.5 * constants.index_difference);
426 ASSERT_FALSE(estimator.zeroed());
427
428 // Move back to 1.5 constants.index_difference and we should still not be
429 // zeroed.
430 MoveTo(&sim, &estimator, 1.5 * constants.index_difference);
431 ASSERT_FALSE(estimator.zeroed());
432
433 // Move back to 2.5 constants.index_difference and we should still not be
434 // zeroed.
435 MoveTo(&sim, &estimator, 2.5 * constants.index_difference);
436 ASSERT_FALSE(estimator.zeroed());
437
438 // Move back to 3.5 constants.index_difference and we should now be zeroed.
439 MoveTo(&sim, &estimator, 3.5 * constants.index_difference);
440 ASSERT_TRUE(estimator.zeroed());
441
442 ASSERT_DOUBLE_EQ(start_pos, estimator.offset());
Brian Silvermanf37839c2017-02-19 18:07:15 -0800443 ASSERT_DOUBLE_EQ(3.5 * constants.index_difference,
444 estimator.GetEstimatorState().position);
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000445
446 MoveTo(&sim, &estimator, 0.5 * constants.index_difference);
Brian Silvermanf37839c2017-02-19 18:07:15 -0800447 ASSERT_DOUBLE_EQ(0.5 * constants.index_difference,
448 estimator.GetEstimatorState().position);
Isaac Wilcove0851ffd2017-02-16 04:13:14 +0000449}
450
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000451} // namespace zeroing
452} // namespace frc971