Thumbnail

steew/gilgamesh.git

Clone URL: https://git.buni.party/steew/gilgamesh.git

Viewing file on branch master

1use core::ops::{Add, Sub};
2
3use defmt::{info, trace};
4use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, channel::Receiver};
5use mpu6050_dmp::{quaternion::Quaternion, yaw_pitch_roll::YawPitchRoll};
6
7use crate::mpu::BUFFERED_QUATERNIONS;
8
9// represents the motor's possible turning direction (clockwise and counter-clockwise)
10pub enum MotorTurningState {
11 CW,
12 CCW
13}
14
15// holds the motor state, including its angular speed and direction.
16pub struct Motor {
17 angular_rotation_speed: f32,
18 turning: MotorTurningState,
19}
20
21// represents the body's total motor count
22pub const MOTOR_NUM: usize = 4;
23
24// holds the system state for control, including the motor rotation speeds, the current velocity and altitude,
25// and several other data relevant to system control
26pub struct Controller {
27 motors: [Motor; MOTOR_NUM],
28 altitude: f64,
29 velocity: f64,
30 // stores the last reference frame
31 last_frame: YawPitchRoll,
32 // stores the target body attitude desired, from a reference frame
33 attitude: YawPitchRoll
34 // store the last and next quaternion values for the control calculus
35}
36
37pub struct Frame {
38 yaw: f32,
39 pitch: f32,
40 roll: f32
41}
42
43impl Add for Frame {
44 type Output = Self;
45
46 fn add(self, other: Self) -> Self {
47 Self {
48 yaw: self.yaw + other.yaw,
49 pitch: self.pitch + other.pitch,
50 roll: self.roll + other.roll
51 }
52 }
53}
54
55impl Sub for Frame {
56 type Output = Self;
57
58 fn sub(self, other: Self) -> Self {
59 Self {
60 yaw: self.yaw - other.yaw,
61 pitch: self.pitch - other.pitch,
62 roll: self.roll - other.roll
63 }
64 }
65
66}
67
68#[embassy_executor::task]
69pub async fn update_control_loop(
70 quaternion_channel: Receiver<'static, ThreadModeRawMutex, Quaternion, BUFFERED_QUATERNIONS>,
71 target_frame: Option<Frame>,
72) {
73 let mut last_yaw: f32 = 0.0;
74 let mut last_pitch: f32 = 0.0;
75 let mut last_roll: f32 = 0.0;
76
77 const THRESHOLD: f32 = 3.0;
78
79 loop {
80 let next_quaternion_value = quaternion_channel.receive().await;
81 let ypr_format = YawPitchRoll::from(next_quaternion_value);
82
83 let yaw_deg = ypr_format.yaw * 180.0 / core::f32::consts::PI;
84 let pitch_deg = ypr_format.pitch * 180.0 / core::f32::consts::PI;
85 let roll_deg = ypr_format.roll * 180.0 / core::f32::consts::PI;
86
87 let y_diff = yaw_deg - last_yaw;
88 let p_diff = pitch_deg - last_pitch;
89 let r_diff = roll_deg - last_roll;
90
91 // filter the new value and see if it has differed in more than THRESHOLD than the
92 // previous. If not, ignore it.
93 if f32::abs(y_diff) > THRESHOLD
94 || f32::abs(p_diff) > THRESHOLD
95 || f32::abs(r_diff) > THRESHOLD
96 {
97 info!("YPR differential: y:{}, p:{}, r:{}", y_diff, p_diff, r_diff);
98 last_yaw = yaw_deg;
99 last_pitch = pitch_deg;
100 last_roll = roll_deg;
101 }
102 }
103}
104