vex_rt/
rotation.rs

1//! # Rotation Sensor API.
2
3use crate::{
4    bindings,
5    error::{get_errno, Error},
6    rtos::DataSource,
7};
8
9/// A struct which represents a V5 smart port configured as a rotation sensor.
10pub struct RotationSensor {
11    port: u8,
12}
13
14impl RotationSensor {
15    /// Constructs a new rotation sensor.
16    ///
17    /// # Safety
18    ///
19    /// This function is unsafe because it allows the user to create multiple
20    /// mutable references to the same rotation sensor. You likely want to
21    /// implement [`Robot::new()`](crate::robot::Robot::new()) instead.
22    pub unsafe fn new(port: u8, reversed: bool) -> Result<Self, RotationSensorError> {
23        let mut sensor = Self { port };
24
25        sensor.set_reversed(reversed)?;
26
27        Ok(sensor)
28    }
29
30    /// Reset the current absolute position to be the same as the Rotation
31    /// Sensor angle.
32    pub fn reset(&mut self) -> Result<(), RotationSensorError> {
33        match unsafe { bindings::rotation_reset(self.port) } {
34            bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
35            _ => Ok(()),
36        }
37    }
38
39    /// Set the Rotation sensor to a desired rotation value in centidegrees.
40    pub fn set_position(&mut self, rotation: u32) -> Result<(), RotationSensorError> {
41        match unsafe { bindings::rotation_set_position(self.port, rotation) } {
42            bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
43            _ => Ok(()),
44        }
45    }
46
47    /// Reset the current absolute position to be the same as the Rotation
48    /// Sensor angle.
49    pub fn reset_position(&mut self) -> Result<(), RotationSensorError> {
50        match unsafe { bindings::rotation_reset_position(self.port) } {
51            bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
52            _ => Ok(()),
53        }
54    }
55
56    /// Get the Rotation Sensor’s current position in centidegrees.
57    pub fn get_position(&self) -> Result<i32, RotationSensorError> {
58        match unsafe { bindings::rotation_get_position(self.port) } {
59            x if x == bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
60            x => Ok(x),
61        }
62    }
63
64    /// Get the Rotation Sensor’s current velocity in centidegrees per second.
65    pub fn get_velocity(&self) -> Result<i32, RotationSensorError> {
66        match unsafe { bindings::rotation_get_velocity(self.port) } {
67            x if x == bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
68            x => Ok(x),
69        }
70    }
71
72    /// Get the Rotation Sensor’s current angle in centidegrees (0-36000).
73    pub fn get_angle(&self) -> Result<i32, RotationSensorError> {
74        match unsafe { bindings::rotation_get_angle(self.port) } {
75            x if x == bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
76            x => Ok(x),
77        }
78    }
79
80    /// Set the rotation direction of the sensor.
81    pub fn set_reversed(&mut self, reverse: bool) -> Result<(), RotationSensorError> {
82        match unsafe { bindings::rotation_set_reversed(self.port, reverse) } {
83            bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
84            _ => Ok(()),
85        }
86    }
87
88    /// Reverses the rotational sensor’s direction.
89    pub fn reverse(&mut self) -> Result<(), RotationSensorError> {
90        match unsafe { bindings::rotation_reverse(self.port) } {
91            bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
92            _ => Ok(()),
93        }
94    }
95
96    /// Get the Rotation Sensor’s reversed flag.
97    pub fn get_reversed(&self) -> Result<bool, RotationSensorError> {
98        match unsafe { bindings::rotation_get_reversed(self.port) } {
99            x if x == bindings::PROS_ERR_ => Err(RotationSensorError::from_errno()),
100            x => Ok(x != 0),
101        }
102    }
103}
104
105impl DataSource for RotationSensor {
106    type Data = RotationSensorData;
107
108    type Error = RotationSensorError;
109
110    fn read(&self) -> Result<Self::Data, Self::Error> {
111        Ok(RotationSensorData {
112            position: self.get_position()?,
113            velocity: self.get_velocity()?,
114            angle: self.get_angle()?,
115        })
116    }
117}
118
119/// Represents the data that can be read from a rotation sensor.
120#[derive(Clone, Copy, Debug, PartialEq, Eq)]
121pub struct RotationSensorData {
122    /// The current position in centidegrees.
123    pub position: i32,
124    /// The current velocity in centidegrees per second.
125    pub velocity: i32,
126    /// The current angle in centidegrees (0-36000).
127    pub angle: i32,
128}
129
130/// Represents possible errors for distance sensor operations.
131#[derive(Debug)]
132pub enum RotationSensorError {
133    /// Port is out of range (1-21).
134    PortOutOfRange,
135    /// Port cannot be configured as a distance sensor.
136    PortNotDistanceSensor,
137    /// Unknown error.
138    Unknown(i32),
139}
140
141impl RotationSensorError {
142    fn from_errno() -> Self {
143        match get_errno() {
144            libc::ENXIO => Self::PortOutOfRange,
145            libc::ENODEV => Self::PortNotDistanceSensor,
146            x => Self::Unknown(x),
147        }
148    }
149}
150
151impl From<RotationSensorError> for Error {
152    fn from(err: RotationSensorError) -> Self {
153        match err {
154            RotationSensorError::PortOutOfRange => Error::Custom("port out of range".into()),
155            RotationSensorError::PortNotDistanceSensor => {
156                Error::Custom("port not a rotation sensor".into())
157            }
158            RotationSensorError::Unknown(n) => Error::System(n),
159        }
160    }
161}