blob: c0831e8b9f6912c2af3eb525232e2bb31ebf1af9 [file] [log] [blame]
Brian Silvermana57b7012020-03-11 20:19:23 -07001#include "frc971/zeroing/pulse_index.h"
2
3#include <cmath>
4#include <limits>
5
6#include "glog/logging.h"
7
8namespace frc971 {
9namespace zeroing {
10
11void PulseIndexZeroingEstimator::Reset() {
12 max_index_position_ = ::std::numeric_limits<double>::lowest();
13 min_index_position_ = ::std::numeric_limits<double>::max();
14 offset_ = 0;
15 last_used_index_pulse_count_ = 0;
16 zeroed_ = false;
17 error_ = false;
18}
19
20void PulseIndexZeroingEstimator::StoreIndexPulseMaxAndMin(
21 const IndexPosition &info) {
22 // If we have a new index pulse.
23 if (last_used_index_pulse_count_ != info.index_pulses()) {
24 // If the latest pulses's position is outside the range we've currently
25 // seen, record it appropriately.
26 if (info.latched_encoder() > max_index_position_) {
27 max_index_position_ = info.latched_encoder();
28 }
29 if (info.latched_encoder() < min_index_position_) {
30 min_index_position_ = info.latched_encoder();
31 }
32 last_used_index_pulse_count_ = info.index_pulses();
33 }
34}
35
36int PulseIndexZeroingEstimator::IndexPulseCount() const {
37 if (min_index_position_ > max_index_position_) {
38 // This condition means we haven't seen a pulse yet.
39 return 0;
40 }
41
42 // Calculate the number of pulses encountered so far.
43 return 1 + static_cast<int>(
44 ::std::round((max_index_position_ - min_index_position_) /
45 constants_.index_difference));
46}
47
48void PulseIndexZeroingEstimator::UpdateEstimate(const IndexPosition &info) {
49 StoreIndexPulseMaxAndMin(info);
50 const int index_pulse_count = IndexPulseCount();
51 if (index_pulse_count > constants_.index_pulse_count) {
52 if (!error_) {
53 VLOG(1) << "Got more index pulses than expected. Got "
54 << index_pulse_count << " expected "
55 << constants_.index_pulse_count;
56 error_ = true;
57 }
58 }
59
60 // TODO(austin): Detect if the encoder or index pulse is unplugged.
61 // TODO(austin): Detect missing counts.
62
63 if (index_pulse_count == constants_.index_pulse_count && !zeroed_) {
64 offset_ = constants_.measured_index_position -
65 constants_.known_index_pulse * constants_.index_difference -
66 min_index_position_;
67 zeroed_ = true;
68 } else if (zeroed_ && !error_) {
69 // Detect whether the index pulse is somewhere other than where we expect
70 // it to be. First we compute the position of the most recent index pulse.
71 double index_pulse_distance =
72 info.latched_encoder() + offset_ - constants_.measured_index_position;
73 // Second we compute the position of the index pulse in terms of
74 // the index difference. I.e. if this index pulse is two pulses away from
75 // the index pulse that we know about then this number should be positive
76 // or negative two.
77 double relative_distance =
78 index_pulse_distance / constants_.index_difference;
79 // Now we compute how far away the measured index pulse is from the
80 // expected index pulse.
81 double error = relative_distance - ::std::round(relative_distance);
82 // This lets us check if the index pulse is within an acceptable error
83 // margin of where we expected it to be.
84 if (::std::abs(error) > constants_.allowable_encoder_error) {
85 VLOG(1)
86 << "Encoder ticks out of range since last index pulse. known index "
87 "pulse: "
88 << constants_.measured_index_position << ", expected index pulse: "
89 << round(relative_distance) * constants_.index_difference +
90 constants_.measured_index_position
91 << ", actual index pulse: " << info.latched_encoder() + offset_
92 << ", "
93 "allowable error: "
94 << constants_.allowable_encoder_error * constants_.index_difference;
95 error_ = true;
96 }
97 }
98
99 position_ = info.encoder() + offset_;
100}
101
102flatbuffers::Offset<PulseIndexZeroingEstimator::State>
103PulseIndexZeroingEstimator::GetEstimatorState(
104 flatbuffers::FlatBufferBuilder *fbb) const {
105 State::Builder builder(*fbb);
106 builder.add_error(error_);
107 builder.add_zeroed(zeroed_);
108 builder.add_position(position_);
109 builder.add_min_index_position(min_index_position_);
110 builder.add_max_index_position(max_index_position_);
111 builder.add_index_pulses_seen(IndexPulseCount());
112 return builder.Finish();
113}
114
115} // namespace zeroing
116} // namespace frc971