blob: 92f28755e9cf80b8343551e8a77e28df55b0aadc [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
Austin Schuh703b8d42015-02-01 14:56:34 -08009ZeroingEstimator::ZeroingEstimator(
10 const constants::Values::ZeroingConstants& constants) {
Adam Snaiderb4119252015-02-15 01:30:57 +000011 index_diff_ = constants.index_difference;
12 max_sample_count_ = constants.average_filter_size;
Philipp Schrader030ad182015-02-15 05:40:58 +000013 known_index_pos_ = constants.measured_index_position;
Adam Snaiderb4119252015-02-15 01:30:57 +000014
15 start_pos_samples_.reserve(max_sample_count_);
16
17 Reset();
Austin Schuh703b8d42015-02-01 14:56:34 -080018}
19
Adam Snaiderb4119252015-02-15 01:30:57 +000020void ZeroingEstimator::Reset() {
Adam Snaiderc4b3c192015-02-01 01:30:39 +000021 samples_idx_ = 0;
Adam Snaiderb4119252015-02-15 01:30:57 +000022 start_pos_ = 0;
23 start_pos_samples_.clear();
24 zeroed_ = false;
Philipp Schrader41d82912015-02-15 03:44:23 +000025 wait_for_index_pulse_ = true;
Philipp Schradere828be72015-02-15 07:07:37 +000026 last_used_index_pulse_count_ = 0;
27}
28
29double ZeroingEstimator::CalculateStartPosition(double start_average,
30 double latched_encoder) const {
31 // We calculate an aproximation of the value of the last index position.
32 // Also account for index pulses not lining up with integer multiples of the
33 // index_diff.
34 double index_pos = start_average + latched_encoder - known_index_pos_;
35 // We round index_pos to the closest valid value of the index.
36 double accurate_index_pos = (round(index_pos / index_diff_)) * index_diff_;
37 // Now we reverse the first calculation to get the accurate start position.
38 return accurate_index_pos - latched_encoder + known_index_pos_;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000039}
40
Austin Schuh703b8d42015-02-01 14:56:34 -080041void ZeroingEstimator::UpdateEstimate(const PotAndIndexPosition& info) {
Philipp Schrader41d82912015-02-15 03:44:23 +000042 // We want to make sure that we encounter at least one index pulse while
43 // zeroing. So we take the index pulse count from the first sample after
44 // reset and wait for that count to change before we consider ourselves
45 // zeroed.
46 if (wait_for_index_pulse_) {
Philipp Schradere828be72015-02-15 07:07:37 +000047 last_used_index_pulse_count_ = info.index_pulses;
Philipp Schrader41d82912015-02-15 03:44:23 +000048 wait_for_index_pulse_ = false;
49 }
50
Adam Snaiderc4b3c192015-02-01 01:30:39 +000051 if (start_pos_samples_.size() < max_sample_count_) {
52 start_pos_samples_.push_back(info.pot - info.encoder);
53 } else {
54 start_pos_samples_[samples_idx_] = info.pot - info.encoder;
55 }
Adam Snaiderb4119252015-02-15 01:30:57 +000056
57 // Drop the oldest sample when we run this function the next time around.
Adam Snaiderc4b3c192015-02-01 01:30:39 +000058 samples_idx_ = (samples_idx_ + 1) % max_sample_count_;
59
Adam Snaiderb4119252015-02-15 01:30:57 +000060 double sample_sum = 0.0;
61
Adam Snaiderc4b3c192015-02-01 01:30:39 +000062 for (size_t i = 0; i < start_pos_samples_.size(); ++i) {
Adam Snaiderb4119252015-02-15 01:30:57 +000063 sample_sum += start_pos_samples_[i];
Adam Snaiderc4b3c192015-02-01 01:30:39 +000064 }
65
66 // Calculates the average of the starting position.
Adam Snaiderb4119252015-02-15 01:30:57 +000067 double start_average = sample_sum / start_pos_samples_.size();
68
69 // If there are no index pulses to use or we don't have enough samples yet to
70 // have a well-filtered starting position then we use the filtered value as
71 // our best guess.
Philipp Schradere828be72015-02-15 07:07:37 +000072 if (!zeroed_ && (info.index_pulses == last_used_index_pulse_count_ ||
73 offset_ratio_ready() < 1.0)) {
Adam Snaiderb4119252015-02-15 01:30:57 +000074 start_pos_ = start_average;
Philipp Schradere828be72015-02-15 07:07:37 +000075 } else if (!zeroed_ || last_used_index_pulse_count_ != info.index_pulses) {
76 // Note the accurate start position and the current index pulse count so
77 // that we only run this logic once per index pulse. That should be more
78 // resilient to corrupted intermediate data.
79 start_pos_ = CalculateStartPosition(start_average, info.latched_encoder);
80 last_used_index_pulse_count_ = info.index_pulses;
Adam Snaiderb4119252015-02-15 01:30:57 +000081
82 // Now that we have an accurate starting position we can consider ourselves
83 // zeroed.
Austin Schuh703b8d42015-02-01 14:56:34 -080084 zeroed_ = true;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000085 }
Adam Snaiderb4119252015-02-15 01:30:57 +000086
87 pos_ = start_pos_ + info.encoder;
Adam Snaiderc4b3c192015-02-01 01:30:39 +000088}
89
Adam Snaiderc4b3c192015-02-01 01:30:39 +000090} // namespace zeroing
91} // namespace frc971