Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
eff_scheduling_rotwing_V2.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Tomaso De Ponti <T.M.L.DePonti@tudelft.nl>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
27 #include "generated/airframe.h"
28 #include "state.h"
30 #include "modules/core/abi.h"
33 
34 #define FORCE_ONELOOP
35 #ifdef FORCE_ONELOOP
38 #else
40 #endif
41 
42 #ifndef ROTWING_EFF_SCHED_IXX_BODY
43 #error "NO ROTWING_EFF_SCHED_IXX_BODY defined"
44 #endif
45 
46 #ifndef ROTWING_EFF_SCHED_IYY_BODY
47 #error "NO ROTWING_EFF_SCHED_IYY_BODY defined"
48 #endif
49 
50 #ifndef ROTWING_EFF_SCHED_IZZ
51 #error "NO ROTWING_EFF_SCHED_IZZ defined"
52 #endif
53 
54 #ifndef ROTWING_EFF_SCHED_IXX_WING
55 #error "NO ROTWING_EFF_SCHED_IXX_WING defined"
56 #endif
57 
58 #ifndef ROTWING_EFF_SCHED_IYY_WING
59 #error "NO ROTWING_EFF_SCHED_IYY_WING defined"
60 #endif
61 
62 #ifndef ROTWING_EFF_SCHED_M
63 #error "NO ROTWING_EFF_SCHED_M defined"
64 #endif
65 
66 /* Effectiveness Matrix definition */
67 float G2_RW[EFF_MAT_COLS_NB] = {0};//ROTWING_EFF_SCHED_G2; //scaled by RW_G_SCALE
68 float G1_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB] = {0};//{ROTWING_EFF_SCHED_G1_ZERO, ROTWING_EFF_SCHED_G1_ZERO, ROTWING_EFF_SCHED_G1_THRUST, ROTWING_EFF_SCHED_G1_ROLL, ROTWING_EFF_SCHED_G1_PITCH, ROTWING_EFF_SCHED_G1_YAW}; //scaled by RW_G_SCALE
70 static float flt_cut = 1.0e-4;
71 
74 /* Temp variables*/
75 bool airspeed_fake_on = false;
76 float airspeed_fake = 0.0;
77 float ele_eff = 19.36; // (0.88*22.0);
78 float ele_min = 0.0;
79 /* Define Forces and Moments tructs for each actuator*/
80 struct RW_Model RW;
81 
84 void ele_pref_sched(void);
85 void update_attitude(void);
86 void sum_EFF_MAT_RW(void);
87 void init_RW_Model(void);
88 void calc_G1_G2_RW(void);
89 
92 #ifndef WING_ROTATION_CAN_ROTWING_ID
93 #define WING_ROTATION_CAN_ROTWING_ID ABI_BROADCAST
94 #endif
95 PRINT_CONFIG_VAR(WING_ROTATION_CAN_ROTWING_ID)
97 
98 float skew_meas = 0.0;
99 static void wing_position_cb(uint8_t sender_id UNUSED, struct act_feedback_t *pos_msg, uint8_t num_act)
100 {
101  for (int i=0; i<num_act; i++){
102  if (pos_msg[i].set.position && (pos_msg[i].idx == SERVO_ROTATION_MECH_IDX))
103  {
104  skew_meas = 0.5 * M_PI - pos_msg[i].position;
105  Bound(skew_meas, 0, 0.5 * M_PI);
106  }
107  }
108 }
109 
111 {
112  init_RW_Model();
113  update_attitude();
115  float tau_skew = 1.0 / (2.0 * M_PI * 5.0);
116  float sample_time = 1.0 / PERIODIC_FREQUENCY;
117  init_butterworth_2_low_pass(&skew_filt, tau_skew, sample_time, 0.0);
118 }
119 
120 void init_RW_Model(void)
121 {
122  // Inertia and mass
123  RW.I.b_xx = 0.12879; // [kgm²] (0.0478 + 0.08099)
124  RW.I.b_yy = 0.94950; // [kgm²] (0.7546 + 0.1949)
125  RW.I.w_xx = 0.0; // [kgm²]
126  RW.I.w_yy = 0.0; // [kgm²]
127  RW.I.xx = RW.I.b_xx + RW.I.w_xx; // [kgm²]
128  RW.I.yy = RW.I.b_yy + RW.I.b_yy; // [kgm²]
129  RW.I.zz = 0.975; // [kgm²]
130  RW.m = 6.670; // [kg]
131  // Motor Front
132  RW.mF.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
133  RW.mF.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
134  RW.mF.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
135  RW.mF.l = 0.423 ; // [m]
136  // Motor Right
137  RW.mR.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
138  RW.mR.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
139  RW.mR.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
140  RW.mR.l = 0.408 ; // [m]
141  // Motor Back
142  RW.mB.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
143  RW.mB.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
144  RW.mB.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
145  RW.mB.l = 0.423 ; // [m]
146  // Motor Left
147  RW.mL.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
148  RW.mL.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
149  RW.mL.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
150  RW.mL.l = 0.408 ; // [m]
151  // Motor Pusher
152  RW.mP.dFdu = 3.468 / RW_G_SCALE; // [N / pprz]
153  RW.mP.dMdu = 0.000 / RW_G_SCALE; // [Nm / pprz]
154  RW.mP.dMdud = 0.000 / RW_G_SCALE; // [Nm / pprz]
155  RW.mP.l = 0.000 ; // [m]
156  // Elevator
157  RW.ele.dFdu = ele_eff / (RW_G_SCALE * RW_G_SCALE); // [N / pprz] old value: 24.81 29.70
158  RW.ele.dMdu = 0; // [Nm / pprz]
159  RW.ele.dMdud = 0; // [Nm / pprz]
160  RW.ele.l = 0.85; // [m]
161  RW.ele_pref = 0;
162  // Rudder
163  RW.rud.dFdu = 1.207 / (RW_G_SCALE * RW_G_SCALE); // [N / pprz]
164  RW.rud.dMdu = 0; // [Nm / pprz]
165  RW.rud.dMdud = 0; // [Nm / pprz]
166  RW.rud.l = 0.88; // [m]
167  // Aileron
168  RW.ail.dFdu = 7.678 / (RW_G_SCALE * RW_G_SCALE); // [N / pprz] (1.88 * 4.084)
169  RW.ail.dMdu = 0; // [Nm / pprz]
170  RW.ail.dMdud = 0; // [Nm / pprz]
171  RW.ail.l = 0.68; // [m]
172  // Flaperon
173  RW.flp.dFdu = 10.825 / (RW_G_SCALE * RW_G_SCALE); // [N / pprz] (1.88 * 5.758)
174  RW.flp.dMdu = 0; // [Nm / pprz]
175  RW.flp.dMdud = 0; // [Nm / pprz]
176  RW.flp.l = 0.36; // [m]
177  // Lift: k0 the v²+ k1 the sin² v² + k2 sin² v²
178  RW.wing.k0 = 0.336 + 0.0507 + 0.102;
179  RW.wing.k1 = 0.616;
180  RW.wing.k2 = 0.121;
181  // Initialize attitude
182  RW.att.phi = 0.0;
183  RW.att.theta = 0.0;
184  RW.att.psi = 0.0;
185  RW.att.sphi = 0.0;
186  RW.att.cphi = 0.0;
187  RW.att.stheta = 0.0;
188  RW.att.ctheta = 0.0;
189  RW.att.spsi = 0.0;
190  RW.att.cpsi = 0.0;
191  // Initialize skew variables to quad values
192  RW.skew.rad = 0.0; // ABI input
193  RW.skew.deg = 0.0;
194  RW.skew.cosr = 1.0;
195  RW.skew.sinr = 0.0;
196  RW.skew.cosr2 = 1.0;
197  RW.skew.sinr2 = 0.0;
198  RW.skew.sinr3 = 0.0;
199  // Initialize airspeed
200  RW.as = 0.0;
201  RW.as2 = 0.0;
202 }
203 
204 /*Update the attitude*/
205 void update_attitude(void)
206 {
211  RW.att.sphi = sinf(eulers_zxy_RW_EFF.phi);
212  RW.att.cphi = cosf(eulers_zxy_RW_EFF.phi);
215  RW.att.spsi = sinf(eulers_zxy_RW_EFF.psi);
216  RW.att.cpsi = cosf(eulers_zxy_RW_EFF.psi);
217 }
218 /* Function to precalculate once some constant effectiveness values to improve efficiency*/
219 void calc_G1_G2_RW(void)
220 {
221  // Inertia
222  RW.I.xx = RW.I.b_xx + RW.skew.cosr2 * RW.I.w_xx + RW.skew.sinr2 * RW.I.w_yy;
223  RW.I.yy = RW.I.b_yy + RW.skew.sinr2 * RW.I.w_xx + RW.skew.cosr2 * RW.I.w_yy;
224  Bound(RW.I.xx, 0.01, 100.);
225  Bound(RW.I.yy, 0.01, 100.);
226  // Motor Front
227  G1_RW[RW_aZ][COMMAND_MOTOR_FRONT] = -RW.mF.dFdu / RW.m;
228  G1_RW[RW_aq][COMMAND_MOTOR_FRONT] = (RW.mF.dFdu * RW.mF.l) / RW.I.yy;
229  G1_RW[RW_ar][COMMAND_MOTOR_FRONT] = -RW.mF.dMdu / RW.I.zz;
230  G2_RW[COMMAND_MOTOR_FRONT] = -RW.mF.dMdud / RW.I.zz;
231  // Motor Right
232  G1_RW[RW_aZ][COMMAND_MOTOR_RIGHT] = -RW.mR.dFdu / RW.m;
233  G1_RW[RW_ap][COMMAND_MOTOR_RIGHT] = -(RW.mR.dFdu * RW.mR.l * RW.skew.cosr) / RW.I.xx;
234  G1_RW[RW_aq][COMMAND_MOTOR_RIGHT] = (RW.mR.dFdu * RW.mR.l * RW.skew.sinr) / RW.I.yy;
235  G1_RW[RW_ar][COMMAND_MOTOR_RIGHT] = RW.mR.dMdu / RW.I.zz;
236  G2_RW[COMMAND_MOTOR_RIGHT] = RW.mR.dMdud / RW.I.zz;
237  // Motor Back
238  G1_RW[RW_aZ][COMMAND_MOTOR_BACK] = -RW.mB.dFdu / RW.m;
239  G1_RW[RW_aq][COMMAND_MOTOR_BACK] = -(RW.mB.dFdu * RW.mB.l) / RW.I.yy;
240  G1_RW[RW_ar][COMMAND_MOTOR_BACK] = -RW.mB.dMdu / RW.I.zz;
241  G2_RW[COMMAND_MOTOR_BACK] = -RW.mB.dMdud / RW.I.zz;
242  // Motor Left
243  G1_RW[RW_aZ][COMMAND_MOTOR_LEFT] = -RW.mL.dFdu / RW.m;
244  G1_RW[RW_ap][COMMAND_MOTOR_LEFT] = (RW.mL.dFdu * RW.mL.l * RW.skew.cosr) / RW.I.xx;
245  G1_RW[RW_aq][COMMAND_MOTOR_LEFT] = -(RW.mL.dFdu * RW.mL.l * RW.skew.sinr) / RW.I.yy;
246  G1_RW[RW_ar][COMMAND_MOTOR_LEFT] = RW.mL.dMdu / RW.I.zz;
247  G2_RW[COMMAND_MOTOR_LEFT] = RW.mL.dMdud / RW.I.zz;
248  // Motor Pusher
249  G1_RW[RW_aX][COMMAND_MOTOR_PUSHER] = RW.mP.dFdu / RW.m;
250  // Elevator
252  G1_RW[RW_aq][COMMAND_ELEVATOR] = (RW.ele.dFdu * RW.as2 * RW.ele.l) / RW.I.yy;
253  // Rudder
254  G1_RW[RW_ar][COMMAND_RUDDER] = (RW.rud.dFdu * RW.as2 * RW.rud.l) / RW.I.zz ;
255  // Aileron
256  G1_RW[RW_ap][COMMAND_AILERONS] = (RW.ail.dFdu * RW.as2 * RW.ail.l * RW.skew.sinr3) / RW.I.xx;
257  G1_RW[RW_aq][COMMAND_AILERONS] = (RW.ail.dFdu * RW.as2 * RW.ail.l * (RW.skew.cosr-RW.skew.cosr3)) / RW.I.yy;
258 
259  // Flaperon
260  G1_RW[RW_ap][COMMAND_FLAPS] = (RW.flp.dFdu * RW.as2 * RW.flp.l * RW.skew.sinr3) / RW.I.xx;
261  G1_RW[RW_aq][COMMAND_FLAPS] = (RW.flp.dFdu * RW.as2 * RW.flp.l * (RW.skew.cosr-RW.skew.cosr3)) / RW.I.yy;
262  // Lift and thrust
263  RW.wing.dLdtheta = (RW.wing.k0 + RW.wing.k1 * RW.skew.sinr2) * RW.as2;
264  Bound(RW.wing.dLdtheta, 0.0, 1300.0);
266  Bound(RW.wing.L, 0.0, 350.0);
267  RW.T = actuator_state_1l[COMMAND_MOTOR_FRONT] * RW.mF.dFdu + actuator_state_1l[COMMAND_MOTOR_RIGHT] * RW.mR.dFdu + actuator_state_1l[COMMAND_MOTOR_BACK] * RW.mB.dFdu + actuator_state_1l[COMMAND_MOTOR_LEFT] * RW.mL.dFdu;
268  Bound(RW.T, 0.0, 180.0);
269  RW.P = actuator_state_1l[COMMAND_MOTOR_PUSHER] * RW.mP.dFdu;
270 }
271 
273 {
274  update_attitude();
277  ele_pref_sched();
278  calc_G1_G2_RW();
279  sum_EFF_MAT_RW();
280 }
281 
282 
289 void sum_EFF_MAT_RW(void) {
290 
291  // Thrust and Pusher force estimation
292  float L = RW.wing.L / RW.m; // Lift specific force
293  float dLdtheta = RW.wing.dLdtheta / RW.m; // Lift specific force derivative with pitch
294  float T = RW.T / RW.m; // Thrust specific force. Minus gravity is a guesstimate.
295  float P = RW.P / RW.m; // Pusher specific force
296  float T_L = T + L * RW.att.ctheta; // Thrust and Lift term
297  float P_L = P + L * RW.att.stheta; // Pusher and Lift term
298  int i = 0;
299  int j = 0;
300 
301  for (i = 0; i < EFF_MAT_COLS_NB; i++) {
302  switch (i) {
303  case (COMMAND_MOTOR_FRONT):
304  case (COMMAND_MOTOR_BACK):
305  case (COMMAND_MOTOR_RIGHT):
306  case (COMMAND_MOTOR_LEFT):
309  EFF_MAT_RW[RW_aD][i] = (RW.att.cphi * RW.att.ctheta ) * G1_RW[RW_aZ][i];
310  EFF_MAT_RW[RW_ap][i] = (G1_RW[RW_ap][i]) ;
311  EFF_MAT_RW[RW_aq][i] = (G1_RW[RW_aq][i]) ;
312  EFF_MAT_RW[RW_ar][i] = (G1_RW[RW_ar][i] + G2_RW[i]) ;
313  break;
314  case (COMMAND_MOTOR_PUSHER):
317  EFF_MAT_RW[RW_aD][i] = (- RW.att.cphi * RW.att.stheta ) * G1_RW[RW_aX][i];
318  EFF_MAT_RW[RW_ap][i] = 0.0;
319  EFF_MAT_RW[RW_aq][i] = 0.0;
320  EFF_MAT_RW[RW_ar][i] = 0.0;
321  break;
322  case (COMMAND_ELEVATOR):
323  case (COMMAND_RUDDER):
324  case (COMMAND_AILERONS):
325  case (COMMAND_FLAPS):
326  EFF_MAT_RW[RW_aN][i] = 0.0;
327  EFF_MAT_RW[RW_aE][i] = 0.0;
328  EFF_MAT_RW[RW_aD][i] = 0.0;
329  EFF_MAT_RW[RW_ap][i] = G1_RW[RW_ap][i];
330  EFF_MAT_RW[RW_aq][i] = G1_RW[RW_aq][i];
331  EFF_MAT_RW[RW_ar][i] = G1_RW[RW_ar][i];
332  break;
333  case (COMMAND_ROLL):
334  EFF_MAT_RW[RW_aN][i] = (-RW.att.cphi * RW.att.ctheta * RW.att.spsi * T_L - RW.att.cphi * RW.att.spsi * RW.att.stheta * P_L);
335  EFF_MAT_RW[RW_aE][i] = ( RW.att.cphi * RW.att.ctheta * RW.att.cpsi * T_L + RW.att.cphi * RW.att.cpsi * RW.att.stheta * P_L);
336  EFF_MAT_RW[RW_aD][i] = ( RW.att.sphi * RW.att.ctheta * T_L + RW.att.sphi * RW.att.stheta * P_L);
337  EFF_MAT_RW[RW_ap][i] = 0.0;
338  EFF_MAT_RW[RW_aq][i] = 0.0;
339  EFF_MAT_RW[RW_ar][i] = 0.0;
340  break;
341  case (COMMAND_PITCH):
342  EFF_MAT_RW[RW_aN][i] = (-(RW.att.ctheta * RW.att.cpsi - RW.att.sphi * RW.att.stheta * RW.att.spsi) * T - (RW.att.cpsi * RW.att.stheta + RW.att.ctheta * RW.att.sphi * RW.att.spsi) * P - RW.att.sphi * RW.att.spsi * dLdtheta);
343  EFF_MAT_RW[RW_aE][i] = (-(RW.att.ctheta * RW.att.spsi + RW.att.sphi * RW.att.stheta * RW.att.cpsi) * T - (RW.att.spsi * RW.att.stheta - RW.att.cpsi * RW.att.ctheta * RW.att.sphi) * P + RW.att.sphi * RW.att.cpsi * dLdtheta);
344  EFF_MAT_RW[RW_aD][i] = ( RW.att.stheta * RW.att.cphi * T - RW.att.cphi * RW.att.ctheta * P - RW.att.cphi * dLdtheta) ;
345  EFF_MAT_RW[RW_ap][i] = 0.0;
346  EFF_MAT_RW[RW_aq][i] = 0.0;
347  EFF_MAT_RW[RW_ar][i] = 0.0;
348  break;
349  default:
350  break;
351  }
352  }
353  for (i = 0; i < EFF_MAT_ROWS_NB; i++) {
354  for(j = 0; j < EFF_MAT_COLS_NB; j++) {
355  float abs = fabs(EFF_MAT_RW[i][j]);
356  if (abs < flt_cut) {
357  EFF_MAT_RW[i][j] = 0.0;
358  }
359  }
360  }
361 }
362 
364 {
365  // Calculate sin and cosines of rotation
367  RW.skew.rad = skew_filt.o[0];
368  RW.skew.deg = RW.skew.rad / M_PI * 180.;
369  RW.skew.cosr = cosf(RW.skew.rad);
370  RW.skew.sinr = sinf(RW.skew.rad);
375 #ifdef INS_EXT_VISION_ROTATION
376  // Define an INS external pose quaternion rotation from the wing rotation angle
377  struct FloatEulers rot_e = {0, 0, RW.skew.rad};
378  float_quat_of_eulers(&ins_ext_vision_rot, &rot_e);
379 #endif
380 
381 }
382 float time = 0.0;
384 {
386  Bound(RW.as, 0. , 30.);
387  RW.as2 = RW.as * RW.as;
388  Bound(RW.as2, 0. , 900.);
389  if(airspeed_fake_on) {
390  //float freq = 0.5;
391  //float amp = 3.0;
392  time = time + 0.002;
393  RW.as = airspeed_fake ;//+ amp * sinf(2.0 * M_PI * freq * time);
394  RW.as2 = RW.as * RW.as;
395  } else {
396  time = 0.0;
397  }
398 }
399 
400 void ele_pref_sched(void)
401 {
402  if (RW.as > ELE_MIN_AS){
405  } else {
406  RW.ele_pref = ele_min;
407  }
408 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
uint8_t last_wp UNUSED
void update_attitude(void)
float G2_RW[EFF_MAT_COLS_NB]
void calc_G1_G2_RW(void)
float G1_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB]
float ele_min
float airspeed_fake
struct FloatEulers eulers_zxy_RW_EFF
struct RW_Model RW
#define WING_ROTATION_CAN_ROTWING_ID
ABI binding wing position data.
float actuator_state_filt_vect[EFF_MAT_COLS_NB]
void eff_scheduling_rotwing_update_airspeed(void)
float EFF_MAT_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB]
static Butterworth2LowPass skew_filt
void ele_pref_sched(void)
void eff_scheduling_rotwing_update_wing_angle(void)
static abi_event wing_position_ev
void eff_scheduling_rotwing_init(void)
void sum_EFF_MAT_RW(void)
Function that sums g1 and g2 to obtain the g1_g2 matrix.
bool airspeed_fake_on
void init_RW_Model(void)
static float flt_cut
void eff_scheduling_rotwing_periodic(void)
static void wing_position_cb(uint8_t sender_id UNUSED, struct act_feedback_t *pos_msg, uint8_t num_act)
float skew_meas
float ele_eff
#define RW_G_SCALE
struct wing_model wing
#define RW_aN
struct F_M_Body ele
#define RW_aE
struct F_M_Body mP
#define RW_aZ
struct F_M_Body mL
#define ELE_MAX_AS
#define RW_aX
#define EFF_MAT_COLS_NB
#define RW_ap
#define ELE_MIN_AS
#define RW_ar
#define ZERO_ELE_PPRZ
struct F_M_Body mR
struct F_M_Body mF
struct RW_attitude att
#define EFF_MAT_ROWS_NB
struct F_M_Body rud
struct RW_skew skew
#define RW_aq
#define RW_aD
struct F_M_Body flp
struct F_M_Body mB
struct F_M_Body ail
float phi
in radians
float theta
in radians
float psi
in radians
void float_eulers_of_quat_zxy(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
void float_quat_of_eulers(struct FloatQuat *q, struct FloatEulers *e)
quat of euler roation 'ZYX'
euler angles
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition: state.h:1407
Integrated Navigation System interface.
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
Second order low pass filter structure.
Hardware independent API for actuators (servos, motor controllers).
float actuator_state_1l[ANDI_NUM_ACT]
Definition: oneloop_andi.c:333
API to get/set the generic vehicle states.
static float P[3][3]
Definition: trilateration.c:31
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98