Skip to main content

frclib_core/hal/rt/
station_interface.rs

1//! A platform and driver station independent interface for interacting with the user control station.
2
3/// The commanded enable state of the robot.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
5pub enum EnabledState {
6    /// The robot is unable to actuate any mechanisms.
7    #[default]
8    Disabled,
9    /// Same as [`Disabled`](EnabledState::Disabled) but the robot has to be restarted to re-enable.
10    EStopped,
11    /// The robot is able to actuate mechanisms.
12    Enabled,
13}
14
15/// The commanded mode of the robot.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
17pub enum Mode {
18    /// The is being controlled by a user directly.
19    #[default]
20    Teleop,
21    /// The robot is being controlled by a user code autonomously.
22    Auto,
23    /// The robot is being controlled by a user directly for testing purposes.
24    Test,
25}
26
27/// The data for a single joystick.
28#[derive(Debug, Clone, Copy, PartialEq, Default)]
29pub struct JoystickData {
30    /// If the joystick is plugged in.
31    pub plugged_in: bool,
32    /// An array of the joystick axies,
33    /// this can be lossy if the joystick has more than 8 axies.
34    pub axies: [f32; 8],
35    /// An array of the joystick buttons,
36    /// this can be lossy if the joystick has more than 48 buttons.
37    /// This array sub should treated as 8*6 bits where each bit is a button.
38    pub buttons: [u8; 6],
39    /// An array of the joystick povs,
40    /// this can be lossy if the joystick has more than 3 povs.
41    pub povs: [i16; 3],
42}
43
44/// The data for the current station.
45#[allow(missing_docs)]
46#[derive(Debug, Clone, Copy, Default)]
47pub struct StationData {
48    pub enabled_state: EnabledState,
49    pub mode: Mode,
50    pub station_attached: bool,
51    pub fms_attached: bool,
52    pub team_number: u16,
53    pub joysticks: [JoystickData; 8],
54}
55
56/// A trait that represents a platform specific user control station interface.
57pub trait StationInterfaceDriver: 'static {
58    /// Will send an error message to the driver station console,
59    /// driver station has to support error messages.
60    fn send_console_line_error(line: &str, location: &str, callstack: &str);
61
62    /// Will send a warning message to the driver station console,
63    /// if the driver station does not support warnings it will be sent as an error.
64    fn send_console_line_warn(line: &str, location: &str);
65
66    /// Will send an info message to the driver station console,
67    /// driver station has to support info messages.
68    fn send_console_line_info(line: &str, location: &str);
69
70    /// Will send a debug message to the driver station console,
71    /// if the driver station does not support debug messages it will be ignored.
72    fn send_console_line_debug(line: &str, location: &str);
73
74    /// Should update all process local station data from the driver station latest values.
75    fn refresh();
76
77    /// Should return the latest station data.
78    fn get_station_data() -> StationData;
79}
80
81/// A struct that defines a platform specific user control station interface for user code.
82#[derive(Debug, Clone, Copy)]
83pub struct StationInterfaceVTable {
84    pub(crate) send_console_line_error: fn(line: &str, location: &str, callstack: &str),
85    pub(crate) send_console_line_warn: fn(line: &str, location: &str),
86    pub(crate) send_console_line_info: fn(line: &str, location: &str),
87    pub(crate) send_console_line_debug: fn(line: &str, location: &str),
88    pub(crate) refresh: fn(),
89    pub(crate) get_station_data: fn() -> StationData,
90}
91
92impl StationInterfaceVTable {
93    pub(crate) fn from_driver<T: StationInterfaceDriver>() -> Self {
94        assert!(
95            std::mem::size_of::<T>() == 0,
96            "Station Interface Driver must be zero sized"
97        );
98        Self {
99            send_console_line_error: T::send_console_line_error,
100            send_console_line_warn: T::send_console_line_warn,
101            send_console_line_info: T::send_console_line_info,
102            send_console_line_debug: T::send_console_line_debug,
103            refresh: T::refresh,
104            get_station_data: T::get_station_data,
105        }
106    }
107
108    /// Will send an error message to the driver station console,
109    /// driver station has to support error messages.
110    pub fn send_console_line_error(&self, line: &str, location: &str, callstack: &str) {
111        (self.send_console_line_error)(line, location, callstack);
112    }
113
114    /// Will send a warning message to the driver station console,
115    /// if the driver station does not support warnings it will be sent as an error.
116    pub fn send_console_line_warn(&self, line: &str, location: &str) {
117        (self.send_console_line_warn)(line, location);
118    }
119
120    /// Will send an info message to the driver station console,
121    /// driver station has to support info messages.
122    pub fn send_console_line_info(&self, line: &str, location: &str) {
123        (self.send_console_line_info)(line, location);
124    }
125
126    /// Will send a debug message to the driver station console,
127    /// if the driver station does not support debug messages it will be ignored.
128    pub fn send_console_line_debug(&self, line: &str, location: &str) {
129        (self.send_console_line_debug)(line, location);
130    }
131
132    /// Should update all process local station data from the driver station latest values.
133    pub fn refresh(&self) {
134        (self.refresh)();
135    }
136
137    /// Should return the latest station data.
138    #[must_use]
139    pub fn get_station_data(&self) -> StationData {
140        (self.get_station_data)()
141    }
142
143    /// Returns if the latest station data declares the robot enabled.
144    #[must_use]
145    pub fn is_enabled(&self) -> bool {
146        self.get_station_data().enabled_state == EnabledState::Enabled
147    }
148
149    /// Returns if the latest station data declares the robot disabled.
150    #[must_use]
151    pub fn is_disabled(&self) -> bool {
152        self.get_station_data().enabled_state == EnabledState::Disabled
153    }
154
155    /// Returns if the latest station data declares the robot estopped.
156    #[must_use]
157    pub fn is_estopped(&self) -> bool {
158        self.get_station_data().enabled_state == EnabledState::EStopped
159    }
160
161    /// Returns if the latest station data declares the robot in teleop mode.
162    #[must_use]
163    pub fn is_teleop(&self) -> bool {
164        self.get_station_data().mode == Mode::Teleop
165    }
166
167    /// Returns if the latest station data declares the robot in auto mode.
168    #[must_use]
169    pub fn is_auto(&self) -> bool {
170        self.get_station_data().mode == Mode::Auto
171    }
172
173    /// Returns if the latest station data declares the robot in test mode.
174    #[must_use]
175    pub fn is_test(&self) -> bool {
176        self.get_station_data().mode == Mode::Test
177    }
178
179    /// Returns if the latest station data declares the robot is attached to the FMS.
180    #[must_use]
181    pub fn is_fms_attached(&self) -> bool {
182        self.get_station_data().fms_attached
183    }
184
185    /// Returns if the latest station data declares the robot is attached to a station.
186    #[must_use]
187    pub fn is_station_attached(&self) -> bool {
188        self.get_station_data().station_attached
189    }
190
191    /// Returns the team number of the latest station data.
192    #[must_use]
193    pub fn get_station_team_number(&self) -> u16 {
194        self.get_station_data().team_number
195    }
196}