1#![no_std]
2
3mod fusion_vector_impl;
4mod fusion_quaternion_impl;
5mod fusion_matrix_impl;
6mod fusion_euler_impl;
7mod fusion_impl;
8mod fusion_ahrs_impl;
9mod fusion_gyr_offset_impl;
10mod nalgebra;
11
12pub enum FusionConvention {
13 NWU,
15 ENU,
17 NED,
19}
20
21pub struct Fusion {
22 pub gyr_misalignment: FusionMatrix,
23 pub gyr_sensitivity: FusionVector,
24 pub gyr_offset: FusionVector,
25 pub acc_misalignment: FusionMatrix,
26 pub acc_sensitivity: FusionVector,
27 pub acc_offset: FusionVector,
28 pub soft_iron_matrix: FusionMatrix,
29 pub hard_iron_offset: FusionVector,
30 pub ahrs: FusionAhrs,
31 pub offset: FusionGyrOffset,
32 pub last_timestamp: f32,
33}
34
35pub struct FusionAhrs {
36 pub settings: FusionAhrsSettings,
37 pub quaternion: FusionQuaternion,
38 pub acc: FusionVector,
39 pub initialising: bool,
40 pub ramped_gain: f32,
41 pub ramped_gain_step: f32,
42 pub angular_rate_recovery: bool,
43 pub half_accelerometer_feedback: FusionVector,
44 pub half_magnetometer_feedback: FusionVector,
45 pub accelerometer_ignored: bool,
46 pub acceleration_recovery_trigger: i32,
47 pub acceleration_recovery_timeout: i32,
48 pub magnetometer_ignored: bool,
49 pub magnetic_recovery_trigger: i32,
50 pub magnetic_recovery_timeout: i32,
51}
52
53pub struct FusionAhrsSettings {
54 pub convention: FusionConvention,
55 pub gain: f32,
56 pub gyr_range: f32,
57 pub acc_rejection: f32,
58 pub mag_rejection: f32,
59 pub recovery_trigger_period: i32,
60}
61
62pub struct FusionAhrsFlags {
63 pub initializing: bool,
64 pub angular_rate_recovery: bool,
65 pub acceleration_recovery: bool,
66 pub magnetic_recovery: bool,
67}
68
69#[derive(Copy, Clone)]
70pub struct Angle {
71 pub roll: f32,
72 pub pitch: f32,
73 pub yaw: f32,
74}
75
76#[derive(Copy, Clone)]
77#[allow(dead_code)]
78pub struct FusionVector {
79 pub x: f32,
80 pub y: f32,
81 pub z: f32,
82}
83
84#[derive(Copy, Clone)]
85pub struct FusionMatrix {
86 pub xx: f32,
87 pub xy: f32,
88 pub xz: f32,
89 pub yx: f32,
90 pub yy: f32,
91 pub yz: f32,
92 pub zx: f32,
93 pub zy: f32,
94 pub zz: f32,
95}
96
97#[derive(Copy, Clone)]
98pub struct FusionQuaternion {
99 pub w: f32,
100 pub x: f32,
101 pub y: f32,
102 pub z: f32,
103}
104
105#[derive(Copy, Clone)]
106#[allow(dead_code)]
107pub struct FusionEuler {
108 pub angle: Angle,
109}
110
111pub struct FusionGyrOffset {
112 pub filter_coefficient: f32,
113 pub timeout: u32,
114 pub timer: u32,
115 pub gyroscope_offset: FusionVector,
116}
117
118const TIMEOUT: u32 = 5;
120
121const CUTOFF_FREQUENCY: f32 = 0.02f32;
123
124const THRESHOLD: f32 = 3f32;
126
127fn fusion_degrees_to_radians(degrees: f32) -> f32 {
128 degrees * (core::f32::consts::PI / 180.0f32)
129}
130
131fn fusion_radians_to_degrees(radians: f32) -> f32 {
132 radians * (180.0f32 / core::f32::consts::PI)
133}
134
135fn asin_safe(value: f32) -> f32 {
136 use libm::{asinf};
137 if value <= -1.0f32 {
138 return core::f32::consts::PI / -2.0f32;
139 }
140 if value >= 1.0f32 {
141 return core::f32::consts::PI / 2.0f32;
142 }
143 asinf(value)
144}
145
146fn fusion_fast_inverse_sqrt(x: f32) -> f32 {
147 union Union32 {
148 f: f32,
149 i: i32,
150 }
151
152 let mut union32 = Union32 { f: x };
153 unsafe {
154 union32.i = 0x5F1F1412 - (union32.i >> 1);
155 union32.f * (1.69000231f32 - 0.714158168f32 * x * union32.f * union32.f)
156 }
157}
158
159
160#[test]
161fn fusion_fast_inverse_sqrt_test() {
162 use libm::{fabsf};
163 let result = fusion_fast_inverse_sqrt(9.0f32);
164 let actual = 1f32 / result;
165 let expected = 3f32;
166 assert!(fabsf(actual - expected) < 0.01f32);
167}