2026-03-11 12:50:50 +00:00
|
|
|
use crate::DroneState;
|
|
|
|
|
use crate::PidConfig;
|
2026-02-05 20:26:42 +00:00
|
|
|
use nalgebra as na;
|
|
|
|
|
|
2026-03-03 11:17:30 +00:00
|
|
|
pub mod acceleration;
|
2026-03-02 16:09:30 +00:00
|
|
|
pub mod angular_rate;
|
|
|
|
|
pub mod rotation;
|
2026-03-02 15:39:21 +00:00
|
|
|
|
2026-03-03 11:17:30 +00:00
|
|
|
pub use acceleration::AccelerationController;
|
2026-03-02 16:09:30 +00:00
|
|
|
pub use angular_rate::AngularRateController;
|
|
|
|
|
pub use rotation::RotationController;
|
2026-03-02 15:39:21 +00:00
|
|
|
|
|
|
|
|
pub trait ControllerModule {
|
|
|
|
|
type Input: Clone + Default;
|
|
|
|
|
type Output: Clone + Default;
|
|
|
|
|
|
|
|
|
|
fn process(&mut self, input: Self::Input, state: &DroneState, dt: f32) -> Self::Output;
|
2026-02-05 20:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-02 15:39:21 +00:00
|
|
|
pub struct ModuleRuntime<C>
|
|
|
|
|
where
|
|
|
|
|
C: ControllerModule,
|
|
|
|
|
{
|
|
|
|
|
pub module: C,
|
|
|
|
|
pub target_dt: f32,
|
2026-02-23 08:23:52 +00:00
|
|
|
pub accumulated_time: f32,
|
2026-03-02 15:39:21 +00:00
|
|
|
pub last_output: Option<C::Output>,
|
2026-02-23 08:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-02 15:39:21 +00:00
|
|
|
impl<C> ModuleRuntime<C>
|
|
|
|
|
where
|
|
|
|
|
C: ControllerModule,
|
|
|
|
|
{
|
|
|
|
|
pub fn update(&mut self, input: C::Input, state: &DroneState, dt: f32) -> C::Output {
|
|
|
|
|
self.accumulated_time += dt;
|
|
|
|
|
|
|
|
|
|
if self.accumulated_time >= self.target_dt {
|
|
|
|
|
self.accumulated_time = 0.0;
|
|
|
|
|
|
|
|
|
|
let output = self.module.process(input, state, self.target_dt);
|
|
|
|
|
self.last_output = Some(output.clone());
|
|
|
|
|
output
|
|
|
|
|
} else {
|
|
|
|
|
self.last_output
|
|
|
|
|
.as_ref()
|
|
|
|
|
.unwrap_or(&C::Output::default())
|
|
|
|
|
.clone()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub fn new(module: C, frequency: f32) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
module,
|
|
|
|
|
target_dt: 1.0 / frequency,
|
|
|
|
|
accumulated_time: 0.0,
|
|
|
|
|
last_output: None,
|
2026-02-05 20:26:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-02 15:39:21 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Position(pub na::Vector3<f32>); // meters
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Velocity(pub na::Vector3<f32>); // m/s
|
|
|
|
|
|
2026-03-02 16:09:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Acceleration(pub na::Vector3<f32>); // m/s
|
|
|
|
|
|
2026-03-02 15:39:21 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Rotation(pub na::Vector3<f32>); // radians
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct AngularRate(pub na::Vector3<f32>); // rad/s
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Torque(pub na::Vector3<f32>); // control output
|
|
|
|
|
|
2026-03-03 11:17:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default)]
|
|
|
|
|
pub struct Throttle(pub f32);
|
|
|
|
|
|
2026-02-05 20:26:42 +00:00
|
|
|
pub struct PidProcessor {
|
|
|
|
|
kp: na::Vector3<f32>,
|
|
|
|
|
ki: na::Vector3<f32>,
|
|
|
|
|
kd: na::Vector3<f32>,
|
|
|
|
|
integral: na::Vector3<f32>,
|
|
|
|
|
last_error: na::Vector3<f32>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PidProcessor {
|
|
|
|
|
pub fn new(c: &PidConfig) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
kp: c.p_vec(),
|
|
|
|
|
ki: c.i_vec(),
|
|
|
|
|
kd: c.d_vec(),
|
|
|
|
|
integral: na::Vector3::zeros(),
|
|
|
|
|
last_error: na::Vector3::zeros(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn update(
|
|
|
|
|
&mut self,
|
|
|
|
|
target: na::Vector3<f32>,
|
|
|
|
|
current: na::Vector3<f32>,
|
|
|
|
|
dt: f32,
|
|
|
|
|
) -> na::Vector3<f32> {
|
|
|
|
|
let error = target - current;
|
|
|
|
|
self.integral += error * dt;
|
|
|
|
|
let derivative = (error - self.last_error) / dt;
|
|
|
|
|
self.last_error = error;
|
|
|
|
|
|
|
|
|
|
error.component_mul(&self.kp)
|
|
|
|
|
+ self.integral.component_mul(&self.ki)
|
|
|
|
|
+ derivative.component_mul(&self.kd)
|
|
|
|
|
}
|
|
|
|
|
}
|