blob: 72a557e61ab98181a84c158b183c5d3724776bd2 [file] [log] [blame]
Sabina Davisadc58542019-02-01 22:23:00 -08001#ifndef FRC971_WPILIB_SENSOR_READER_H_
2#define FRC971_WPILIB_SENSOR_READER_H_
3
4#include <atomic>
5#include <chrono>
6
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "aos/events/event_loop.h"
Austin Schuh217a9782019-12-21 23:02:50 -08008#include "aos/events/shm_event_loop.h"
Sabina Davisadc58542019-02-01 22:23:00 -08009#include "aos/stl_mutex/stl_mutex.h"
10#include "aos/time/time.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "frc971/control_loops/control_loops_generated.h"
Maxwell Hendersond5ae85b2024-01-08 16:14:28 -080012#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
James Kuszmaul7077d342021-06-09 20:23:58 -070013#include "frc971/input/robot_state_generated.h"
Sabina Davisadc58542019-02-01 22:23:00 -080014#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
15#include "frc971/wpilib/ahal/DigitalInput.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080016#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080017#include "frc971/wpilib/dma.h"
18#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080019#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080020
21using ::aos::monotonic_clock;
22namespace chrono = ::std::chrono;
23
24namespace frc971 {
25namespace wpilib {
26
27class SensorReader {
28 public:
Austin Schuh217a9782019-12-21 23:02:50 -080029 SensorReader(::aos::ShmEventLoop *event_loop);
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080030 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080031
Austin Schuh45a549f2019-02-02 15:43:56 -080032 // Updates the fast and medium encoder filter frequencies.
33 void UpdateFastEncoderFilterHz(int hz);
34 void UpdateMediumEncoderFilterHz(int hz);
35
Sabina Davisb6317b72019-02-01 22:53:23 -080036 // Sets the left drivetrain encoder.
37 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
38
39 // Sets the right drivetrain encoder.
40 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
41
Sabina Davis6292bec2019-02-06 22:53:14 -080042 // Adds a sensor to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080043 void AddToDMA(DMASampleHandlerInterface *handler) {
Sabina Davis6292bec2019-02-06 22:53:14 -080044 if (!dma_synchronizer_) {
45 dma_synchronizer_.reset(
46 new ::frc971::wpilib::DMASynchronizer(std::make_unique<DMA>()));
47 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080048 dma_synchronizer_->Add(handler);
49 }
50
Austin Schuh3b010bc2019-02-24 17:25:37 -080051 // Sets PWM trigger mode. If true, synchronize the control loops with the PWM
52 // pulses. The sensors are sampled 50 uS after the falling edge of the PWM
53 // pulse.
54 void set_pwm_trigger(bool trigger) { pwm_trigger_ = trigger; }
Sabina Davisadc58542019-02-01 22:23:00 -080055
Sabina Davisa42cc352019-02-01 22:55:50 -080056 // Stops the pwm trigger on the next iteration.
57 void Quit() { run_ = false; }
58
Sabina Davis399dbd82019-02-01 23:06:08 -080059 virtual void RunIteration() = 0;
Sabina Davis6292bec2019-02-06 22:53:14 -080060 // Runs the DMA iteration after the synchronizer. This only gets run if a
61 // sensor has been added to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080062 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080063
Sabina Davisadc58542019-02-01 22:23:00 -080064 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080065 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
66 // changes.
67 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -070068 ::frc971::IndexPositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -080069 double encoder_counts_per_revolution, double encoder_ratio,
70 bool reverse) {
71 const double multiplier = reverse ? -1.0 : 1.0;
72 position->encoder =
73 multiplier * encoder_translate(encoder.polled_encoder_value(),
74 encoder_counts_per_revolution,
75 encoder_ratio);
76 position->latched_encoder =
77 multiplier * encoder_translate(encoder.last_encoder_value(),
78 encoder_counts_per_revolution,
79 encoder_ratio);
80 position->index_pulses = encoder.index_posedge_count();
81 }
82
83 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
84 // the correct unit and direction changes.
85 void CopyPosition(
86 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
Alex Perrycb7da4b2019-08-28 19:35:56 -070087 ::frc971::PotAndAbsolutePositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -080088 double encoder_counts_per_revolution, double encoder_ratio,
89 ::std::function<double(double)> potentiometer_translate, bool reverse,
90 double pot_offset) {
91 const double multiplier = reverse ? -1.0 : 1.0;
92 position->pot = multiplier * potentiometer_translate(
93 encoder.ReadPotentiometerVoltage()) +
94 pot_offset;
95 position->encoder =
96 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
97 encoder_counts_per_revolution,
98 encoder_ratio);
99
100 position->absolute_encoder =
101 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
102 : encoder.ReadAbsoluteEncoder()) *
103 encoder_ratio * (2.0 * M_PI);
104 }
105
Ravago Jones937587c2020-12-26 17:21:09 -0800106 // Copies an AbsoluteEncoderAndPotentiometer to an AbsoluteAndAbsolutePosition
107 // with the correct unit and direction changes.
108 void CopyPosition(const ::frc971::wpilib::AbsoluteAndAbsoluteEncoder &encoder,
109 ::frc971::AbsoluteAndAbsolutePositionT *position,
110 double encoder_counts_per_revolution, double encoder_ratio,
111 double single_turn_encoder_ratio, bool reverse) {
112 const double multiplier = reverse ? -1.0 : 1.0;
113 position->encoder =
114 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
115 encoder_counts_per_revolution,
116 encoder_ratio);
117
118 position->absolute_encoder =
119 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
120 : encoder.ReadAbsoluteEncoder()) *
121 encoder_ratio * (2.0 * M_PI);
122
123 position->single_turn_absolute_encoder =
124 (reverse ? (1.0 - encoder.ReadSingleTurnAbsoluteEncoder())
125 : encoder.ReadSingleTurnAbsoluteEncoder()) *
126 single_turn_encoder_ratio * (2.0 * M_PI);
127 }
128
Austin Schuh54667ac2019-02-02 16:44:49 -0800129 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
130 // and direction changes.
131 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
Alex Perrycb7da4b2019-08-28 19:35:56 -0700132 ::frc971::HallEffectAndPositionT *position,
Austin Schuh54667ac2019-02-02 16:44:49 -0800133 double encoder_counts_per_revolution, double encoder_ratio,
134 bool reverse) {
135 const double multiplier = reverse ? -1.0 : 1.0;
136 position->encoder =
137 multiplier * encoder_translate(counter.polled_encoder(),
138 encoder_counts_per_revolution,
139 encoder_ratio);
140 position->current = !counter.polled_value();
141 position->posedge_count = counter.negative_count();
142 position->negedge_count = counter.positive_count();
143 position->posedge_value =
144 multiplier * encoder_translate(counter.last_negative_encoder_value(),
145 encoder_counts_per_revolution,
146 encoder_ratio);
147 position->negedge_value =
148 multiplier * encoder_translate(counter.last_positive_encoder_value(),
149 encoder_counts_per_revolution,
150 encoder_ratio);
151 }
152
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800153 // Copies a Absolute Encoder with the correct unit
154 // and direction changes.
Ravago Jones937587c2020-12-26 17:21:09 -0800155 void CopyPosition(const ::frc971::wpilib::AbsoluteEncoder &encoder,
156 ::frc971::AbsolutePositionT *position,
157 double encoder_counts_per_revolution, double encoder_ratio,
158 bool reverse) {
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800159 const double multiplier = reverse ? -1.0 : 1.0;
160 position->encoder =
161 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
162 encoder_counts_per_revolution,
163 encoder_ratio);
164
165 position->absolute_encoder =
166 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
167 : encoder.ReadAbsoluteEncoder()) *
168 encoder_ratio * (2.0 * M_PI);
169 }
170
Ravago Jones937587c2020-12-26 17:21:09 -0800171 void CopyPosition(const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
172 ::frc971::PotAndIndexPositionT *position,
173 ::std::function<double(int32_t)> encoder_translate,
174 ::std::function<double(double)> potentiometer_translate,
175 bool reverse, double pot_offset) {
Sabina Davis2243cab2019-02-05 21:45:08 -0800176 const double multiplier = reverse ? -1.0 : 1.0;
177 position->encoder =
178 multiplier * encoder_translate(encoder.polled_encoder_value());
179 position->pot = multiplier * potentiometer_translate(
180 encoder.polled_potentiometer_voltage()) +
181 pot_offset;
182 position->latched_encoder =
183 multiplier * encoder_translate(encoder.last_encoder_value());
184 position->latched_pot =
185 multiplier *
186 potentiometer_translate(encoder.last_potentiometer_voltage()) +
187 pot_offset;
188 position->index_pulses = encoder.index_posedge_count();
189 }
190
Siddhant Kanwar0e37f592022-02-21 19:26:50 -0800191 // Copies a relative digital encoder.
Alex Perry2712c102020-02-17 19:17:11 -0800192 void CopyPosition(const ::frc::Encoder &encoder,
193 ::frc971::RelativePositionT *position,
194 double encoder_counts_per_revolution, double encoder_ratio,
195 bool reverse) {
196 const double multiplier = reverse ? -1.0 : 1.0;
197 position->encoder =
198 multiplier * encoder_translate(encoder.GetRaw(),
199 encoder_counts_per_revolution,
200 encoder_ratio);
201 }
202
Siddhant Kanwar0e37f592022-02-21 19:26:50 -0800203 // Copies a potentiometer
204 void CopyPosition(const ::frc::AnalogInput &input,
205 ::frc971::RelativePositionT *position,
206 ::std::function<double(double)> potentiometer_translate,
207 bool reverse, double pot_offset) {
208 const double multiplier = reverse ? -1.0 : 1.0;
209 position->encoder =
210 multiplier * potentiometer_translate(input.GetVoltage()) + pot_offset;
211 }
212
Austin Schuh54667ac2019-02-02 16:44:49 -0800213 double encoder_translate(int32_t value, double counts_per_revolution,
214 double ratio) {
215 return static_cast<double>(value) / counts_per_revolution * ratio *
216 (2.0 * M_PI);
217 }
218
Maxwell Hendersond5ae85b2024-01-08 16:14:28 -0800219 void SendDrivetrainPosition(
220 aos::Sender<control_loops::drivetrain::Position>
221 drivetrain_position_sender,
222 std::function<double(double input)> velocity_translate,
223 std::function<double(double input)> encoder_to_meters, bool left_inverted,
224 bool right_inverted);
225
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800226 ::aos::EventLoop *event_loop_;
227 ::aos::Sender<::aos::RobotState> robot_state_sender_;
228
Austin Schuh45a549f2019-02-02 15:43:56 -0800229 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
230
231 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
232 drivetrain_right_encoder_;
233
234 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800235 // Gets called right before the DMA synchronizer is up and running.
236 virtual void Start() {}
237
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700238 // Sets up everything during startup.
239 void DoStart();
240
241 // Runs a single iteration.
milind-u61227f22021-08-29 15:58:33 -0700242 void Loop();
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700243
Austin Schuh3b010bc2019-02-24 17:25:37 -0800244 // Returns the monotonic time of the start of the first PWM cycle.
245 // Returns min_time if no start time could be calculated.
246 monotonic_clock::time_point GetPWMStartTime();
Sabina Davisadc58542019-02-01 22:23:00 -0800247
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700248 bool pwm_trigger_ = false;
Sabina Davisadc58542019-02-01 22:23:00 -0800249
Sabina Davis1ffa4172019-02-01 22:38:33 -0800250 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
251
Sabina Davisadc58542019-02-01 22:23:00 -0800252 ::std::atomic<bool> run_{true};
Austin Schuh3b010bc2019-02-24 17:25:37 -0800253 ::frc::DriverStation *ds_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700254
255 const int32_t my_pid_;
256
milind-u61227f22021-08-29 15:58:33 -0700257 // Pointer to the timer handler used to modify the wakeup.
258 ::aos::TimerHandler *timer_handler_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700259
260 // Last time we got called.
261 ::aos::monotonic_clock::time_point last_monotonic_now_ =
262 ::aos::monotonic_clock::min_time;
263 // The current period.
264 chrono::microseconds period_ = chrono::microseconds(5000);
Sabina Davisadc58542019-02-01 22:23:00 -0800265};
266
267} // namespace wpilib
268} // namespace frc971
269
270#endif // FRC971_WPILIB_SENSOR_READER_H_