ev3dev_rs/pupdevices/
gyro_sensor.rs

1use crate::{
2    attribute::AttributeName,
3    error::Ev3Result,
4    parameters::SensorPort,
5    sensor_driver::{SensorDriver, SensorMode::*, SensorType},
6};
7
8/// Stock EV3 Gyro Sensor
9///
10/// # Examples
11/// ``` no_run
12/// use ev3dev_rs::pupdevices::GyroSensor;
13/// use ev3dev_rs::parameters::SensorPort;
14///
15/// let gyro_sensor = GyroSensor::new(SensorPort::In1)?;
16///
17/// println!("Heading: {}", gyro_sensor.heading()?);
18/// println!("Velocity: {}", gyro_sensor.rate()?);
19/// println!("Tilt: {}", gyro_sensor.tilt()?);
20/// println!("Tilt Velocity: {}", gyro_sensor.tilt_velocity()?);
21///
22/// ```
23pub struct GyroSensor {
24    driver: SensorDriver,
25}
26
27impl GyroSensor {
28    /// Find a `GyroSensor` on the given port.
29    ///
30    /// Will return `SensorNotFound` if no sensor is found
31    /// or `IncorrectSensorType` if the found sensor is not a `GyroSensor`.
32    pub fn new(port: SensorPort) -> Ev3Result<Self> {
33        let driver = SensorDriver::new(SensorType::Gyro, port)?;
34        Ok(Self { driver })
35    }
36
37    /// Get the current heading of the sensor in degrees (-32768 to 32767).
38    pub fn heading(&self) -> Ev3Result<i16> {
39        match self.driver.mode.get() {
40            GyroAngle | GyroAngleAndRate => {
41                Ok(self.driver.read_attribute(AttributeName::Value0)?.parse()?)
42            }
43            _ => {
44                self.driver.set_mode(GyroAngleAndRate)?;
45                Ok(self.driver.read_attribute(AttributeName::Value0)?.parse()?)
46            }
47        }
48    }
49
50    /// Get the current angular velocity of the sensor in degrees per second (-440 to 440).
51    pub fn angular_velocity(&self) -> Ev3Result<i16> {
52        match self.driver.mode.get() {
53            GyroRate => Ok(self.driver.read_attribute(AttributeName::Value0)?.parse()?),
54            GyroAngleAndRate => Ok(self.driver.read_attribute(AttributeName::Value1)?.parse()?),
55            _ => {
56                self.driver.set_mode(GyroAngleAndRate)?;
57                Ok(self.driver.read_attribute(AttributeName::Value1)?.parse()?)
58            }
59        }
60    }
61
62    /// Get the current heading and angular velocity of the sensor.
63    ///
64    /// This does the same job as calling both `heading()` and `angular_velocity()`,
65    /// but it is more efficient because it reads them simultaneously.
66    ///
67    /// # Examples
68    ///
69    /// ``` no_run
70    /// let (heading, velocity) = sensor.heading_and_velocity()?;
71    /// assert_eq!(heading, sensor.heading()?);
72    /// assert_eq!(velocity, sensor.angular_velocity()?);
73    /// ```
74    pub fn heading_and_velocity(&self) -> Ev3Result<(i16, i16)> {
75        if self.driver.mode.get() != GyroAngleAndRate {
76            self.driver.set_mode(GyroAngleAndRate)?;
77        }
78
79        let heading = self.driver.read_attribute(AttributeName::Value0)?.parse()?;
80        let velocity = self.driver.read_attribute(AttributeName::Value1)?.parse()?;
81
82        Ok((heading, velocity))
83    }
84
85    /// Get the current tilt angle of the sensor in degrees (-32768 to 32767).
86    pub fn tilt(&self) -> Ev3Result<i16> {
87        if self.driver.mode.get() != GyroTiltAngle {
88            self.driver.set_mode(GyroTiltAngle)?;
89        }
90
91        Ok(self.driver.read_attribute(AttributeName::Value0)?.parse()?)
92    }
93
94    /// Get the current tilt velocity of the sensor in degrees per second (-440 to 440).
95    pub fn tilt_velocity(&self) -> Ev3Result<i16> {
96        if self.driver.mode.get() != GyroTiltRate {
97            self.driver.set_mode(GyroTiltRate)?;
98        }
99
100        Ok(self.driver.read_attribute(AttributeName::Value0)?.parse()?)
101    }
102}