1use crate::{
4 bindings,
5 error::{get_errno, Error},
6 rtos::DataSource,
7};
8
9pub struct Motor {
11 port: u8,
12}
13
14impl Motor {
15 pub unsafe fn new(
23 port: u8,
24 gearset: Gearset,
25 encoder_units: EncoderUnits,
26 reverse: bool,
27 ) -> Result<Self, MotorError> {
28 let mut motor = Self { port };
29 motor.set_reversed(reverse)?;
30 motor.set_gearing(gearset)?;
31 match unsafe { bindings::motor_set_encoder_units(port, encoder_units.into()) } {
32 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
33 _ => Ok(motor),
34 }
35 }
36
37 pub fn move_i8(&mut self, voltage: i8) -> Result<(), MotorError> {
43 match unsafe { bindings::motor_move(self.port, voltage as i32) } {
44 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
45 _ => Ok(()),
46 }
47 }
48
49 pub fn move_absolute(&mut self, position: f64, velocity: i32) -> Result<(), MotorError> {
58 match unsafe { bindings::motor_move_absolute(self.port, position, velocity) } {
59 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
60 _ => Ok(()),
61 }
62 }
63
64 pub fn move_relative(&mut self, position: f64, velocity: i32) -> Result<(), MotorError> {
74 match unsafe { bindings::motor_move_relative(self.port, position, velocity) } {
75 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
76 _ => Ok(()),
77 }
78 }
79
80 pub fn move_velocity(&mut self, velocity: i32) -> Result<(), MotorError> {
88 match unsafe { bindings::motor_move_velocity(self.port, velocity) } {
89 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
90 _ => Ok(()),
91 }
92 }
93
94 pub fn move_voltage(&mut self, voltage: i32) -> Result<(), MotorError> {
97 match unsafe { bindings::motor_move_voltage(self.port, voltage) } {
98 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
99 _ => Ok(()),
100 }
101 }
102
103 pub fn modify_profiled_velocity(&mut self, velocity: i32) -> Result<(), MotorError> {
107 match unsafe { bindings::motor_modify_profiled_velocity(self.port, velocity) } {
108 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
109 _ => Ok(()),
110 }
111 }
112
113 pub fn get_target_position(&self) -> Result<f64, MotorError> {
115 match unsafe { bindings::motor_get_target_position(self.port) } {
116 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
117 x => Ok(x),
118 }
119 }
120
121 pub fn get_target_velocity(&self) -> Result<i32, MotorError> {
123 match unsafe { bindings::motor_get_target_velocity(self.port) } {
124 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
125 x => Ok(x),
126 }
127 }
128
129 pub fn get_actual_velocity(&self) -> Result<f64, MotorError> {
131 match unsafe { bindings::motor_get_actual_velocity(self.port) } {
132 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
133 x => Ok(x),
134 }
135 }
136
137 pub fn get_current_draw(&self) -> Result<i32, MotorError> {
139 match unsafe { bindings::motor_get_current_draw(self.port) } {
140 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
141 x => Ok(x),
142 }
143 }
144
145 pub fn get_direction(&self) -> Result<Direction, MotorError> {
147 match unsafe { bindings::motor_get_direction(self.port) } {
148 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
149 1 => Ok(Direction::Positive),
150 -1 => Ok(Direction::Negative),
151 x => panic!(
152 "bindings::motor_get_direction returned unexpected value: {}",
153 x
154 ),
155 }
156 }
157
158 pub fn get_efficiency(&self) -> Result<f64, MotorError> {
160 match unsafe { bindings::motor_get_efficiency(self.port) } {
161 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
162 x => Ok(x),
163 }
164 }
165
166 pub fn get_position(&self) -> Result<f64, MotorError> {
168 match unsafe { bindings::motor_get_position(self.port) } {
169 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
170 x => Ok(x),
171 }
172 }
173
174 pub fn get_power(&self) -> Result<f64, MotorError> {
176 match unsafe { bindings::motor_get_power(self.port) } {
177 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
178 x => Ok(x),
179 }
180 }
181
182 pub fn get_temperature(&self) -> Result<f64, MotorError> {
184 match unsafe { bindings::motor_get_temperature(self.port) } {
185 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
186 x => Ok(x),
187 }
188 }
189
190 pub fn get_torque(&self) -> Result<f64, MotorError> {
192 match unsafe { bindings::motor_get_torque(self.port) } {
193 x if x == bindings::PROS_ERR_F_ => Err(MotorError::from_errno()),
194 x => Ok(x),
195 }
196 }
197
198 pub fn get_voltage(&self) -> Result<i32, MotorError> {
200 match unsafe { bindings::motor_get_voltage(self.port) } {
201 x if x == bindings::PROS_ERR_ => Err(MotorError::from_errno()),
202 x => Ok(x),
203 }
204 }
205
206 pub fn is_over_current(&self) -> Result<bool, MotorError> {
208 match unsafe { bindings::motor_is_over_current(self.port) } {
209 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
210 0 => Ok(false),
211 _ => Ok(true),
212 }
213 }
214
215 pub fn is_over_temp(&self) -> Result<bool, MotorError> {
217 match unsafe { bindings::motor_is_over_temp(self.port) } {
218 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
219 0 => Ok(false),
220 _ => Ok(true),
221 }
222 }
223
224 pub fn get_brake_mode(&self) -> Result<BrakeMode, MotorError> {
226 match unsafe { bindings::motor_get_brake_mode(self.port) } {
227 bindings::motor_brake_mode_e_E_MOTOR_BRAKE_BRAKE => Ok(BrakeMode::Brake),
228 bindings::motor_brake_mode_e_E_MOTOR_BRAKE_COAST => Ok(BrakeMode::Coast),
229 bindings::motor_brake_mode_e_E_MOTOR_BRAKE_HOLD => Ok(BrakeMode::Hold),
230 bindings::motor_brake_mode_e_E_MOTOR_BRAKE_INVALID => Err(MotorError::from_errno()),
231 x => panic!(
232 "bindings::motor_get_brake_mode returned unexpected value: {}.",
233 x
234 ),
235 }
236 }
237
238 pub fn get_current_limit(&self) -> Result<i32, MotorError> {
243 match unsafe { bindings::motor_get_current_limit(self.port) } {
244 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
245 x => Ok(x),
246 }
247 }
248
249 pub fn get_gearing(&self) -> Result<Gearset, MotorError> {
251 match unsafe { bindings::motor_get_gearing(self.port) } {
252 bindings::motor_gearset_e_E_MOTOR_GEARSET_36 => Ok(Gearset::SixToOne),
253 bindings::motor_gearset_e_E_MOTOR_GEARSET_18 => Ok(Gearset::EighteenToOne),
254 bindings::motor_gearset_e_E_MOTOR_GEARSET_06 => Ok(Gearset::ThirtySixToOne),
255 bindings::motor_gearset_e_E_MOTOR_GEARSET_INVALID => Err(MotorError::from_errno()),
256 x => panic!(
257 "bindings::motor_get_gearing returned unexpected value: {}.",
258 x
259 ),
260 }
261 }
262
263 pub fn get_voltage_limit(&self) -> Result<i32, MotorError> {
268 match unsafe { bindings::motor_get_voltage_limit(self.port) } {
269 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
270 x => Ok(x),
271 }
272 }
273
274 pub fn is_reversed(&self) -> Result<bool, MotorError> {
278 match unsafe { bindings::motor_is_reversed(self.port) } {
279 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
280 0 => Ok(false),
281 _ => Ok(true),
282 }
283 }
284
285 pub fn set_brake_mode(&mut self, mode: BrakeMode) -> Result<(), MotorError> {
287 match unsafe { bindings::motor_set_brake_mode(self.port, mode.into()) } {
288 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
289 _ => Ok(()),
290 }
291 }
292
293 pub fn set_current_limit(&mut self, limit: i32) -> Result<(), MotorError> {
295 match unsafe { bindings::motor_set_current_limit(self.port, limit) } {
296 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
297 _ => Ok(()),
298 }
299 }
300
301 pub fn set_gearing(&mut self, gearset: Gearset) -> Result<(), MotorError> {
303 match unsafe { bindings::motor_set_gearing(self.port, gearset.into()) } {
304 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
305 _ => Ok(()),
306 }
307 }
308
309 pub fn set_reversed(&mut self, reverse: bool) -> Result<(), MotorError> {
313 match unsafe { bindings::motor_set_reversed(self.port, reverse) } {
314 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
315 _ => Ok(()),
316 }
317 }
318
319 pub fn set_voltage_limit(&mut self, limit: i32) -> Result<(), MotorError> {
321 match unsafe { bindings::motor_set_voltage_limit(self.port, limit) } {
322 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
323 _ => Ok(()),
324 }
325 }
326
327 pub fn set_zero_position(&mut self, position: f64) -> Result<(), MotorError> {
329 match unsafe { bindings::motor_set_zero_position(self.port, position) } {
330 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
331 _ => Ok(()),
332 }
333 }
334
335 pub fn tare_position(&mut self) -> Result<(), MotorError> {
337 match unsafe { bindings::motor_tare_position(self.port) } {
338 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
339 _ => Ok(()),
340 }
341 }
342
343 pub fn set_encoder_units(&mut self, units: EncoderUnits) -> Result<(), MotorError> {
345 match unsafe { bindings::motor_set_encoder_units(self.port, units.into()) } {
346 bindings::PROS_ERR_ => Err(MotorError::from_errno()),
347 _ => Ok(()),
348 }
349 }
350
351 pub fn get_encoder_units(&self) -> Result<EncoderUnits, MotorError> {
353 match unsafe { bindings::motor_get_encoder_units(self.port) } {
354 bindings::motor_encoder_units_e_E_MOTOR_ENCODER_COUNTS => {
355 Ok(EncoderUnits::EncoderTicks)
356 }
357 bindings::motor_encoder_units_e_E_MOTOR_ENCODER_DEGREES => Ok(EncoderUnits::Degrees),
358 bindings::motor_encoder_units_e_E_MOTOR_ENCODER_ROTATIONS => {
359 Ok(EncoderUnits::Rotations)
360 }
361 bindings::motor_encoder_units_e_E_MOTOR_ENCODER_INVALID => {
362 Err(MotorError::from_errno())
363 }
364 x => panic!("bindings:get_encoder_units returned unexpected value {}", x),
365 }
366 }
367}
368
369impl DataSource for Motor {
370 type Data = MotorData;
371
372 type Error = MotorError;
373
374 fn read(&self) -> Result<Self::Data, Self::Error> {
375 Ok(MotorData {
376 target_position: self.get_target_position()?,
377 target_velocity: self.get_target_velocity()?,
378 actual_velocity: self.get_actual_velocity()?,
379 current_draw: self.get_current_draw()?,
380 direction: self.get_direction()?,
381 efficiency: self.get_efficiency()?,
382 position: self.get_position()?,
383 power: self.get_power()?,
384 temperature: self.get_temperature()?,
385 torque: self.get_torque()?,
386 voltage: self.get_voltage()?,
387 over_current: self.is_over_current()?,
388 over_temp: self.is_over_temp()?,
389 brake_mode: self.get_brake_mode()?,
390 current_limit: self.get_current_limit()?,
391 voltage_limit: self.get_voltage_limit()?,
392 })
393 }
394}
395
396#[derive(Clone, Copy, Debug, PartialEq)]
398pub struct MotorData {
399 pub target_position: f64,
401 pub target_velocity: i32,
403 pub actual_velocity: f64,
405 pub current_draw: i32,
407 pub direction: Direction,
409 pub efficiency: f64,
411 pub position: f64,
413 pub power: f64,
415 pub temperature: f64,
417 pub torque: f64,
419 pub voltage: i32,
421 pub over_current: bool,
423 pub over_temp: bool,
425 pub brake_mode: BrakeMode,
427 pub current_limit: i32,
429 pub voltage_limit: i32,
431}
432
433#[derive(Debug)]
435pub enum MotorError {
436 PortOutOfRange,
438 PortNotMotor,
440 Unknown(i32),
442}
443
444impl MotorError {
445 fn from_errno() -> Self {
446 match get_errno() {
447 libc::ENXIO => Self::PortOutOfRange,
448 libc::ENODEV => Self::PortNotMotor,
449 x => Self::Unknown(x),
450 }
451 }
452}
453
454impl From<MotorError> for Error {
455 fn from(err: MotorError) -> Self {
456 match err {
457 MotorError::PortOutOfRange => Error::Custom("port out of range".into()),
458 MotorError::PortNotMotor => Error::Custom("port not a motor".into()),
459 MotorError::Unknown(n) => Error::System(n),
460 }
461 }
462}
463
464#[derive(Clone, Copy, Debug, PartialEq, Eq)]
466pub enum BrakeMode {
467 Coast,
469 Brake,
471 Hold,
473}
474
475impl From<BrakeMode> for bindings::motor_brake_mode_e {
476 fn from(mode: BrakeMode) -> Self {
477 match mode {
478 BrakeMode::Coast => bindings::motor_brake_mode_e_E_MOTOR_BRAKE_COAST,
479 BrakeMode::Brake => bindings::motor_brake_mode_e_E_MOTOR_BRAKE_BRAKE,
480 BrakeMode::Hold => bindings::motor_brake_mode_e_E_MOTOR_BRAKE_HOLD,
481 }
482 }
483}
484
485#[derive(Clone, Copy, Debug, PartialEq, Eq)]
487pub enum Gearset {
488 SixToOne,
490 EighteenToOne,
492 ThirtySixToOne,
494}
495
496impl From<Gearset> for bindings::motor_gearset_e {
497 fn from(gearset: Gearset) -> Self {
498 match gearset {
499 Gearset::SixToOne => bindings::motor_gearset_e_E_MOTOR_GEARSET_06,
500 Gearset::EighteenToOne => bindings::motor_gearset_e_E_MOTOR_GEARSET_18,
501 Gearset::ThirtySixToOne => bindings::motor_gearset_e_E_MOTOR_GEARSET_36,
502 }
503 }
504}
505
506#[derive(Clone, Copy, Debug, PartialEq, Eq)]
508pub enum Direction {
509 Positive,
511 Negative,
513}
514
515#[derive(Clone, Copy)]
517pub enum EncoderUnits {
518 EncoderTicks,
523 Degrees,
525 Rotations,
527}
528
529impl From<EncoderUnits> for bindings::motor_encoder_units_e {
530 fn from(units: EncoderUnits) -> Self {
531 match units {
532 EncoderUnits::EncoderTicks => bindings::motor_encoder_units_e_E_MOTOR_ENCODER_COUNTS,
533 EncoderUnits::Degrees => bindings::motor_encoder_units_e_E_MOTOR_ENCODER_DEGREES,
534 EncoderUnits::Rotations => bindings::motor_encoder_units_e_E_MOTOR_ENCODER_ROTATIONS,
535 }
536 }
537}