1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use super::MotorControl;
use crate::ESC;
use nalgebra::Vector3;
use std::f32::consts::SQRT_2;
pub struct QuadMotorControl<E> {
pub m: f32,
pub k_m: f32,
pub k_f: f32,
pub l: f32,
pub min_thrust: f32,
pub max_thrust: f32,
pub motors: [E; 4],
}
impl<E: ESC<f32>> QuadMotorControl<E> {
pub fn new(m: f32, length: f32, max_thrust: f32, min_thrust: f32, motors: [E; 4]) -> Self {
Self {
k_f: 1.,
k_m: 1.,
m,
l: length / (2. * SQRT_2),
motors,
min_thrust,
max_thrust,
}
}
pub fn thrust_from_acceleration(
&self,
acceleration: Vector3<f32>,
thrust_acceleration: f32,
moment_of_inertia: &Vector3<f32>,
) -> [f32; 4] {
let angular_velocity = self.angular_velocity_from_acceleration(
acceleration,
thrust_acceleration,
moment_of_inertia,
);
self.thrust_from_angular_velocity(angular_velocity)
}
pub fn angular_velocity(
&self,
torque: Vector3<f32>,
thrust_acceleration: f32,
moment_of_inertia: &Vector3<f32>,
) -> [f32; 4] {
let acceleration = torque.zip_map(moment_of_inertia, |t, moi| acceleration(t, moi));
self.angular_velocity_from_acceleration(
acceleration,
thrust_acceleration,
moment_of_inertia,
)
}
pub fn angular_velocity_from_acceleration(
&self,
acceleration: Vector3<f32>,
thrust_acceleration: f32,
moment_of_inertia: &Vector3<f32>,
) -> [f32; 4] {
let c_bar = -thrust_acceleration * self.m / self.k_f;
let p_bar = acceleration.x * moment_of_inertia.x / (self.k_f * self.l);
let q_bar = acceleration.y * moment_of_inertia.y / (self.k_f * self.l);
let r_bar = acceleration.z * moment_of_inertia.z / self.k_m;
let omega_4 = (c_bar + p_bar - r_bar - q_bar) / 4.;
let omega_3 = (r_bar - p_bar) / 2. + omega_4;
let omega_2 = (c_bar - p_bar) / 2. - omega_3;
let omega_1 = c_bar - omega_2 - omega_3 - omega_4;
[
-(omega_1.sqrt()),
omega_2.sqrt(),
-(omega_3.sqrt()),
omega_4.sqrt(),
]
}
pub fn thrust_from_angular_velocity(&self, angular_velocity: [f32; 4]) -> [f32; 4] {
angular_velocity.map(|v| self.k_f * v.powi(2))
}
pub fn output_thrust(&mut self, thrust: [f32; 4]) {
for (esc, thrust) in self.motors.iter_mut().zip(thrust) {
let actuation =
(thrust - self.min_thrust) * 2. / (self.max_thrust - self.min_thrust) + 1.;
esc.output(thrust);
}
}
}
fn acceleration(net_torque: f32, moment_of_inertia: f32) -> f32 {
net_torque / moment_of_inertia
}
impl<E: ESC<f32>> MotorControl for QuadMotorControl<E> {
fn arm(&mut self) {
for motor in &mut self.motors {
motor.arm();
}
}
fn motor_control(
&mut self,
torque: Vector3<f32>,
acceleration: f32,
moment_of_inertia: &Vector3<f32>,
) {
let angular_velocity = self.angular_velocity(torque, acceleration, moment_of_inertia);
let thrust = self.thrust_from_angular_velocity(angular_velocity);
self.output_thrust(thrust);
}
}