ev3_drivebase/drivebase.rs
1//! Core drivebase functionality for controlling a two-wheeled robot.
2
3mod brake_mode;
4mod drive;
5mod ramping;
6mod run;
7mod speed;
8mod turn;
9mod utils;
10mod wait;
11
12pub use brake_mode::BrakeMode;
13
14use crate::Motor;
15use ev3dev_lang_rust::{Ev3Error, motors::TachoMotor, sensors::ColorSensor};
16use std::f64::consts::PI;
17
18/// A two-wheeled robot drivebase controller.
19///
20/// The `DriveBase` provides high-level control over a differential drive robot,
21/// handling the complex calculations needed for precise movement and turning.
22///
23/// # Physical Parameters
24///
25/// The drivebase needs to know the physical dimensions of your robot:
26///
27/// - **Wheel diameter**: The diameter of your wheels in millimeters
28/// - **Axle track**: The distance between the contact points of the left and right wheels in millimeters
29///
30/// These measurements are critical for accurate distance and angle calculations.
31///
32/// # Examples
33///
34/// Basic setup and movement:
35///
36/// ```no_run
37/// use ev3_drivebase::{DriveBase, Motor, Direction, BrakeMode};
38/// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
39///
40/// fn main() -> Result<(), Ev3Error> {
41/// let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
42/// let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
43///
44/// let mut drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
45/// drivebase.set_brake_mode(BrakeMode::Hold)?;
46///
47/// // Drive 200mm forward at 300 deg/s
48/// drivebase.drive(300, 200, true)?;
49///
50/// Ok(())
51/// }
52/// ```
53#[derive(Debug, Clone)]
54pub struct DriveBase {
55 /// The left motor of the drivebase.
56 pub left: TachoMotor,
57 /// The right motor of the drivebase.
58 pub right: TachoMotor,
59 /// Current speed of the robot in degrees per second.
60 pub current_speed: i32,
61 /// Left color sensor if specified, useful for line following methods.
62 pub left_sensor: Option<ColorSensor>,
63 /// Right color sensor if specified, useful for line following methods.
64 pub right_sensor: Option<ColorSensor>,
65 /// Metadata of the left motor.
66 pub left_meta: Motor,
67 /// Metadata of the right motor.
68 pub right_meta: Motor,
69 /// The circumference of the wheels in millimeters.
70 pub circumference: f64,
71 /// The distance between the points where both wheels touch the ground in millimeters.
72 pub axle_track: f64,
73}
74
75impl DriveBase {
76 /// Creates a new `DriveBase` using the provided motor configurations.
77 ///
78 /// # Parameters
79 ///
80 /// - `left_meta`: Configuration for the left motor
81 /// - `right_meta`: Configuration for the right motor
82 /// - `wheel_diameter`: Diameter of the wheels in millimeters
83 /// - `axle_track`: Distance between wheel contact points in millimeters
84 ///
85 /// # Errors
86 ///
87 /// Returns an error if:
88 /// - The specified motor ports are not connected
89 /// - The ports are being used by another device
90 /// - The motors cannot be initialized
91 ///
92 /// # Examples
93 ///
94 /// ```no_run
95 /// use ev3_drivebase::{DriveBase, Motor, Direction};
96 /// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
97 ///
98 /// fn main() -> Result<(), Ev3Error> {
99 /// let left = Motor::new(MotorPort::OutA, Direction::Clockwise);
100 /// let right = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
101 ///
102 /// // Create drivebase with 43.2mm diameter wheels and 185mm axle track
103 /// let drivebase = DriveBase::new(left, right, 43.2, 185.0)?;
104 ///
105 /// Ok(())
106 /// }
107 /// ```
108 pub fn new(
109 left_meta: Motor,
110 right_meta: Motor,
111 wheel_diameter: f64,
112 axle_track: f64,
113 ) -> Result<Self, Ev3Error> {
114 let left = TachoMotor::get(left_meta.port)?;
115 let right = TachoMotor::get(right_meta.port)?;
116 let circumference = PI * wheel_diameter;
117 let drivebase = Self {
118 left,
119 right,
120 current_speed: 0,
121 left_sensor: None,
122 right_sensor: None,
123 left_meta,
124 right_meta,
125 circumference,
126 axle_track,
127 };
128 drivebase.reset()?;
129 Ok(drivebase)
130 }
131
132 /// Adds left and right color sensors to the drivebase.
133 ///
134 /// Color sensors can be used for line following and other applications
135 /// that require detecting surface colors or light intensity.
136 ///
137 /// # Parameters
138 ///
139 /// - `left_sensor`: The color sensor on the left side of the robot
140 /// - `right_sensor`: The color sensor on the right side of the robot
141 ///
142 /// # Examples
143 ///
144 /// ```no_run
145 /// use ev3_drivebase::{DriveBase, Motor, Direction};
146 /// use ev3_drivebase::ev3dev_lang_rust::{Ev3Error, motors::MotorPort};
147 /// use ev3_drivebase::ev3dev_lang_rust::sensors::{ColorSensor, SensorPort};
148 ///
149 /// fn main() -> Result<(), Ev3Error> {
150 /// let left_motor = Motor::new(MotorPort::OutA, Direction::Clockwise);
151 /// let right_motor = Motor::new(MotorPort::OutB, Direction::CounterClockwise);
152 /// let mut drivebase = DriveBase::new(left_motor, right_motor, 43.2, 185.0)?;
153 ///
154 /// let left_sensor = ColorSensor::get(SensorPort::In1)?;
155 /// let right_sensor = ColorSensor::get(SensorPort::In2)?;
156 ///
157 /// drivebase.add_colorsensor(left_sensor, right_sensor);
158 ///
159 /// Ok(())
160 /// }
161 /// ```
162 pub fn add_colorsensor(
163 &mut self,
164 left_sensor: ColorSensor,
165 right_sensor: ColorSensor,
166 ) -> &Self {
167 self.left_sensor = Some(left_sensor);
168 self.right_sensor = Some(right_sensor);
169 self
170 }
171}