blob: 9b2347d614ab51393e8adf82367691b90fc5323d [file] [log] [blame]
Adam Snaiderc4b3c192015-02-01 01:30:39 +00001#include "frc971/zeroing/zeroing.h"
Adam Snaiderb4119252015-02-15 01:30:57 +00002
Adam Snaiderc4b3c192015-02-01 01:30:39 +00003#include <math.h>
4#include <vector>
5
6namespace frc971 {
7namespace zeroing {
8
Daniel Pettiab274232015-02-16 19:15:34 -08009void PopulateEstimatorState(const zeroing::ZeroingEstimator &estimator,
10 EstimatorState *state) {
11 state->error = estimator.error();
12 state->zeroed = estimator.zeroed();
13 state->position = estimator.position();
14}
15
Austin Schuh703b8d42015-02-01 14:56:34 -080016ZeroingEstimator::ZeroingEstimator(
17 const constants::Values::ZeroingConstants& constants) {
Adam Snaiderb4119252015-02-15 01:30:57 +000018 index_diff_ = constants.index_difference;
19 max_sample_count_ = constants.average_filter_size;
Philipp Schrader030ad182015-02-15 05:40:58 +000020 known_index_pos_ = constants.measured_index_position;
Adam Snaiderb4119252015-02-15 01:30:57 +000021
22 start_pos_samples_.reserve(max_sample_count_);
23
24 Reset();
Austin Schuh703b8d42015-02-01 14:56:34 -080025}
26
Adam Snaiderb4119252015-02-15 01:30:57 +000027void ZeroingEstimator::Reset() {
Adam Snaiderc4b3c192015-02-01 01:30:39 +000028 samples_idx_ = 0;
Adam Snaiderb4119252015-02-15 01:30:57 +000029 start_pos_ = 0;
30 start_pos_samples_.clear();
31 zeroed_ = false;
Philipp Schrader41d82912015-02-15 03:44:23 +000032 wait_for_index_pulse_ = true;
Philipp Schradere828be72015-02-15 07:07:37 +000033 last_used_index_pulse_count_ = 0;
Philipp Schrader53f4b6d2015-02-15 22:32:08 +000034 error_ = false;
35}
36
37void ZeroingEstimator::TriggerError() {
38 if (!error_) {
39 LOG(ERROR, "Manually triggered zeroing error.\n");
40 error_ = true;
41 }
Philipp Schradere828be72015-02-15 07:07:37 +000042}
43
44double ZeroingEstimator::CalculateStartPosition(double start_average,
45 double latched_encoder) const {
46 // We calculate an aproximation of the value of the last index position.
47 // Also account for index pulses not lining up with integer multiples of the
48 // index_diff.
49 double index_pos = start_average + latched_encoder - known_index_pos_;
50 // We round index_pos to the closest valid value of the index.
51 double accurate_index_pos = (round(index_pos / index_diff_)) * index_diff_;
52 // Now we reverse the first calculation to get the accurate start position.
53 return accurate_index_pos - latched_encoder + known_index_pos_;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000054}
55
Austin Schuh703b8d42015-02-01 14:56:34 -080056void ZeroingEstimator::UpdateEstimate(const PotAndIndexPosition& info) {
Philipp Schrader41d82912015-02-15 03:44:23 +000057 // We want to make sure that we encounter at least one index pulse while
58 // zeroing. So we take the index pulse count from the first sample after
59 // reset and wait for that count to change before we consider ourselves
60 // zeroed.
61 if (wait_for_index_pulse_) {
Philipp Schradere828be72015-02-15 07:07:37 +000062 last_used_index_pulse_count_ = info.index_pulses;
Philipp Schrader41d82912015-02-15 03:44:23 +000063 wait_for_index_pulse_ = false;
64 }
65
Adam Snaiderc4b3c192015-02-01 01:30:39 +000066 if (start_pos_samples_.size() < max_sample_count_) {
67 start_pos_samples_.push_back(info.pot - info.encoder);
68 } else {
69 start_pos_samples_[samples_idx_] = info.pot - info.encoder;
70 }
Adam Snaiderb4119252015-02-15 01:30:57 +000071
72 // Drop the oldest sample when we run this function the next time around.
Adam Snaiderc4b3c192015-02-01 01:30:39 +000073 samples_idx_ = (samples_idx_ + 1) % max_sample_count_;
74
Adam Snaiderb4119252015-02-15 01:30:57 +000075 double sample_sum = 0.0;
76
Adam Snaiderc4b3c192015-02-01 01:30:39 +000077 for (size_t i = 0; i < start_pos_samples_.size(); ++i) {
Adam Snaiderb4119252015-02-15 01:30:57 +000078 sample_sum += start_pos_samples_[i];
Adam Snaiderc4b3c192015-02-01 01:30:39 +000079 }
80
81 // Calculates the average of the starting position.
Adam Snaiderb4119252015-02-15 01:30:57 +000082 double start_average = sample_sum / start_pos_samples_.size();
83
84 // If there are no index pulses to use or we don't have enough samples yet to
85 // have a well-filtered starting position then we use the filtered value as
86 // our best guess.
Philipp Schradere828be72015-02-15 07:07:37 +000087 if (!zeroed_ && (info.index_pulses == last_used_index_pulse_count_ ||
88 offset_ratio_ready() < 1.0)) {
Adam Snaiderb4119252015-02-15 01:30:57 +000089 start_pos_ = start_average;
Philipp Schradere828be72015-02-15 07:07:37 +000090 } else if (!zeroed_ || last_used_index_pulse_count_ != info.index_pulses) {
91 // Note the accurate start position and the current index pulse count so
92 // that we only run this logic once per index pulse. That should be more
93 // resilient to corrupted intermediate data.
94 start_pos_ = CalculateStartPosition(start_average, info.latched_encoder);
95 last_used_index_pulse_count_ = info.index_pulses;
Adam Snaiderb4119252015-02-15 01:30:57 +000096
97 // Now that we have an accurate starting position we can consider ourselves
98 // zeroed.
Austin Schuh703b8d42015-02-01 14:56:34 -080099 zeroed_ = true;
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000100 }
Adam Snaiderb4119252015-02-15 01:30:57 +0000101
102 pos_ = start_pos_ + info.encoder;
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000103}
104
Adam Snaiderc4b3c192015-02-01 01:30:39 +0000105} // namespace zeroing
106} // namespace frc971