blob: 29c4273a57b8a33e31c22ed70a8e5c08ba4c9744 [file] [log] [blame]
James Kuszmaulb5e497c2013-03-02 15:14:13 -08001#ifndef FRC971_CONTROL_LOOPS_HALL_EFFECT_INL_H_
2#define FRC971_CONTROL_LOOPS_HALL_EFFECT_INL_H_
3
4#include "frc971/control_loops/hall_effect_loop.h"
5
6#include "aos/aos_core.h"
7
8#include "aos/common/messages/RobotState.q.h"
9#include "aos/common/logging/logging.h"
10
11namespace frc971 {
12namespace control_loops {
13
14template <int kNumHallEffect>
15HallEffectLoop<kNumHallEffect>::HallEffectLoop(
16 StateFeedbackLoop<2, 1, 1>* state_feedback_loop,
17 bool zero_down, double max_zeroing_voltage)
18 : kMaxZeroingVoltage(max_zeroing_voltage),
19 zero_down_(zero_down),
20 state_(UNINITIALIZED),
21 loop_(state_feedback_loop),
22 current_position_(0.0),
23 last_off_position_(0.0),
24 last_calibration_sensor_(-1),
25 zeroing_position_(0.0),
26 zero_offset_(0.0),
27 old_zero_offset_(0.0) {
28}
29
30template <int kNumHallEffect>
31int HallEffectLoop<kNumHallEffect>::HallEffect() const {
32 for (int i = 0; i < kNumHallEffect; ++i) {
33 if (hall_effect_[i]) {
34 return i;
35 }
36 }
37 return -1;
38}
39
40template <int kNumHallEffect>
41int HallEffectLoop<kNumHallEffect>::WhichHallEffect() const {
42 if (zero_down_) {
43 for (int i = 0; i < kNumHallEffect; ++i) {
44 if (calibration_[i] + hall_effect_angle_[i] < last_off_position_ &&
45 calibration_[i] + hall_effect_angle_[i] >= current_position_) {
46 return i;
47 }
48 }
49 } else {
50 for (int i = 0; i < kNumHallEffect; ++i) {
51 if (calibration_[i] + hall_effect_angle_[i] > last_off_position_ &&
52 calibration_[i] + hall_effect_angle_[i] <= current_position_) {
53 return i;
54 }
55 }
56 }
57 return -1;
58}
59
60template <int kNumHallEffect>
61void HallEffectLoop<kNumHallEffect>::LimitZeroingGoal() {
James Kuszmaul16bcb5f2013-03-03 14:50:07 -080062 if (state_ == MOVING_OFF || state_ == ZEROING) {
63 if (loop_->U_uncapped(0, 0) > kMaxZeroingVoltage) {
64 double excess = (loop_->U_uncapped(0, 0) - kMaxZeroingVoltage)
65 / loop_->K(0, 0);
66 zeroing_position_ -= excess;
67 }
68 if (loop_->U_uncapped(0, 0) < -kMaxZeroingVoltage) {
69 double excess = (loop_->U_uncapped(0, 0) + kMaxZeroingVoltage)
70 / loop_->K(0, 0);
71 zeroing_position_ -= excess;
72 }
James Kuszmaulb5e497c2013-03-02 15:14:13 -080073 }
74}
75
76template <int kNumHallEffect>
77void HallEffectLoop<kNumHallEffect>::UpdateZeros(
78 ::std::array<double, kNumHallEffect> hall_effect_angle,
79 ::std::array<bool, kNumHallEffect> hall_effect,
80 ::std::array<double, kNumHallEffect> calibration,
81 double zeroing_speed,
82 double position, bool good_position) {
83 hall_effect_angle_ = hall_effect_angle;
84 hall_effect_ = hall_effect;
85 calibration_ = calibration;
86 zeroing_speed_ = zeroing_speed;
87 current_position_ = position;
88
89 if (!zero_down_) {
90 zeroing_speed_ *= -1;
91 }
92
93 // Deal with getting all the position variables updated.
94 absolute_position_ = current_position_;
95 if (good_position) {
96 if (state_ == READY) {
97 absolute_position_ -= zero_offset_;
98 }
99 loop_->Y << absolute_position_;
100 if (HallEffect() == -1) {
101 last_off_position_ = current_position_;
102 }
103 } else {
104 absolute_position_ = loop_->X_hat(0, 0);
105 }
106
107 // switch for dealing with various zeroing states.
108 switch (state_) {
109 case UNINITIALIZED:
110 LOG(DEBUG, "status_: UNINITIALIZED\n");
111 last_calibration_sensor_ = -1;
112 if (good_position) {
113 // Reset the zeroing goal.
114 zeroing_position_ = absolute_position_;
115 // Clear the observer state.
116 loop_->X_hat << absolute_position_, 0.0;
117 // Only progress if we are enabled.
118 if (::aos::robot_state->enabled) {
119 if (HallEffect() != -1) {
120 state_ = MOVING_OFF;
121 } else {
122 state_ = ZEROING;
123 }
124 } else {
125 loop_->R << absolute_position_, 0.0;
126 }
127 }
128 break;
129 case MOVING_OFF:
130 LOG(DEBUG, "status_: MOVING_OFF\n");
131 // Move off the hall effect sensor.
132 if (!::aos::robot_state->enabled) {
133 // Start over if disabled.
134 state_ = UNINITIALIZED;
135 } else if (good_position && (HallEffect() == -1)) {
136 // We are now off the sensor. Time to zero now.
137 state_ = ZEROING;
138 } else {
139 // Slowly creep off the sensor.
140 zeroing_position_ += zeroing_speed_ * dt;
141 loop_->R << zeroing_position_, zeroing_speed_;
142 break;
143 }
144 case ZEROING:
145 LOG(DEBUG, "status_: ZEROING\n");
146 if (!::aos::robot_state->enabled) {
147 // Start over if disabled.
148 state_ = UNINITIALIZED;
149 } else if (good_position && (HallEffect() != -1)) {
150 state_ = READY;
151 // Verify that the calibration number is between the last off position
152 // and the current on position. If this is not true, move off and try
153 // again.
154 if (WhichHallEffect() == -1) {
155 LOG(ERROR, "Got a bogus calibration number. Trying again.\n");
156 LOG(ERROR,
157 "Last off position was %f, current is %f,\n",
158 last_off_position_, current_position_);
159 state_ = MOVING_OFF;
160 } else {
161 // Save the zero, and then offset the observer to deal with the
162 // phantom step change.
163 const double old_zero_offset = zero_offset_;
164 zero_offset_ = calibration_[WhichHallEffect()];
165 loop_->X_hat(0, 0) += old_zero_offset - zero_offset_;
166 loop_->Y(0, 0) += old_zero_offset - zero_offset_;
167 last_calibration_sensor_ = WhichHallEffect();
168 }
169 } else {
170 // Slowly creep towards the sensor.
171 zeroing_position_ -= zeroing_speed_ * dt;
172 loop_->R << zeroing_position_, -zeroing_speed_;
173 }
174 break;
175
176 case READY:
177 {
178 LOG(DEBUG, "status_: READY\n");
179 break;
180 }
181
182 case ESTOP:
183 LOG(WARNING, "have already given up\n");
184 return;
185 }
186
James Kuszmaulb5e497c2013-03-02 15:14:13 -0800187 if (good_position) {
188 LOG(DEBUG,
189 "calibration sensor: %d zero_offset: %f absolute_position: %f\n",
190 last_calibration_sensor_, zero_offset_, absolute_position_);
191 }
192
193} // UpdateZeros
194
195} // namespace control_loops
196} // namespace frc971
197
198#endif // FRC971_CONTROL_LOOPS_HALL_EFFECT_INL_H_