Skip to main content

veloxity_core/
params.rs

1#![allow(non_camel_case_types)]
2
3pub mod reactions;
4pub mod service;
5
6//=================================================================================
7// 1. Core Data Types
8//=================================================================================
9
10/// An enum representing the value of a parameter.
11#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
12pub enum ParamValue {
13    Float(f32),
14    Int(i32),
15    Uint(u32),
16    Bool(bool),
17}
18
19/// A static definition of a parameter, containing its compile-time metadata.
20pub struct ParamDefinition {
21    pub id: ParamId,
22    pub name: &'static str,
23    pub default: ParamValue,
24}
25
26//=================================================================================
27// 2. The `declare_params!` Macro
28//=================================================================================
29macro_rules! declare_params {
30    (
31        // RustId, NameStr, Type(DefaultValue);
32        $( $rust_id:ident, $name:literal, $type:ident($default:expr); )+
33    ) => {
34        //----------------------------------------------------------------
35        // A. Generate a type-safe enum for parameter identification.
36        //----------------------------------------------------------------
37        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
38        #[repr(u16)]
39        pub enum ParamId {
40            $( $rust_id, )+
41        }
42
43        //----------------------------------------------------------------
44        // A(1.5). Generate a lookup from the id (u16) to the Parameter string...
45        //----------------------------------------------------------------
46        impl ParamId {
47            /// Returns the static string name of the parameter.
48            pub fn as_str(&self) -> &'static str {
49                // This is a safe, direct lookup because the enum order
50                // and the array order are guaranteed to match.
51                PARAM_DEFINITIONS[*self as usize].name
52            }
53
54            /// Returns a parameter ID from its table index.
55            pub fn from_index(index: usize) -> Option<Self> {
56                PARAM_DEFINITIONS.get(index).map(|definition| definition.id)
57            }
58        }
59
60        //----------------------------------------------------------------
61        // B. Define a compile-time constant for the number of parameters.
62        //----------------------------------------------------------------
63        pub const PARAMS_COUNT: usize = $( {let _ = stringify!($rust_id); 1} + )+ 0;
64
65        //----------------------------------------------------------------
66        // C. Generate a static array of parameter definitions.
67        //----------------------------------------------------------------
68        pub static PARAM_DEFINITIONS: [ParamDefinition; PARAMS_COUNT] = [
69            $(
70                ParamDefinition {
71                    id: ParamId::$rust_id,
72                    name: $name,
73                    default: ParamValue::$type($default),
74                },
75            )+
76        ];
77
78        //----------------------------------------------------------------
79        // D. The main `Params` struct holding runtime values.
80        //----------------------------------------------------------------
81        #[derive(Copy, Clone)]
82        pub struct Params {
83            values: [ParamValue; PARAMS_COUNT],
84        }
85
86        impl Params {
87            /// Creates a new `Params` instance and initializes it with default values.
88            pub fn new() -> Self {
89                let mut params = Self {
90                    values: [ParamValue::Int(0); PARAMS_COUNT],
91                };
92                params.set_defaults();
93                params
94            }
95
96            /// Resets all parameters to their default values.
97            pub fn set_defaults(&mut self) {
98                for def in PARAM_DEFINITIONS.iter() {
99                    self.values[def.id as usize] = def.default;
100                }
101            }
102
103            /// Gets a parameter's value by its type-safe ID. Returns a copy.
104            pub fn get_by_id(&self, id: ParamId) -> ParamValue {
105                self.values[id as usize]
106            }
107
108            /// Sets a parameter's value by its type-safe ID.
109            pub fn set_by_id(&mut self, id: ParamId, value: ParamValue) {
110                self.values[id as usize] = value;
111            }
112
113            /// Gets a parameter's value by its string name. Returns `None` if not found.
114            pub fn get_by_name(&self, name: &str) -> Option<ParamValue> {
115                PARAM_DEFINITIONS.iter().find(|d| d.name == name).map(|def| self.get_by_id(def.id))
116            }
117
118            /// Sets a parameter's value by its string name. Returns `true` on success.
119            pub fn set_by_name(&mut self, name: &str, value: ParamValue) -> bool {
120                if let Some(def) = PARAM_DEFINITIONS.iter().find(|d| d.name == name) {
121                    self.set_by_id(def.id, value);
122                    true
123                } else {
124                    false
125                }
126            }
127        }
128
129        impl Default for Params {
130            fn default() -> Self {
131                Self::new()
132            }
133        }
134    };
135}
136
137//=================================================================================
138// 3. Parameter Definitions
139//=================================================================================
140declare_params! {
141    // RustId, Name, Type(Default);
142    PARAM_BAUD_RATE, "BAUD_RATE", Int(921600);
143    PARAM_SERIAL_DEVICE, "SERIAL_DEVICE", Int(0);
144    PARAM_NUM_MOTORS, "NUM_MOTORS", Int(4);
145    PARAM_MOTOR_RESISTANCE, "MOTOR_RESISTANCE", Float(0.042);
146    PARAM_MOTOR_KV, "MOTOR_KV", Float(0.01706);
147    PARAM_NO_LOAD_CURRENT, "NO_LOAD_CURRENT", Float(1.5);
148    PARAM_PROP_DIAMETER, "PROP_DIAMETER", Float(0.381);
149    PARAM_PROP_CT, "PROP_CT", Float(0.075);
150    PARAM_PROP_CQ, "PROP_CQ", Float(0.0045);
151    PARAM_VOLT_MAX, "BATT_VOLT_MAX", Float(25.0);
152    PARAM_USE_MOTOR_PARAMETERS, "USE_MOTOR_PARAM", Int(0);
153    PARAM_PRIMARY_MIXER_OUTPUT_0, "PRI_MIXER_OUT_0", Int(0);
154    PARAM_PRIMARY_MIXER_OUTPUT_1, "PRI_MIXER_OUT_1", Int(0);
155    PARAM_PRIMARY_MIXER_OUTPUT_2, "PRI_MIXER_OUT_2", Int(0);
156    PARAM_PRIMARY_MIXER_OUTPUT_3, "PRI_MIXER_OUT_3", Int(0);
157    PARAM_PRIMARY_MIXER_OUTPUT_4, "PRI_MIXER_OUT_4", Int(0);
158    PARAM_PRIMARY_MIXER_OUTPUT_5, "PRI_MIXER_OUT_5", Int(0);
159    PARAM_PRIMARY_MIXER_OUTPUT_6, "PRI_MIXER_OUT_6", Int(0);
160    PARAM_PRIMARY_MIXER_OUTPUT_7, "PRI_MIXER_OUT_7", Int(0);
161    PARAM_PRIMARY_MIXER_OUTPUT_8, "PRI_MIXER_OUT_8", Int(0);
162    PARAM_PRIMARY_MIXER_OUTPUT_9, "PRI_MIXER_OUT_9", Int(0);
163    PARAM_PRIMARY_MIXER_PWM_RATE_0, "PRI_MIXER_PWM_0", Float(0.0);
164    PARAM_PRIMARY_MIXER_PWM_RATE_1, "PRI_MIXER_PWM_1", Float(0.0);
165    PARAM_PRIMARY_MIXER_PWM_RATE_2, "PRI_MIXER_PWM_2", Float(0.0);
166    PARAM_PRIMARY_MIXER_PWM_RATE_3, "PRI_MIXER_PWM_3", Float(0.0);
167    PARAM_PRIMARY_MIXER_PWM_RATE_4, "PRI_MIXER_PWM_4", Float(0.0);
168    PARAM_PRIMARY_MIXER_PWM_RATE_5, "PRI_MIXER_PWM_5", Float(0.0);
169    PARAM_PRIMARY_MIXER_PWM_RATE_6, "PRI_MIXER_PWM_6", Float(0.0);
170    PARAM_PRIMARY_MIXER_PWM_RATE_7, "PRI_MIXER_PWM_7", Float(0.0);
171    PARAM_PRIMARY_MIXER_PWM_RATE_8, "PRI_MIXER_PWM_8", Float(0.0);
172    PARAM_PRIMARY_MIXER_PWM_RATE_9, "PRI_MIXER_PWM_9", Float(0.0);
173    PARAM_PRIMARY_MIXER_0_0, "PRI_MIXER_0_0", Float(0.0);
174    PARAM_PRIMARY_MIXER_1_0, "PRI_MIXER_1_0", Float(0.0);
175    PARAM_PRIMARY_MIXER_2_0, "PRI_MIXER_2_0", Float(0.0);
176    PARAM_PRIMARY_MIXER_3_0, "PRI_MIXER_3_0", Float(0.0);
177    PARAM_PRIMARY_MIXER_4_0, "PRI_MIXER_4_0", Float(0.0);
178    PARAM_PRIMARY_MIXER_5_0, "PRI_MIXER_5_0", Float(0.0);
179    PARAM_PRIMARY_MIXER_6_0, "PRI_MIXER_6_0", Float(0.0);
180    PARAM_PRIMARY_MIXER_7_0, "PRI_MIXER_7_0", Float(0.0);
181    PARAM_PRIMARY_MIXER_8_0, "PRI_MIXER_8_0", Float(0.0);
182    PARAM_PRIMARY_MIXER_9_0, "PRI_MIXER_9_0", Float(0.0);
183    PARAM_PRIMARY_MIXER_0_1, "PRI_MIXER_0_1", Float(0.0);
184    PARAM_PRIMARY_MIXER_1_1, "PRI_MIXER_1_1", Float(0.0);
185    PARAM_PRIMARY_MIXER_2_1, "PRI_MIXER_2_1", Float(0.0);
186    PARAM_PRIMARY_MIXER_3_1, "PRI_MIXER_3_1", Float(0.0);
187    PARAM_PRIMARY_MIXER_4_1, "PRI_MIXER_4_1", Float(0.0);
188    PARAM_PRIMARY_MIXER_5_1, "PRI_MIXER_5_1", Float(0.0);
189    PARAM_PRIMARY_MIXER_6_1, "PRI_MIXER_6_1", Float(0.0);
190    PARAM_PRIMARY_MIXER_7_1, "PRI_MIXER_7_1", Float(0.0);
191    PARAM_PRIMARY_MIXER_8_1, "PRI_MIXER_8_1", Float(0.0);
192    PARAM_PRIMARY_MIXER_9_1, "PRI_MIXER_9_1", Float(0.0);
193    PARAM_PRIMARY_MIXER_0_2, "PRI_MIXER_0_2", Float(0.0);
194    PARAM_PRIMARY_MIXER_1_2, "PRI_MIXER_1_2", Float(0.0);
195    PARAM_PRIMARY_MIXER_2_2, "PRI_MIXER_2_2", Float(0.0);
196    PARAM_PRIMARY_MIXER_3_2, "PRI_MIXER_3_2", Float(0.0);
197    PARAM_PRIMARY_MIXER_4_2, "PRI_MIXER_4_2", Float(0.0);
198    PARAM_PRIMARY_MIXER_5_2, "PRI_MIXER_5_2", Float(0.0);
199    PARAM_PRIMARY_MIXER_6_2, "PRI_MIXER_6_2", Float(0.0);
200    PARAM_PRIMARY_MIXER_7_2, "PRI_MIXER_7_2", Float(0.0);
201    PARAM_PRIMARY_MIXER_8_2, "PRI_MIXER_8_2", Float(0.0);
202    PARAM_PRIMARY_MIXER_9_2, "PRI_MIXER_9_2", Float(0.0);
203    PARAM_PRIMARY_MIXER_0_3, "PRI_MIXER_0_3", Float(0.0);
204    PARAM_PRIMARY_MIXER_1_3, "PRI_MIXER_1_3", Float(0.0);
205    PARAM_PRIMARY_MIXER_2_3, "PRI_MIXER_2_3", Float(0.0);
206    PARAM_PRIMARY_MIXER_3_3, "PRI_MIXER_3_3", Float(0.0);
207    PARAM_PRIMARY_MIXER_4_3, "PRI_MIXER_4_3", Float(0.0);
208    PARAM_PRIMARY_MIXER_5_3, "PRI_MIXER_5_3", Float(0.0);
209    PARAM_PRIMARY_MIXER_6_3, "PRI_MIXER_6_3", Float(0.0);
210    PARAM_PRIMARY_MIXER_7_3, "PRI_MIXER_7_3", Float(0.0);
211    PARAM_PRIMARY_MIXER_8_3, "PRI_MIXER_8_3", Float(0.0);
212    PARAM_PRIMARY_MIXER_9_3, "PRI_MIXER_9_3", Float(0.0);
213    PARAM_PRIMARY_MIXER_0_4, "PRI_MIXER_0_4", Float(0.0);
214    PARAM_PRIMARY_MIXER_1_4, "PRI_MIXER_1_4", Float(0.0);
215    PARAM_PRIMARY_MIXER_2_4, "PRI_MIXER_2_4", Float(0.0);
216    PARAM_PRIMARY_MIXER_3_4, "PRI_MIXER_3_4", Float(0.0);
217    PARAM_PRIMARY_MIXER_4_4, "PRI_MIXER_4_4", Float(0.0);
218    PARAM_PRIMARY_MIXER_5_4, "PRI_MIXER_5_4", Float(0.0);
219    PARAM_PRIMARY_MIXER_6_4, "PRI_MIXER_6_4", Float(0.0);
220    PARAM_PRIMARY_MIXER_7_4, "PRI_MIXER_7_4", Float(0.0);
221    PARAM_PRIMARY_MIXER_8_4, "PRI_MIXER_8_4", Float(0.0);
222    PARAM_PRIMARY_MIXER_9_4, "PRI_MIXER_9_4", Float(0.0);
223    PARAM_PRIMARY_MIXER_0_5, "PRI_MIXER_0_5", Float(0.0);
224    PARAM_PRIMARY_MIXER_1_5, "PRI_MIXER_1_5", Float(0.0);
225    PARAM_PRIMARY_MIXER_2_5, "PRI_MIXER_2_5", Float(0.0);
226    PARAM_PRIMARY_MIXER_3_5, "PRI_MIXER_3_5", Float(0.0);
227    PARAM_PRIMARY_MIXER_4_5, "PRI_MIXER_4_5", Float(0.0);
228    PARAM_PRIMARY_MIXER_5_5, "PRI_MIXER_5_5", Float(0.0);
229    PARAM_PRIMARY_MIXER_6_5, "PRI_MIXER_6_5", Float(0.0);
230    PARAM_PRIMARY_MIXER_7_5, "PRI_MIXER_7_5", Float(0.0);
231    PARAM_PRIMARY_MIXER_8_5, "PRI_MIXER_8_5", Float(0.0);
232    PARAM_PRIMARY_MIXER_9_5, "PRI_MIXER_9_5", Float(0.0);
233    PARAM_PRIMARY_MIXER_0_6, "PRI_MIXER_0_6", Float(0.0);
234    PARAM_PRIMARY_MIXER_1_6, "PRI_MIXER_1_6", Float(0.0);
235    PARAM_PRIMARY_MIXER_2_6, "PRI_MIXER_2_6", Float(0.0);
236    PARAM_PRIMARY_MIXER_3_6, "PRI_MIXER_3_6", Float(0.0);
237    PARAM_PRIMARY_MIXER_4_6, "PRI_MIXER_4_6", Float(0.0);
238    PARAM_PRIMARY_MIXER_5_6, "PRI_MIXER_5_6", Float(0.0);
239    PARAM_PRIMARY_MIXER_6_6, "PRI_MIXER_6_6", Float(0.0);
240    PARAM_PRIMARY_MIXER_7_6, "PRI_MIXER_7_6", Float(0.0);
241    PARAM_PRIMARY_MIXER_8_6, "PRI_MIXER_8_6", Float(0.0);
242    PARAM_PRIMARY_MIXER_9_6, "PRI_MIXER_9_6", Float(0.0);
243    PARAM_PRIMARY_MIXER_0_7, "PRI_MIXER_0_7", Float(0.0);
244    PARAM_PRIMARY_MIXER_1_7, "PRI_MIXER_1_7", Float(0.0);
245    PARAM_PRIMARY_MIXER_2_7, "PRI_MIXER_2_7", Float(0.0);
246    PARAM_PRIMARY_MIXER_3_7, "PRI_MIXER_3_7", Float(0.0);
247    PARAM_PRIMARY_MIXER_4_7, "PRI_MIXER_4_7", Float(0.0);
248    PARAM_PRIMARY_MIXER_5_7, "PRI_MIXER_5_7", Float(0.0);
249    PARAM_PRIMARY_MIXER_6_7, "PRI_MIXER_6_7", Float(0.0);
250    PARAM_PRIMARY_MIXER_7_7, "PRI_MIXER_7_7", Float(0.0);
251    PARAM_PRIMARY_MIXER_8_7, "PRI_MIXER_8_7", Float(0.0);
252    PARAM_PRIMARY_MIXER_9_7, "PRI_MIXER_9_7", Float(0.0);
253    PARAM_PRIMARY_MIXER_0_8, "PRI_MIXER_0_8", Float(0.0);
254    PARAM_PRIMARY_MIXER_1_8, "PRI_MIXER_1_8", Float(0.0);
255    PARAM_PRIMARY_MIXER_2_8, "PRI_MIXER_2_8", Float(0.0);
256    PARAM_PRIMARY_MIXER_3_8, "PRI_MIXER_3_8", Float(0.0);
257    PARAM_PRIMARY_MIXER_4_8, "PRI_MIXER_4_8", Float(0.0);
258    PARAM_PRIMARY_MIXER_5_8, "PRI_MIXER_5_8", Float(0.0);
259    PARAM_PRIMARY_MIXER_6_8, "PRI_MIXER_6_8", Float(0.0);
260    PARAM_PRIMARY_MIXER_7_8, "PRI_MIXER_7_8", Float(0.0);
261    PARAM_PRIMARY_MIXER_8_8, "PRI_MIXER_8_8", Float(0.0);
262    PARAM_PRIMARY_MIXER_9_8, "PRI_MIXER_9_8", Float(0.0);
263    PARAM_PRIMARY_MIXER_0_9, "PRI_MIXER_0_9", Float(0.0);
264    PARAM_PRIMARY_MIXER_1_9, "PRI_MIXER_1_9", Float(0.0);
265    PARAM_PRIMARY_MIXER_2_9, "PRI_MIXER_2_9", Float(0.0);
266    PARAM_PRIMARY_MIXER_3_9, "PRI_MIXER_3_9", Float(0.0);
267    PARAM_PRIMARY_MIXER_4_9, "PRI_MIXER_4_9", Float(0.0);
268    PARAM_PRIMARY_MIXER_5_9, "PRI_MIXER_5_9", Float(0.0);
269    PARAM_PRIMARY_MIXER_6_9, "PRI_MIXER_6_9", Float(0.0);
270    PARAM_PRIMARY_MIXER_7_9, "PRI_MIXER_7_9", Float(0.0);
271    PARAM_PRIMARY_MIXER_8_9, "PRI_MIXER_8_9", Float(0.0);
272    PARAM_PRIMARY_MIXER_9_9, "PRI_MIXER_9_9", Float(0.0);
273    PARAM_SECONDARY_MIXER_0_0, "SEC_MIXER_0_0", Float(0.0);
274    PARAM_SECONDARY_MIXER_1_0, "SEC_MIXER_1_0", Float(0.0);
275    PARAM_SECONDARY_MIXER_2_0, "SEC_MIXER_2_0", Float(0.0);
276    PARAM_SECONDARY_MIXER_3_0, "SEC_MIXER_3_0", Float(0.0);
277    PARAM_SECONDARY_MIXER_4_0, "SEC_MIXER_4_0", Float(0.0);
278    PARAM_SECONDARY_MIXER_5_0, "SEC_MIXER_5_0", Float(0.0);
279    PARAM_SECONDARY_MIXER_6_0, "SEC_MIXER_6_0", Float(0.0);
280    PARAM_SECONDARY_MIXER_7_0, "SEC_MIXER_7_0", Float(0.0);
281    PARAM_SECONDARY_MIXER_8_0, "SEC_MIXER_8_0", Float(0.0);
282    PARAM_SECONDARY_MIXER_9_0, "SEC_MIXER_9_0", Float(0.0);
283    PARAM_SECONDARY_MIXER_0_1, "SEC_MIXER_0_1", Float(0.0);
284    PARAM_SECONDARY_MIXER_1_1, "SEC_MIXER_1_1", Float(0.0);
285    PARAM_SECONDARY_MIXER_2_1, "SEC_MIXER_2_1", Float(0.0);
286    PARAM_SECONDARY_MIXER_3_1, "SEC_MIXER_3_1", Float(0.0);
287    PARAM_SECONDARY_MIXER_4_1, "SEC_MIXER_4_1", Float(0.0);
288    PARAM_SECONDARY_MIXER_5_1, "SEC_MIXER_5_1", Float(0.0);
289    PARAM_SECONDARY_MIXER_6_1, "SEC_MIXER_6_1", Float(0.0);
290    PARAM_SECONDARY_MIXER_7_1, "SEC_MIXER_7_1", Float(0.0);
291    PARAM_SECONDARY_MIXER_8_1, "SEC_MIXER_8_1", Float(0.0);
292    PARAM_SECONDARY_MIXER_9_1, "SEC_MIXER_9_1", Float(0.0);
293    PARAM_SECONDARY_MIXER_0_2, "SEC_MIXER_0_2", Float(0.0);
294    PARAM_SECONDARY_MIXER_1_2, "SEC_MIXER_1_2", Float(0.0);
295    PARAM_SECONDARY_MIXER_2_2, "SEC_MIXER_2_2", Float(0.0);
296    PARAM_SECONDARY_MIXER_3_2, "SEC_MIXER_3_2", Float(0.0);
297    PARAM_SECONDARY_MIXER_4_2, "SEC_MIXER_4_2", Float(0.0);
298    PARAM_SECONDARY_MIXER_5_2, "SEC_MIXER_5_2", Float(0.0);
299    PARAM_SECONDARY_MIXER_6_2, "SEC_MIXER_6_2", Float(0.0);
300    PARAM_SECONDARY_MIXER_7_2, "SEC_MIXER_7_2", Float(0.0);
301    PARAM_SECONDARY_MIXER_8_2, "SEC_MIXER_8_2", Float(0.0);
302    PARAM_SECONDARY_MIXER_9_2, "SEC_MIXER_9_2", Float(0.0);
303    PARAM_SECONDARY_MIXER_0_3, "SEC_MIXER_0_3", Float(0.0);
304    PARAM_SECONDARY_MIXER_1_3, "SEC_MIXER_1_3", Float(0.0);
305    PARAM_SECONDARY_MIXER_2_3, "SEC_MIXER_2_3", Float(0.0);
306    PARAM_SECONDARY_MIXER_3_3, "SEC_MIXER_3_3", Float(0.0);
307    PARAM_SECONDARY_MIXER_4_3, "SEC_MIXER_4_3", Float(0.0);
308    PARAM_SECONDARY_MIXER_5_3, "SEC_MIXER_5_3", Float(0.0);
309    PARAM_SECONDARY_MIXER_6_3, "SEC_MIXER_6_3", Float(0.0);
310    PARAM_SECONDARY_MIXER_7_3, "SEC_MIXER_7_3", Float(0.0);
311    PARAM_SECONDARY_MIXER_8_3, "SEC_MIXER_8_3", Float(0.0);
312    PARAM_SECONDARY_MIXER_9_3, "SEC_MIXER_9_3", Float(0.0);
313    PARAM_SECONDARY_MIXER_0_4, "SEC_MIXER_0_4", Float(0.0);
314    PARAM_SECONDARY_MIXER_1_4, "SEC_MIXER_1_4", Float(0.0);
315    PARAM_SECONDARY_MIXER_2_4, "SEC_MIXER_2_4", Float(0.0);
316    PARAM_SECONDARY_MIXER_3_4, "SEC_MIXER_3_4", Float(0.0);
317    PARAM_SECONDARY_MIXER_4_4, "SEC_MIXER_4_4", Float(0.0);
318    PARAM_SECONDARY_MIXER_5_4, "SEC_MIXER_5_4", Float(0.0);
319    PARAM_SECONDARY_MIXER_6_4, "SEC_MIXER_6_4", Float(0.0);
320    PARAM_SECONDARY_MIXER_7_4, "SEC_MIXER_7_4", Float(0.0);
321    PARAM_SECONDARY_MIXER_8_4, "SEC_MIXER_8_4", Float(0.0);
322    PARAM_SECONDARY_MIXER_9_4, "SEC_MIXER_9_4", Float(0.0);
323    PARAM_SECONDARY_MIXER_0_5, "SEC_MIXER_0_5", Float(0.0);
324    PARAM_SECONDARY_MIXER_1_5, "SEC_MIXER_1_5", Float(0.0);
325    PARAM_SECONDARY_MIXER_2_5, "SEC_MIXER_2_5", Float(0.0);
326    PARAM_SECONDARY_MIXER_3_5, "SEC_MIXER_3_5", Float(0.0);
327    PARAM_SECONDARY_MIXER_4_5, "SEC_MIXER_4_5", Float(0.0);
328    PARAM_SECONDARY_MIXER_5_5, "SEC_MIXER_5_5", Float(0.0);
329    PARAM_SECONDARY_MIXER_6_5, "SEC_MIXER_6_5", Float(0.0);
330    PARAM_SECONDARY_MIXER_7_5, "SEC_MIXER_7_5", Float(0.0);
331    PARAM_SECONDARY_MIXER_8_5, "SEC_MIXER_8_5", Float(0.0);
332    PARAM_SECONDARY_MIXER_9_5, "SEC_MIXER_9_5", Float(0.0);
333    PARAM_SECONDARY_MIXER_0_6, "SEC_MIXER_0_6", Float(0.0);
334    PARAM_SECONDARY_MIXER_1_6, "SEC_MIXER_1_6", Float(0.0);
335    PARAM_SECONDARY_MIXER_2_6, "SEC_MIXER_2_6", Float(0.0);
336    PARAM_SECONDARY_MIXER_3_6, "SEC_MIXER_3_6", Float(0.0);
337    PARAM_SECONDARY_MIXER_4_6, "SEC_MIXER_4_6", Float(0.0);
338    PARAM_SECONDARY_MIXER_5_6, "SEC_MIXER_5_6", Float(0.0);
339    PARAM_SECONDARY_MIXER_6_6, "SEC_MIXER_6_6", Float(0.0);
340    PARAM_SECONDARY_MIXER_7_6, "SEC_MIXER_7_6", Float(0.0);
341    PARAM_SECONDARY_MIXER_8_6, "SEC_MIXER_8_6", Float(0.0);
342    PARAM_SECONDARY_MIXER_9_6, "SEC_MIXER_9_6", Float(0.0);
343    PARAM_SECONDARY_MIXER_0_7, "SEC_MIXER_0_7", Float(0.0);
344    PARAM_SECONDARY_MIXER_1_7, "SEC_MIXER_1_7", Float(0.0);
345    PARAM_SECONDARY_MIXER_2_7, "SEC_MIXER_2_7", Float(0.0);
346    PARAM_SECONDARY_MIXER_3_7, "SEC_MIXER_3_7", Float(0.0);
347    PARAM_SECONDARY_MIXER_4_7, "SEC_MIXER_4_7", Float(0.0);
348    PARAM_SECONDARY_MIXER_5_7, "SEC_MIXER_5_7", Float(0.0);
349    PARAM_SECONDARY_MIXER_6_7, "SEC_MIXER_6_7", Float(0.0);
350    PARAM_SECONDARY_MIXER_7_7, "SEC_MIXER_7_7", Float(0.0);
351    PARAM_SECONDARY_MIXER_8_7, "SEC_MIXER_8_7", Float(0.0);
352    PARAM_SECONDARY_MIXER_9_7, "SEC_MIXER_9_7", Float(0.0);
353    PARAM_SECONDARY_MIXER_0_8, "SEC_MIXER_0_8", Float(0.0);
354    PARAM_SECONDARY_MIXER_1_8, "SEC_MIXER_1_8", Float(0.0);
355    PARAM_SECONDARY_MIXER_2_8, "SEC_MIXER_2_8", Float(0.0);
356    PARAM_SECONDARY_MIXER_3_8, "SEC_MIXER_3_8", Float(0.0);
357    PARAM_SECONDARY_MIXER_4_8, "SEC_MIXER_4_8", Float(0.0);
358    PARAM_SECONDARY_MIXER_5_8, "SEC_MIXER_5_8", Float(0.0);
359    PARAM_SECONDARY_MIXER_6_8, "SEC_MIXER_6_8", Float(0.0);
360    PARAM_SECONDARY_MIXER_7_8, "SEC_MIXER_7_8", Float(0.0);
361    PARAM_SECONDARY_MIXER_8_8, "SEC_MIXER_8_8", Float(0.0);
362    PARAM_SECONDARY_MIXER_9_8, "SEC_MIXER_9_8", Float(0.0);
363    PARAM_SECONDARY_MIXER_0_9, "SEC_MIXER_0_9", Float(0.0);
364    PARAM_SECONDARY_MIXER_1_9, "SEC_MIXER_1_9", Float(0.0);
365    PARAM_SECONDARY_MIXER_2_9, "SEC_MIXER_2_9", Float(0.0);
366    PARAM_SECONDARY_MIXER_3_9, "SEC_MIXER_3_9", Float(0.0);
367    PARAM_SECONDARY_MIXER_4_9, "SEC_MIXER_4_9", Float(0.0);
368    PARAM_SECONDARY_MIXER_5_9, "SEC_MIXER_5_9", Float(0.0);
369    PARAM_SECONDARY_MIXER_6_9, "SEC_MIXER_6_9", Float(0.0);
370    PARAM_SECONDARY_MIXER_7_9, "SEC_MIXER_7_9", Float(0.0);
371    PARAM_SECONDARY_MIXER_8_9, "SEC_MIXER_8_9", Float(0.0);
372    PARAM_SECONDARY_MIXER_9_9, "SEC_MIXER_9_9", Float(0.0);
373    PARAM_SYSTEM_ID, "SYS_ID", Int(1);
374    PARAM_PID_ROLL_RATE_P, "PID_ROLL_RATE_P", Float(0.070);
375    PARAM_PID_ROLL_RATE_I, "PID_ROLL_RATE_I", Float(0.0);
376    PARAM_PID_ROLL_RATE_D, "PID_ROLL_RATE_D", Float(0.0);
377    PARAM_PID_PITCH_RATE_P, "PID_PITCH_RATE_P", Float(0.070);
378    PARAM_PID_PITCH_RATE_I, "PID_PITCH_RATE_I", Float(0.0);
379    PARAM_PID_PITCH_RATE_D, "PID_PITCH_RATE_D", Float(0.0);
380    PARAM_PID_YAW_RATE_P, "PID_YAW_RATE_P", Float(0.25);
381    PARAM_PID_YAW_RATE_I, "PID_YAW_RATE_I", Float(0.0);
382    PARAM_PID_YAW_RATE_D, "PID_YAW_RATE_D", Float(0.0);
383    PARAM_PID_ROLL_ANGLE_P, "PID_ROLL_ANG_P", Float(0.15);
384    PARAM_PID_ROLL_ANGLE_I, "PID_ROLL_ANG_I", Float(0.0);
385    PARAM_PID_ROLL_ANGLE_D, "PID_ROLL_ANG_D", Float(0.05);
386    PARAM_PID_PITCH_ANGLE_P, "PID_PITCH_ANG_P", Float(0.15);
387    PARAM_PID_PITCH_ANGLE_I, "PID_PITCH_ANG_I", Float(0.0);
388    PARAM_PID_PITCH_ANGLE_D, "PID_PITCH_ANG_D", Float(0.05);
389    PARAM_X_EQ_TORQUE, "X_EQ_TORQUE", Float(0.0);
390    PARAM_Y_EQ_TORQUE, "Y_EQ_TORQUE", Float(0.0);
391    PARAM_Z_EQ_TORQUE, "Z_EQ_TORQUE", Float(0.0);
392    PARAM_PID_TAU, "PID_TAU", Float(0.05);
393    PARAM_MOTOR_IDLE_THROTTLE, "MOTOR_IDLE_THR", Float(0.1);
394    PARAM_FAILSAFE_THROTTLE, "FAILSAFE_THR", Float(-1.0);
395    PARAM_SPIN_MOTORS_WHEN_ARMED, "ARM_SPIN_MOTORS", Int(1);
396    // Physical output-channel allow mask. Bit N controls channel N regardless
397    // of whether the mixer labels it as a motor, servo, GPIO, or auxiliary
398    // output. Zero is also a global hardware-output inhibit.
399    PARAM_CHANNEL_OUTPUT_MASK, "CHN_OUTPUT_MASK", Int(-1);
400    PARAM_INIT_TIME, "FILT_INIT_T", Int(3000);
401    PARAM_FILTER_KP_ACC, "FILT_ACC_KP", Float(0.5);
402    PARAM_FILTER_KI, "FILT_KI", Float(0.01);
403    PARAM_FILTER_KP_EXT, "FILT_EXT_KP", Float(1.5);
404    PARAM_FILTER_ACCEL_MARGIN, "FILT_ACC_MARGIN", Float(0.1);
405    PARAM_FILTER_USE_QUAD_INT, "FILT_QUAD_INT", Int(1);
406    PARAM_FILTER_USE_MAT_EXP, "FILT_MAT_EXP", Int(1);
407    PARAM_FILTER_USE_ACC, "FILT_USE_ACC", Int(1);
408    PARAM_CALIBRATE_GYRO_ON_ARM, "ARM_CAL_GYRO", Int(0);
409    PARAM_GYRO_XY_ALPHA, "GYRO_XY_LPF", Float(0.3);
410    PARAM_GYRO_Z_ALPHA, "GYRO_Z_LPF", Float(0.3);
411    PARAM_ACC_ALPHA, "ACC_LPF", Float(0.5);
412    PARAM_GYRO_X_BIAS, "GYRO_X_BIAS", Float(0.0);
413    PARAM_GYRO_Y_BIAS, "GYRO_Y_BIAS", Float(0.0);
414    PARAM_GYRO_Z_BIAS, "GYRO_Z_BIAS", Float(0.0);
415    PARAM_ACC_X_BIAS, "ACC_X_BIAS", Float(0.0);
416    PARAM_ACC_Y_BIAS, "ACC_Y_BIAS", Float(0.0);
417    PARAM_ACC_Z_BIAS, "ACC_Z_BIAS", Float(0.0);
418    PARAM_ACC_X_TEMP_COMP, "ACC_X_TEMP_COMP", Float(0.0);
419    PARAM_ACC_Y_TEMP_COMP, "ACC_Y_TEMP_COMP", Float(0.0);
420    PARAM_ACC_Z_TEMP_COMP, "ACC_Z_TEMP_COMP", Float(0.0);
421    PARAM_MAG_A00_COMP, "MAG_CAL_A00", Float(1.0);
422    PARAM_MAG_A01_COMP, "MAG_CAL_A01", Float(0.0);
423    PARAM_MAG_A02_COMP, "MAG_CAL_A02", Float(0.0);
424    PARAM_MAG_A10_COMP, "MAG_CAL_A10", Float(0.0);
425    PARAM_MAG_A11_COMP, "MAG_CAL_A11", Float(1.0);
426    PARAM_MAG_A12_COMP, "MAG_CAL_A12", Float(0.0);
427    PARAM_MAG_A20_COMP, "MAG_CAL_A20", Float(0.0);
428    PARAM_MAG_A21_COMP, "MAG_CAL_A21", Float(0.0);
429    PARAM_MAG_A22_COMP, "MAG_CAL_A22", Float(1.0);
430    PARAM_MAG_X_BIAS, "MAG_X_BIAS", Float(0.0);
431    PARAM_MAG_Y_BIAS, "MAG_Y_BIAS", Float(0.0);
432    PARAM_MAG_Z_BIAS, "MAG_Z_BIAS", Float(0.0);
433    PARAM_BARO_BIAS, "BARO_BIAS", Float(0.0);
434    PARAM_GROUND_LEVEL, "GROUND_LEVEL", Float(1387.0);
435    PARAM_DIFF_PRESS_BIAS, "DIFF_PRESS_BIAS", Float(0.0);
436    PARAM_RC_TYPE, "RC_TYPE", Int(0);
437    PARAM_RC_X_CHANNEL, "RC_X_CHN", Int(0);
438    PARAM_RC_Y_CHANNEL, "RC_Y_CHN", Int(1);
439    PARAM_RC_Z_CHANNEL, "RC_Z_CHN", Int(3);
440    PARAM_RC_F_CHANNEL, "RC_F_CHN", Int(2);
441    PARAM_RC_F_AXIS, "RC_F_AXIS", Int(2);
442    PARAM_RC_ATTITUDE_OVERRIDE_CHANNEL, "RC_ATT_OVRD_CHN", Int(4);
443    PARAM_RC_THROTTLE_OVERRIDE_CHANNEL, "RC_THR_OVRD_CHN", Int(4);
444    PARAM_RC_ATT_CONTROL_TYPE_CHANNEL, "RC_ATT_CTRL_CHN", Int(-1);
445    PARAM_RC_ARM_CHANNEL, "RC_ARM_CHN", Int(-1);
446    PARAM_RC_NUM_CHANNELS, "RC_NUM_CHN", Int(6);
447    PARAM_RC_SWITCH_5_DIRECTION, "SWITCH_5_DIR", Int(1);
448    PARAM_RC_SWITCH_6_DIRECTION, "SWITCH_6_DIR", Int(1);
449    PARAM_RC_SWITCH_7_DIRECTION, "SWITCH_7_DIR", Int(1);
450    PARAM_RC_SWITCH_8_DIRECTION, "SWITCH_8_DIR", Int(1);
451    PARAM_RC_OVERRIDE_DEVIATION, "RC_OVRD_DEV", Float(0.1);
452    PARAM_OVERRIDE_LAG_TIME, "RC_OVRD_LAG_T", Int(1000);
453    PARAM_RC_OVERRIDE_TAKE_MIN_THROTTLE, "TAKE_MIN_THR", Int(1);
454    PARAM_RC_MAX_THROTTLE, "RC_MAX_THR", Float(0.7);
455    PARAM_RC_ATTITUDE_MODE, "RC_ATT_MODE", Int(1);
456    PARAM_ALLOW_UNHEALTHY_ESTIMATOR, "BYPASS_UNH_EST", Int(1);
457    PARAM_EST_ANGLE_LOCKOUT, "EST_ANG_LOCKOUT", Int(0);
458    PARAM_RC_MAX_ROLL, "RC_MAX_ROLL", Float(0.786);
459    PARAM_RC_MAX_PITCH, "RC_MAX_PITCH", Float(0.786);
460    PARAM_RC_MAX_ROLLRATE, "RC_MAX_ROLLRATE", Float(3.14159);
461    PARAM_RC_MAX_PITCHRATE, "RC_MAX_PITCHRATE", Float(3.14159);
462    PARAM_RC_MAX_YAWRATE, "RC_MAX_YAWRATE", Float(1.507);
463    PARAM_PRIMARY_MIXER, "PRIMARY_MIXER", Int(-1);
464    PARAM_SECONDARY_MIXER, "SECONDARY_MIXER", Int(-1);
465    PARAM_FIXED_WING, "FIXED_WING", Int(0);
466    PARAM_ELEVATOR_REVERSE, "REV_ELEVATOR", Int(0);
467    PARAM_AILERON_REVERSE, "REV_AILERON", Int(0);
468    PARAM_RUDDER_REVERSE, "REV_RUDDER", Int(0);
469    PARAM_IMU_ROLL, "IMU_ROLL", Float(0.0);
470    PARAM_IMU_PITCH, "IMU_PITCH", Float(0.0);
471    PARAM_IMU_YAW, "IMU_YAW", Float(0.0);
472    PARAM_MAG_ROLL, "MAG_ROLL", Float(0.0);
473    PARAM_MAG_PITCH, "MAG_PITCH", Float(0.0);
474    PARAM_MAG_YAW, "MAG_YAW", Float(0.0);
475    PARAM_ARM_THRESHOLD, "RC_ARM_THRESHOLD", Float(0.15);
476    PARAM_BATTERY_VOLTAGE_MULTIPLIER, "BATT_VOLT_MULT", Float(1.0);
477    PARAM_BATTERY_CURRENT_MULTIPLIER, "BATT_CURR_MULT", Float(1.0);
478    PARAM_BATTERY_VOLTAGE_ALPHA, "BATT_VOLT_LPF", Float(0.995);
479    PARAM_BATTERY_CURRENT_ALPHA, "BATT_CURR_LPF", Float(0.995);
480    PARAM_OFFBOARD_TIMEOUT, "OFFBOARD_TIMEOUT", Int(100);
481    PARAM_RC_OUTPUT_KILL_CHANNEL, "RC_KILL_CHN", Int(-1);
482
483    // Telemetry publication rates. -1 disables a stream, 0 publishes whenever
484    // eligible, and positive values request a fixed rate in hertz.
485    PARAM_TELEM_HEARTBEAT_HZ, "TEL_HB_HZ", Int(1);
486    PARAM_TELEM_STATUS_HZ, "TEL_STATUS_HZ", Int(10);
487    PARAM_TELEM_IMU_HZ, "TEL_IMU_HZ", Int(400);
488    PARAM_TELEM_ATTITUDE_HZ, "TEL_ATT_HZ", Int(400);
489    PARAM_TELEM_OUTPUT_RAW_HZ, "TEL_OUT_HZ", Int(50);
490    PARAM_TELEM_DIFF_PRESSURE_HZ, "TEL_DIFF_HZ", Int(100);
491    PARAM_TELEM_BARO_HZ, "TEL_BARO_HZ", Int(100);
492    PARAM_TELEM_MAG_HZ, "TEL_MAG_HZ", Int(50);
493    PARAM_TELEM_RANGE_HZ, "TEL_RANGE_HZ", Int(50);
494    PARAM_TELEM_BATTERY_HZ, "TEL_BATT_HZ", Int(200);
495    PARAM_TELEM_GNSS_HZ, "TEL_GNSS_HZ", Int(10);
496    PARAM_TELEM_RC_HZ, "TEL_RC_HZ", Int(800);
497}
498
499//=================================================================================
500// 4. Unit Tests
501//=================================================================================
502
503#[cfg(test)]
504mod tests {
505    use super::*;
506
507    #[test]
508    fn test_param_count() {
509        assert_eq!(PARAMS_COUNT, PARAM_DEFINITIONS.len());
510        assert_eq!(PARAMS_COUNT, 349);
511    }
512
513    #[test]
514    fn rosflight_2_0_param_surface_keeps_known_compatibility_names() {
515        assert_eq!(ParamId::PARAM_VOLT_MAX.as_str(), "BATT_VOLT_MAX");
516        assert_eq!(ParamId::PARAM_PRIMARY_MIXER_9_9.as_str(), "PRI_MIXER_9_9");
517        assert_eq!(ParamId::PARAM_SECONDARY_MIXER_9_9.as_str(), "SEC_MIXER_9_9");
518        assert_eq!(ParamId::PARAM_INIT_TIME.as_str(), "FILT_INIT_T");
519        assert_eq!(ParamId::PARAM_FILTER_KP_ACC.as_str(), "FILT_ACC_KP");
520        assert_eq!(ParamId::PARAM_MAG_A00_COMP.as_str(), "MAG_CAL_A00");
521        assert_eq!(ParamId::PARAM_RC_ARM_CHANNEL.as_str(), "RC_ARM_CHN");
522        assert_eq!(ParamId::PARAM_OVERRIDE_LAG_TIME.as_str(), "RC_OVRD_LAG_T");
523        assert_eq!(
524            ParamId::PARAM_RC_OVERRIDE_TAKE_MIN_THROTTLE.as_str(),
525            "TAKE_MIN_THR"
526        );
527        assert_eq!(
528            ParamId::PARAM_ALLOW_UNHEALTHY_ESTIMATOR.as_str(),
529            "BYPASS_UNH_EST"
530        );
531        assert_eq!(ParamId::PARAM_EST_ANGLE_LOCKOUT.as_str(), "EST_ANG_LOCKOUT");
532        assert_eq!(ParamId::PARAM_ELEVATOR_REVERSE.as_str(), "REV_ELEVATOR");
533        assert_eq!(ParamId::PARAM_IMU_ROLL.as_str(), "IMU_ROLL");
534        assert_eq!(ParamId::PARAM_MAG_YAW.as_str(), "MAG_YAW");
535        assert_eq!(ParamId::PARAM_ARM_THRESHOLD.as_str(), "RC_ARM_THRESHOLD");
536        assert_eq!(
537            ParamId::PARAM_BATTERY_VOLTAGE_ALPHA.as_str(),
538            "BATT_VOLT_LPF"
539        );
540        assert_eq!(
541            ParamId::PARAM_CHANNEL_OUTPUT_MASK.as_str(),
542            "CHN_OUTPUT_MASK"
543        );
544        assert_eq!(
545            ParamId::PARAM_RC_OUTPUT_KILL_CHANNEL.as_str(),
546            "RC_KILL_CHN"
547        );
548    }
549
550    #[test]
551    fn test_new_and_defaults() {
552        let p = Params::new();
553        assert_eq!(
554            p.get_by_id(ParamId::PARAM_BAUD_RATE),
555            ParamValue::Int(921600)
556        );
557        assert_eq!(
558            p.get_by_id(ParamId::PARAM_PID_ROLL_RATE_P),
559            ParamValue::Float(0.070)
560        );
561        assert_eq!(
562            p.get_by_id(ParamId::PARAM_SPIN_MOTORS_WHEN_ARMED),
563            ParamValue::Int(1)
564        );
565        assert_eq!(
566            p.get_by_id(ParamId::PARAM_CHANNEL_OUTPUT_MASK),
567            ParamValue::Int(-1)
568        );
569        assert_eq!(
570            p.get_by_id(ParamId::PARAM_RC_OUTPUT_KILL_CHANNEL),
571            ParamValue::Int(-1)
572        );
573        assert_eq!(
574            p.get_by_id(ParamId::PARAM_CALIBRATE_GYRO_ON_ARM),
575            ParamValue::Int(0)
576        );
577        assert_eq!(
578            p.get_by_id(ParamId::PARAM_BATTERY_VOLTAGE_MULTIPLIER),
579            ParamValue::Float(1.0)
580        );
581    }
582
583    #[test]
584    fn test_get_set_by_id() {
585        let mut p = Params::new();
586        p.set_by_id(ParamId::PARAM_SYSTEM_ID, ParamValue::Int(42));
587        assert_eq!(p.get_by_id(ParamId::PARAM_SYSTEM_ID), ParamValue::Int(42));
588        p.set_by_id(ParamId::PARAM_FIXED_WING, ParamValue::Int(1));
589        assert_eq!(p.get_by_id(ParamId::PARAM_FIXED_WING), ParamValue::Int(1));
590    }
591
592    #[test]
593    fn test_get_set_by_name() {
594        let mut p = Params::new();
595        let success = p.set_by_name("SYS_ID", ParamValue::Int(99));
596        assert!(success);
597        assert_eq!(p.get_by_id(ParamId::PARAM_SYSTEM_ID), ParamValue::Int(99));
598        assert_eq!(p.get_by_name("SYS_ID"), Some(ParamValue::Int(99)));
599
600        let failure = p.set_by_name("NON_EXISTENT", ParamValue::Int(1));
601        assert!(!failure);
602        assert_eq!(p.get_by_name("NON_EXISTENT"), None);
603    }
604}