ev3_drivebase/drivebase/
utils.rs

1use super::DriveBase;
2use ev3dev_lang_rust::Ev3Error;
3
4impl DriveBase {
5    /// Stops both motors and is called on drop.
6    ///
7    /// # Errors
8    ///
9    /// Errors if it can't set the stop command.
10    pub fn stop(&self) -> Result<&Self, Ev3Error> {
11        self.left.stop()?;
12        self.right.stop()?;
13        Ok(self)
14    }
15
16    /// Resets all of the parameters of both motors and the `DriveBase`. Has the added effect of stopping.
17    ///
18    /// # Errors
19    ///
20    /// Errors if it can't reset the `DriveBase`.
21    pub fn reset(&self) -> Result<&Self, Ev3Error> {
22        self.left.reset()?;
23        self.right.reset()?;
24        Ok(self)
25    }
26
27    /// If power is being sent to both motors.
28    ///
29    /// # Errors
30    ///
31    /// Errors if it can't set the stop command.
32    pub fn is_running(&self) -> Result<bool, Ev3Error> {
33        Ok(self.left.is_running()? || self.right.is_running()?)
34    }
35
36    /// If any one of the motors are still ramping up.
37    ///
38    /// # Errors
39    ///
40    /// Errors if it can't read the sysfs
41    pub fn is_ramping(&self) -> Result<bool, Ev3Error> {
42        Ok(self.left.is_ramping()? || self.right.is_ramping()?)
43    }
44
45    /// If any one of the motors are holding.
46    ///
47    /// # Errors
48    ///
49    /// Errors if it can't read the sysfs
50    pub fn is_holding(&self) -> Result<bool, Ev3Error> {
51        Ok(self.left.is_holding()? || self.right.is_holding()?)
52    }
53
54    /// If any one of the motors are overloaded.
55    ///
56    /// # Errors
57    ///
58    /// Errors if it can't read the sysfs
59    pub fn is_overloaded(&self) -> Result<bool, Ev3Error> {
60        Ok(self.left.is_overloaded()? || self.right.is_overloaded()?)
61    }
62
63    /// If any one of the motors are stalled.
64    ///
65    /// # Errors
66    ///
67    /// Errors if it can't read the sysfs
68    pub fn is_stalled(&self) -> Result<bool, Ev3Error> {
69        Ok(self.left.is_stalled()? || self.right.is_stalled()?)
70    }
71
72    /// Returns the encoder counts for a distance in mm with the correct
73    /// sign according to the motor direction.
74    #[expect(clippy::cast_possible_truncation)]
75    pub(super) fn calculate_counts(
76        &self,
77        left_distance: i32,
78        right_distance: i32,
79    ) -> Result<(i32, i32), Ev3Error> {
80        let left_distance = left_distance.abs();
81        let right_distance = right_distance.abs();
82
83        let mut left_counts = ((f64::from(left_distance) / self.circumference)
84            * f64::from(self.left.get_count_per_rot()?))
85        .round()
86        .clamp(f64::from(i32::MIN), f64::from(i32::MAX)) as i32;
87
88        let mut right_counts = ((f64::from(right_distance) / self.circumference)
89            * f64::from(self.right.get_count_per_rot()?))
90        .round()
91        .clamp(f64::from(i32::MIN), f64::from(i32::MAX)) as i32;
92
93        left_counts = left_counts.saturating_mul(self.left_meta.direction.sign());
94        right_counts = right_counts.saturating_mul(self.right_meta.direction.sign());
95
96        Ok((left_counts, right_counts))
97    }
98}
99
100impl Drop for DriveBase {
101    fn drop(&mut self) {
102        let _ = self.stop();
103        let _ = self.set_brake_mode(super::BrakeMode::Coast);
104    }
105}