blob: 99454e48ce6249041e4a88bd3ec614dd04cca8f7 [file] [log] [blame]
Brian Silvermana57b7012020-03-11 20:19:23 -07001#include "frc971/zeroing/hall_effect_and_position.h"
2
3#include <algorithm>
4#include <cmath>
5#include <limits>
6
7#include "glog/logging.h"
8
Stephan Pleinesf63bde82024-01-13 15:59:33 -08009namespace frc971::zeroing {
Brian Silvermana57b7012020-03-11 20:19:23 -070010
11HallEffectAndPositionZeroingEstimator::HallEffectAndPositionZeroingEstimator(
12 const ZeroingConstants &constants)
13 : constants_(constants) {
14 Reset();
15}
16
17void HallEffectAndPositionZeroingEstimator::Reset() {
18 offset_ = 0.0;
19 min_low_position_ = ::std::numeric_limits<double>::max();
20 max_low_position_ = ::std::numeric_limits<double>::lowest();
21 zeroed_ = false;
22 initialized_ = false;
23 last_used_posedge_count_ = 0;
24 cycles_high_ = 0;
25 high_long_enough_ = false;
26 first_start_pos_ = 0.0;
27 error_ = false;
28 current_ = 0.0;
29 first_start_pos_ = 0.0;
30}
31
32void HallEffectAndPositionZeroingEstimator::TriggerError() {
33 if (!error_) {
34 VLOG(1) << "Manually triggered zeroing error.\n";
35 error_ = true;
36 }
37}
38
39void HallEffectAndPositionZeroingEstimator::StoreEncoderMaxAndMin(
40 const HallEffectAndPosition &info) {
41 // If we have a new posedge.
42 if (!info.current()) {
43 if (last_hall_) {
44 min_low_position_ = max_low_position_ = info.encoder();
45 } else {
46 min_low_position_ = ::std::min(min_low_position_, info.encoder());
47 max_low_position_ = ::std::max(max_low_position_, info.encoder());
48 }
49 }
50 last_hall_ = info.current();
51}
52
53void HallEffectAndPositionZeroingEstimator::UpdateEstimate(
54 const HallEffectAndPosition &info) {
55 // We want to make sure that we encounter at least one posedge while zeroing.
56 // So we take the posedge count from the first sample after reset and wait for
57 // that count to change and for the hall effect to stay high before we
58 // consider ourselves zeroed.
59 if (!initialized_) {
60 last_used_posedge_count_ = info.posedge_count();
61 initialized_ = true;
62 last_hall_ = info.current();
63 }
64
65 StoreEncoderMaxAndMin(info);
66
67 if (info.current()) {
68 cycles_high_++;
69 } else {
70 cycles_high_ = 0;
71 last_used_posedge_count_ = info.posedge_count();
72 }
73
74 high_long_enough_ = cycles_high_ >= constants_.hall_trigger_zeroing_length;
75
76 bool moving_backward = false;
77 if (constants_.zeroing_move_direction) {
78 moving_backward = info.encoder() > min_low_position_;
79 } else {
80 moving_backward = info.encoder() < max_low_position_;
81 }
82
83 // If there are no posedges to use or we don't have enough samples yet to
84 // have a well-filtered starting position then we use the filtered value as
85 // our best guess.
86 if (last_used_posedge_count_ != info.posedge_count() && high_long_enough_ &&
87 moving_backward) {
88 // Note the offset and the current posedge count so that we only run this
89 // logic once per posedge. That should be more resilient to corrupted
90 // intermediate data.
91 offset_ = -info.posedge_value();
92 if (constants_.zeroing_move_direction) {
93 offset_ += constants_.lower_hall_position;
94 } else {
95 offset_ += constants_.upper_hall_position;
96 }
97 last_used_posedge_count_ = info.posedge_count();
98
99 // Save the first starting position.
100 if (!zeroed_) {
101 first_start_pos_ = offset_;
102 VLOG(2) << "latching start position" << first_start_pos_;
103 }
104
105 // Now that we have an accurate starting position we can consider ourselves
106 // zeroed.
107 zeroed_ = true;
108 }
109
110 position_ = info.encoder() - offset_;
111}
112
113flatbuffers::Offset<HallEffectAndPositionZeroingEstimator::State>
114HallEffectAndPositionZeroingEstimator::GetEstimatorState(
115 flatbuffers::FlatBufferBuilder *fbb) const {
116 State::Builder builder(*fbb);
117 builder.add_error(error_);
118 builder.add_zeroed(zeroed_);
119 builder.add_encoder(position_);
120 builder.add_high_long_enough(high_long_enough_);
121 builder.add_offset(offset_);
122 return builder.Finish();
123}
124
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800125} // namespace frc971::zeroing