Skip to main content

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().await?);
18/// println!("Velocity: {}", gyro_sensor.angular_velocity().await?);
19/// println!("Tilt: {}", gyro_sensor.tilt().await?);
20/// println!("Tilt Velocity: {}", gyro_sensor.tilt_velocity().await?);
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 32,767).
38    pub async fn heading(&self) -> Ev3Result<i16> {
39        self.driver.set_mode(GyroAngleAndRate).await?;
40        Ok(self
41            .driver
42            .read_attribute(AttributeName::Value0)
43            .await?
44            .parse()?)
45    }
46
47    /// Get the current angular velocity of the sensor in degrees per second (-440 to 440).
48    pub async fn angular_velocity(&self) -> Ev3Result<i16> {
49        self.driver.set_mode(GyroAngleAndRate).await?;
50
51        Ok(self
52            .driver
53            .read_attribute(AttributeName::Value1)
54            .await?
55            .parse()?)
56    }
57
58    /// Get the current heading and angular velocity of the sensor.
59    ///
60    /// This does the same job as calling both `heading()` and `angular_velocity()`,
61    /// but it is more efficient because it reads them simultaneously.
62    ///
63    /// # Examples
64    ///
65    /// ``` no_run
66    /// let (heading, velocity) = sensor.heading_and_velocity()?;
67    /// assert_eq!(heading, sensor.heading().await?);
68    /// assert_eq!(velocity, sensor.angular_velocity().await?);
69    /// ```
70    pub async fn heading_and_velocity(&self) -> Ev3Result<(i16, i16)> {
71        self.driver.set_mode(GyroAngleAndRate).await?;
72
73        let heading = self
74            .driver
75            .read_attribute(AttributeName::Value0)
76            .await?
77            .parse()?;
78        let velocity = self
79            .driver
80            .read_attribute(AttributeName::Value1)
81            .await?
82            .parse()?;
83
84        Ok((heading, velocity))
85    }
86
87    /// Get the current tilt angle of the sensor in degrees (-32768 to, 32,767).
88    pub async fn tilt(&self) -> Ev3Result<i16> {
89        self.driver.set_mode(GyroTiltAngle).await?;
90
91        Ok(self
92            .driver
93            .read_attribute(AttributeName::Value0)
94            .await?
95            .parse()?)
96    }
97
98    /// Get the current tilt velocity of the sensor in degrees per second (-440 to 440).
99    pub async fn tilt_velocity(&self) -> Ev3Result<i16> {
100        self.driver.set_mode(GyroTiltRate).await?;
101
102        Ok(self
103            .driver
104            .read_attribute(AttributeName::Value0)
105            .await?
106            .parse()?)
107    }
108}