Skip to main content

rust_gnc/control/
mixer.rs

1//! # Motor Mixing
2//! 
3//! This module implements the "Mixer" logic, which maps normalized control 
4//! signals from the PID controllers to individual motor output levels.
5//! 
6//! This module defines the interface for mapping control demands (Roll, Pitch, Yaw, Throttle)
7//! to physical actuator outputs.
8
9/// Common interface for different airframe geometries.
10pub trait Mixer {
11    /// The specific signal type produced by this mixer (e.g., 4 signals for a quad).
12    type Output;
13
14    /// Maps normalized control demands [-1.0, 1.0] and throttle [0.0, 1.0] to motor signals.
15    fn mix(&self, roll: f32, pitch: f32, yaw: f32, throttle: f32) -> Self::Output;
16}
17
18/// A collection of normalized pulse-width modulation (PWM) signals for 
19/// a quadcopter's Electronic Speed Controllers (ESCs).
20/// 
21/// Range: 0.0 (Stopped) to 1.0 (Full Power).
22#[derive(Debug, PartialEq, Clone, Copy, Default)]
23pub struct QuadMotorSignals {
24    /// Signal for the Front-Left motor.
25    pub front_left: f32,
26    /// Signal for the Front-Right motor.
27    pub front_right: f32,
28    /// Signal for the Rear-Left motor.
29    pub rear_left: f32,
30    /// Signal for the Rear-Right motor.
31    pub rear_right: f32,
32}
33
34/// A stateless utility for calculating motor power distribution.
35pub struct QuadXMixer;
36
37impl Mixer for QuadXMixer {
38    type Output = QuadMotorSignals;
39
40    /// Mixes axis control signals and throttle into individual motor outputs.
41    /// 
42    /// This follows the standard Quad-X mixing matrix. The signs (+/-) for each 
43    /// component are determined by the motor's position relative to the 
44    /// center of mass and its rotational direction.
45    /// 
46    /// ### Parameters
47    /// * `roll` - Normalized roll correction [-1.0, 1.0].
48    /// * `pitch` - Normalized pitch correction [-1.0, 1.0].
49    /// * `yaw` - Normalized yaw correction [-1.0, 1.0].
50    /// * `throttle` - Base power level [0.0, 1.0].
51    /// 
52    /// ### Returns
53    /// A `MotorSignals` struct with values clamped to the safe operating range [0.0, 1.0].
54    fn mix(&self, roll: f32, pitch: f32, yaw: f32, throttle: f32) -> Self::Output {
55        // Mixing Matrix Calculation:
56        // FL = Throttle + Roll + Pitch - Yaw
57        // FR = Throttle - Roll + Pitch + Yaw
58        // RL = Throttle + Roll - Pitch + Yaw
59        // RR = Throttle - Roll - Pitch - Yaw
60        
61        let fl = throttle - roll - pitch - yaw;
62        let fr = throttle + roll - pitch + yaw;
63        let rl = throttle - roll + pitch + yaw;
64        let rr = throttle + roll + pitch - yaw;
65
66        QuadMotorSignals {
67            front_left: fl.clamp(0.0, 1.0),
68            front_right: fr.clamp(0.0, 1.0),
69            rear_left: rl.clamp(0.0, 1.0),
70            rear_right: rr.clamp(0.0, 1.0),
71        }
72    }
73}