pros_devices/smart/
gps.rs

1//! GPS sensor device.
2//!
3//! A notable differenc between this API and that of PROS
4//! is that [`GpsSensor::status`] returns acceleration along with other status data.
5
6use pros_core::{bail_on, error::PortError, map_errno};
7use pros_sys::{PROS_ERR, PROS_ERR_F};
8use snafu::Snafu;
9
10use super::{SmartDevice, SmartDeviceType, SmartPort};
11
12//TODO: Figure out what all the units are
13#[derive(Default, Debug, Clone, Copy, PartialEq)]
14/// Represents the data output from a GPS sensor.
15pub struct GpsStatus {
16    /// The x-coordinate of the GPS sensor in meters.
17    pub x: f64,
18    /// The y-coordinate of the GPS sensor in meters.
19    pub y: f64,
20    /// The pitch of the GPS sensor.
21    pub pitch: f64,
22    /// The roll of the GPS sensor.
23    pub roll: f64,
24    /// The yaw of the GPS sensor.
25    pub yaw: f64,
26    /// The heading of the GPS sensor.
27    pub heading: f64,
28
29    /// The x-acceleration of the GPS sensor.
30    pub accel_x: f64,
31    /// The y-acceleration of the GPS sensor.
32    pub accel_y: f64,
33    /// The z-acceleration of the GPS sensor.
34    pub accel_z: f64,
35}
36
37/// A physical GPS sensor plugged into a port.
38#[derive(Debug, Eq, PartialEq)]
39pub struct GpsSensor {
40    port: SmartPort,
41}
42
43impl GpsSensor {
44    /// Creates a new GPS sensor on the given port.
45    pub fn new(port: SmartPort) -> Result<Self, GpsError> {
46        unsafe {
47            bail_on!(
48                PROS_ERR,
49                pros_sys::gps_initialize_full(port.index(), 0.0, 0.0, 0.0, 0.0, 0.0)
50            );
51        }
52
53        Ok(Self { port })
54    }
55
56    /// Sets the offset of the GPS sensor, relative to the sensor of turning, in meters.
57    pub fn set_offset(&mut self, x: f64, y: f64) -> Result<(), GpsError> {
58        unsafe {
59            bail_on!(PROS_ERR, pros_sys::gps_set_offset(self.port.index(), x, y));
60        }
61        Ok(())
62    }
63
64    /// Gets the possible error of the GPS sensor, in meters.
65    pub fn rms_error(&self) -> Result<f64, GpsError> {
66        Ok(unsafe { bail_on!(PROS_ERR_F, pros_sys::gps_get_error(self.port.index())) })
67    }
68
69    /// Gets the status of the GPS sensor.
70    pub fn status(&self) -> Result<GpsStatus, GpsError> {
71        unsafe {
72            let status = pros_sys::gps_get_status(self.port.index());
73            bail_on!(PROS_ERR_F, status.x);
74            let accel = pros_sys::gps_get_accel(self.port.index());
75            bail_on!(PROS_ERR_F, accel.x);
76            let heading = bail_on!(PROS_ERR_F, pros_sys::gps_get_heading(self.port.index()));
77
78            Ok(GpsStatus {
79                x: status.x,
80                y: status.y,
81                pitch: status.pitch,
82                roll: status.roll,
83                yaw: status.yaw,
84                heading,
85
86                accel_x: accel.x,
87                accel_y: accel.y,
88                accel_z: accel.z,
89            })
90        }
91    }
92
93    /// Zeroes the rotation of the GPS sensor.
94    pub fn zero_rotation(&mut self) -> Result<(), GpsError> {
95        unsafe {
96            bail_on!(PROS_ERR, pros_sys::gps_tare_rotation(self.port.index()));
97        }
98        Ok(())
99    }
100}
101
102impl SmartDevice for GpsSensor {
103    fn port_index(&self) -> u8 {
104        self.port.index()
105    }
106
107    fn device_type(&self) -> SmartDeviceType {
108        SmartDeviceType::Gps
109    }
110}
111
112#[derive(Debug, Snafu)]
113/// Errors that can occur when using a GPS sensor.
114pub enum GpsError {
115    /// The GPS sensor is still calibrating.
116    StillCalibrating,
117    #[snafu(display("{source}"), context(false))]
118    /// Generic port related error.
119    Port {
120        /// The source of the error.
121        source: PortError,
122    },
123}
124
125map_errno! {
126    GpsError {
127        EAGAIN => Self::StillCalibrating,
128    }
129    inherit PortError;
130}