imu_fusion/
fusion_quaternion_impl.rs1use core::ops;
2#[allow(unused_imports)]
3use libm::{asinf, atan2f, sqrtf};
4use crate::{Angle, asin_safe, fusion_fast_inverse_sqrt, fusion_radians_to_degrees, FusionEuler, FusionMatrix, FusionQuaternion, FusionVector};
5
6impl FusionQuaternion {
7 pub fn identity() -> Self {
8 const VALUE: FusionQuaternion =
9 FusionQuaternion {
10 w: 1.0f32,
11 x: 0.0f32,
12 y: 0.0f32,
13 z: 0.0f32,
14 };
15 VALUE
16 }
17
18 pub fn normalize(&self) -> Self {
19 #[cfg(feature = "fusion-use-normal-sqrt")]
20 {
21 *self * 1.0f32 / sqrtf(self.w * self.w + self.x * self.x + self.y * self.y + self.z * self.z)
22 }
23 #[cfg(not(feature = "fusion-use-normal-sqrt"))]
24 {
25 *self * fusion_fast_inverse_sqrt(self.w * self.w + self.x * self.x + self.y * self.y + self.z * self.z)
26 }
27 }
28
29 pub fn euler(self) -> FusionEuler {
30 let q = self;
32 let half_minus_qy_squared = 0.5f32 - q.y * q.y;
33 let roll = fusion_radians_to_degrees(atan2f(q.w * q.x + q.y * q.z, half_minus_qy_squared - q.x * q.x));
34 let pitch = fusion_radians_to_degrees(asin_safe(2.0f32 * (q.w * q.y - q.z * q.x)));
35 let yaw = fusion_radians_to_degrees(atan2f(q.w * q.z + q.x * q.y, half_minus_qy_squared - q.z * q.z));
36
37 FusionEuler {
38 angle: Angle {
39 roll,
40 pitch,
41 yaw,
42 }
43 }
44 }
45
46 pub fn rotation(self) -> FusionMatrix {
47 let qwqw = self.w * self.w;
49 let qwqx = self.w * self.x;
50 let qwqy = self.w * self.y;
51 let qwqz = self.w * self.z;
52 let qxqx = self.x * self.x;
53 let qxqy = self.x * self.y;
54 let qxqz = self.x * self.z;
55 let qyqy = self.y * self.y;
56 let qyqz = self.y * self.z;
57 let qzqz = self.z * self.z;
58 FusionMatrix {
59 xx: 2.0f32 * (qwqw - 0.5f32 + qxqx),
60 xy: 2.0f32 * (qxqy - qwqz),
61 xz: 2.0f32 * (qxqz + qwqy),
62 yx: 2.0f32 * (qxqy + qwqz),
63 yy: 2.0f32 * (qwqw - 0.5f32 + qyqy),
64 yz: 2.0f32 * (qyqz - qwqx),
65 zx: 2.0f32 * (qxqz - qwqy),
66 zy: 2.0f32 * (qyqz + qwqx),
67 zz: 2.0f32 * (qwqw - 0.5f32 + qzqz),
68
69 }
70 }
71}
72
73impl ops::Add for FusionQuaternion {
74 type Output = Self;
75
76 fn add(self, rhs: Self) -> Self::Output {
77 Self {
78 w: self.w + rhs.w,
79 x: self.x + rhs.x,
80 y: self.y + rhs.y,
81 z: self.z + rhs.z,
82 }
83 }
84}
85
86impl ops::Mul for FusionQuaternion {
87 type Output = Self;
88
89 fn mul(self, rhs: Self) -> Self::Output {
90 Self {
91 w: self.w * rhs.w - self.x * rhs.x - self.y * rhs.y - self.z * rhs.z,
92 x: self.w * rhs.x + self.x * rhs.w + self.y * rhs.z - self.z * rhs.y,
93 y: self.w * rhs.y - self.x * rhs.z + self.y * rhs.w + self.z * rhs.x,
94 z: self.w * rhs.z + self.x * rhs.y - self.y * rhs.x + self.z * rhs.w,
95 }
96 }
97}
98
99impl ops::Mul<FusionVector> for FusionQuaternion {
100 type Output = Self;
101 fn mul(self, rhs: FusionVector) -> Self::Output {
102 Self {
103 w: -self.x * rhs.x - self.y * rhs.y - self.z * rhs.z,
104 x: self.w * rhs.x + self.y * rhs.z - self.z * rhs.y,
105 y: self.w * rhs.y - self.x * rhs.z + self.z * rhs.x,
106 z: self.w * rhs.z + self.x * rhs.y - self.y * rhs.x,
107 }
108 }
109}
110
111impl ops::Mul<f32> for FusionQuaternion {
112 type Output = Self;
113 fn mul(self, rhs: f32) -> Self::Output {
114 Self {
115 w: self.w * rhs,
116 x: self.x * rhs,
117 y: self.y * rhs,
118 z: self.z * rhs,
119 }
120 }
121}
122