openrr_base/types/
differential_drive.rs
1use arci::{BaseVelocity, Localization, MotorDriveVelocity, MoveBase};
2
3use crate::*;
4
5#[derive(Debug)]
6pub struct DifferentialDriveHardwareParameters {
7 pub wheel_radius: f64,
8 pub tread_width: f64,
9}
10
11#[derive(Debug)]
12pub struct DifferentialDriveMotorController<MV: MotorDriveVelocity> {
13 pub left: MV,
14 pub right: MV,
15}
16
17#[derive(Debug)]
18pub struct DifferentialDrive<MV>
19where
20 MV: MotorDriveVelocity,
21{
22 robot_velocity: RobotVelocityStatus,
23 controller: DifferentialDriveMotorController<MV>,
24 param: DifferentialDriveHardwareParameters,
25 odometry: Odometry,
26}
27
28impl<MV> DifferentialDrive<MV>
29where
30 MV: MotorDriveVelocity,
31{
32 pub fn new(
33 param: DifferentialDriveHardwareParameters,
34 controller: DifferentialDriveMotorController<MV>,
35 limit_velocity: BaseVelocity,
36 limit_acceleration: BaseAcceleration,
37 ) -> Self {
38 Self {
39 robot_velocity: RobotVelocityStatus::new(limit_velocity, limit_acceleration),
40 controller,
41 param,
42 odometry: Odometry::default(),
43 }
44 }
45
46 pub fn transform_velocity_base_to_wheel(&self, velocity: &BaseVelocity) -> [f64; 2] {
48 [
49 (velocity.x - 0.5 * self.param.tread_width * velocity.theta) / self.param.wheel_radius,
50 (velocity.x + 0.5 * self.param.tread_width * velocity.theta) / self.param.wheel_radius,
51 ]
52 }
53
54 pub fn transform_velocity_wheel_to_base(&self, wheels_vel: &[f64; 2]) -> BaseVelocity {
56 let left = wheels_vel[0];
57 let right = wheels_vel[1];
58 let translation = 0.5 * self.param.wheel_radius * (left + right);
59 let rotation = self.param.wheel_radius * (right - left) / self.param.tread_width;
60 BaseVelocity {
61 x: translation,
62 y: 0f64,
63 theta: rotation,
64 }
65 }
66}
67
68impl<MV> MoveBase for DifferentialDrive<MV>
69where
70 MV: MotorDriveVelocity,
71{
72 fn send_velocity(&self, velocity: &BaseVelocity) -> Result<(), arci::Error> {
73 let limited_vel = self.robot_velocity.get_limited_velocity(velocity);
74
75 let wheels_vel = self.transform_velocity_base_to_wheel(&limited_vel);
76
77 self.controller
78 .left
79 .set_motor_velocity(wheels_vel[0])
80 .unwrap();
81 self.controller
82 .right
83 .set_motor_velocity(wheels_vel[1])
84 .unwrap();
85
86 let wheels_feedback = [
87 self.controller.left.get_motor_velocity().unwrap(),
88 self.controller.right.get_motor_velocity().unwrap(),
89 ];
90 let feedback_vel = self.transform_velocity_wheel_to_base(&wheels_feedback);
91
92 match self.odometry.update_by_velocity(&feedback_vel) {
93 Ok(_) => {}
94 Err(e) => println!("{e}"),
95 }
96
97 self.robot_velocity.set_log(&limited_vel);
98
99 Ok(())
100 }
101
102 fn current_velocity(&self) -> Result<BaseVelocity, arci::Error> {
103 let left_wheel_rotation = self.controller.left.get_motor_velocity().unwrap();
104 let right_wheel_rotation = self.controller.right.get_motor_velocity().unwrap();
105
106 let feedback_vel =
107 self.transform_velocity_wheel_to_base(&[left_wheel_rotation, right_wheel_rotation]);
108
109 self.robot_velocity.set_velocity_state(feedback_vel);
110
111 Ok(feedback_vel)
112 }
113}
114
115impl<MV> Localization for DifferentialDrive<MV>
116where
117 MV: MotorDriveVelocity,
118{
119 fn current_pose(&self, _frame_id: &str) -> Result<arci::Isometry2<f64>, arci::Error> {
120 match self.odometry.current_pose() {
121 Ok(pose) => Ok(pose),
122 Err(e) => Err(arci::Error::Other(e.into())),
123 }
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use arci::DummyMotorDriveVelocity;
130 use assert_approx_eq::assert_approx_eq;
131
132 use super::*;
133
134 const LIMIT_VEL_X: f64 = 10.0;
135 const LIMIT_VEL_THETA: f64 = 10.0;
136 const LIMIT_ACC_X: f64 = 10.0;
137 const LIMIT_ACC_THETA: f64 = 10.0;
138
139 #[test]
140 fn test_velocity_transformer() {
141 let param = DifferentialDriveHardwareParameters {
142 wheel_radius: 0.5,
143 tread_width: 1.0,
144 };
145 let controller = DifferentialDriveMotorController {
146 left: DummyMotorDriveVelocity::default(),
147 right: DummyMotorDriveVelocity::default(),
148 };
149
150 controller.left.set_motor_velocity(1.234).unwrap();
151 controller.right.set_motor_velocity(2.345).unwrap();
152
153 let limit_velocity = BaseVelocity::new(LIMIT_VEL_X, 0.0, LIMIT_VEL_THETA);
154 let limit_acceleration = BaseAcceleration::new(LIMIT_ACC_X, 0.0, LIMIT_ACC_THETA);
155
156 let dd = DifferentialDrive::new(param, controller, limit_velocity, limit_acceleration);
157
158 let straight_vel = BaseVelocity {
159 x: 1.0,
160 y: 0.0,
161 theta: 0.0,
162 };
163 let turning_vel = BaseVelocity {
164 x: 0.0,
165 y: 0.0,
166 theta: 1.0,
167 };
168
169 let straight_wheel_vel = dd.transform_velocity_base_to_wheel(&straight_vel);
170 let turning_wheel_vel = dd.transform_velocity_base_to_wheel(&turning_vel);
171
172 assert_approx_eq!(straight_wheel_vel[0], 2.0);
173 assert_approx_eq!(straight_wheel_vel[1], 2.0);
174 assert_approx_eq!(turning_wheel_vel[0], -1.0);
175 assert_approx_eq!(turning_wheel_vel[1], 1.0);
176 }
177}