ev3_drivebase/drivebase/
drive.rs

1use super::DriveBase;
2use crate::Direction;
3use ev3dev_lang_rust::Ev3Error;
4
5impl DriveBase {
6    /// Drives the robot forward or backward for a specified distance.
7    ///
8    /// The robot will drive in a straight line at the given speed until it has traveled
9    /// the specified distance, then stop according to the configured brake mode.
10    ///
11    /// # Parameters
12    ///
13    /// - `speed`: The speed in degrees per second. Positive values use forward direction,
14    ///   negative values reverse the direction.
15    /// - `distance`: The distance to travel in millimeters. Positive for forward, negative for backward.
16    /// - `stop`: Whether to stop the motors after reaching the target distance.
17    ///   - `true`: Motors will stop when the distance is reached
18    ///   - `false`: Motors will continue running at the same speed after reaching the distance
19    ///
20    /// # Errors
21    ///
22    /// Returns an error if:
23    /// - The motors cannot be commanded
24    /// - Speed or distance calculations fail
25    ///
26    /// # Examples
27    ///
28    /// Basic forward and backward movement:
29    ///
30    /// ```no_run
31    /// use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
32    /// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
33    ///
34    /// fn main() -> Result<(), Ev3Error> {
35    ///     let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
36    ///     let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
37    ///     let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
38    ///     drivebase.set_brake_mode(BrakeMode::Hold)?;
39    ///
40    ///     // Drive forward 300mm at 200 deg/s and stop
41    ///     drivebase.drive(200, 300, true)?;
42    ///
43    ///     // Drive backward 150mm at 100 deg/s and stop
44    ///     drivebase.drive(100, -150, true)?;
45    ///
46    ///     // Drive forward 500mm and continue running
47    ///     drivebase.drive(300, 500, false)?;
48    ///
49    ///     Ok(())
50    /// }
51    /// ```
52    ///
53    /// # Behavior
54    ///
55    /// - If `distance` is 0, the method returns immediately without moving
56    /// - The direction of travel is determined by the sign of `distance`
57    /// - The method blocks until the robot reaches the target distance
58    /// - Motor speeds are automatically adjusted based on the configured motor directions
59    pub fn drive(
60        &mut self,
61        speed: i32,
62        distance: impl Into<i32>,
63        stop: bool,
64    ) -> Result<&Self, Ev3Error> {
65        let distance: i32 = distance.into();
66        if distance == 0 {
67            return Ok(self);
68        }
69
70        let direction = if distance < 0 {
71            Direction::CounterClockwise
72        } else {
73            Direction::Clockwise
74        };
75
76        self.set_speed(speed, speed)?;
77
78        let mut counts = self.calculate_counts(distance, distance)?;
79
80        counts.0 = counts.0.saturating_mul(direction.sign());
81        counts.1 = counts.1.saturating_mul(direction.sign());
82
83        self.run_to_rel_pos(counts.0, counts.1)?;
84        self.wait_until_not_moving(None);
85
86        if !stop {
87            self.run_forever()?;
88        }
89
90        Ok(self)
91    }
92}