Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
stabilization_indi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) Ewoud Smeur <ewoud_smeur@msn.com>
3  * MAVLab Delft University of Technology
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
36 
38 #include "state.h"
39 #include "generated/airframe.h"
42 #include "modules/core/abi.h"
44 #include "math/wls/wls_alloc.h"
45 #include <stdio.h>
46 
47 // Factor that the estimated G matrix is allowed to deviate from initial one
48 #define INDI_ALLOWED_G_FACTOR 2.0
49 
50 #ifdef STABILIZATION_INDI_FILT_CUTOFF_P
51 #define STABILIZATION_INDI_FILTER_ROLL_RATE TRUE
52 #else
53 #define STABILIZATION_INDI_FILT_CUTOFF_P 20.0
54 #endif
55 
56 #ifdef STABILIZATION_INDI_FILT_CUTOFF_Q
57 #define STABILIZATION_INDI_FILTER_PITCH_RATE TRUE
58 #else
59 #define STABILIZATION_INDI_FILT_CUTOFF_Q 20.0
60 #endif
61 
62 #ifdef STABILIZATION_INDI_FILT_CUTOFF_R
63 #define STABILIZATION_INDI_FILTER_YAW_RATE TRUE
64 #else
65 #define STABILIZATION_INDI_FILT_CUTOFF_R 20.0
66 #endif
67 
68 // Default is WLS
69 #ifndef STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
70 #define STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE FALSE
71 #endif
72 
73 #ifndef STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
74 #define STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER FALSE
75 #endif
76 
77 // Airspeed [m/s] at which the forward flight throttle limit is used instead of
78 // the hover throttle limit.
79 #ifndef STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
80 #define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD 8.0
81 #endif
82 
83 #if INDI_OUTPUTS > 4
84 #ifndef STABILIZATION_INDI_G1_THRUST_X
85 #error "You must define STABILIZATION_INDI_G1_THRUST_X for your number of INDI_OUTPUTS"
86 #endif
87 #endif
88 
89 #ifdef SetCommandsFromRC
90 #warning SetCommandsFromRC not used: STAB_INDI writes actuators directly
91 #endif
92 
93 #ifdef SetAutoCommandsFromRC
94 #warning SetAutoCommandsFromRC not used: STAB_INDI writes actuators directly
95 #endif
96 
97 
98 #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
99 #if INDI_NUM_ACT > WLS_N_U_MAX
100 #error Matrix-WLS_N_U_MAX too small or not defined: define WLS_N_U_MAX >= INDI_NUM_ACT in airframe file
101 #endif
102 #if INDI_OUTPUTS > WLS_N_V_MAX
103 #error Matrix-WLS_N_V_MAX too small or not defined: define WLS_N_V_MAX >= INDI_OUTPUTS in airframe file
104 #endif
105 struct WLS_t wls_stab_p = {
106  .nu = INDI_NUM_ACT,
107  .nv = INDI_OUTPUTS,
108  .gamma_sq = 10000.0,
109  .v = {0.0},
110 #ifdef STABILIZATION_INDI_WLS_PRIORITIES
111  .Wv = STABILIZATION_INDI_WLS_PRIORITIES,
112 #else //State prioritization {W Roll, W pitch, W yaw, TOTAL THRUST}
113 #if INDI_OUTPUTS == 5
114  .Wv = {1000, 1000, 1, 100, 100},
115 #else
116  .Wv = {1000, 1000, 1, 100},
117 #endif
118 #endif
119 #ifdef STABILIZATION_INDI_WLS_WU //Weighting of different actuators in the cost function
120  .Wu = STABILIZATION_INDI_WLS_WU,
121 #else
122  .Wu = {[0 ... INDI_NUM_ACT - 1] = 1.0},
123 #endif
124  .u_pref = {0.0},
125  .u_min = {0.0},
126  .u_max = {0.0},
127  .PC = 0.0,
128  .SC = 0.0,
129  .iter = 0
130 };
131 #endif
132 float indi_v[INDI_OUTPUTS];
133 float *Bwls[INDI_OUTPUTS];
134 
135 static void lms_estimation(void);
136 static void get_actuator_state(void);
137 static void calc_g1_element(float dx_error, int8_t i, int8_t j, float mu_extra);
138 static void calc_g2_element(float dx_error, int8_t j, float mu_extra);
139 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
140 static void calc_g1g2_pseudo_inv(void);
141 #endif
142 static void bound_g_mat(void);
143 
145 struct Indi_gains indi_gains = {
146  .att = {
147  STABILIZATION_INDI_REF_ERR_P,
148  STABILIZATION_INDI_REF_ERR_Q,
149  STABILIZATION_INDI_REF_ERR_R
150  },
151  .rate = {
152  STABILIZATION_INDI_REF_RATE_P,
153  STABILIZATION_INDI_REF_RATE_Q,
154  STABILIZATION_INDI_REF_RATE_R
155  },
156 };
157 
158 #if STABILIZATION_INDI_USE_ADAPTIVE
159 bool indi_use_adaptive = true;
160 #else
161 bool indi_use_adaptive = false;
162 #endif
163 
164 #ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
165 float act_rate_limit[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_RATE_LIMIT;
166 #endif
167 
168 #ifdef STABILIZATION_INDI_ACT_IS_SERVO
169 bool act_is_servo[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_IS_SERVO;
170 #else
171 bool act_is_servo[INDI_NUM_ACT] = {0};
172 #endif
173 
174 #ifdef STABILIZATION_INDI_ACT_IS_THRUSTER_X
175 bool act_is_thruster_x[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_IS_THRUSTER_X;
176 #else
177 bool act_is_thruster_x[INDI_NUM_ACT] = {0};
178 #endif
179 
180 bool act_is_thruster_z[INDI_NUM_ACT];
181 
182 #ifdef STABILIZATION_INDI_ACT_PREF
183 // Preferred (neutral, least energy) actuator value
184 float act_pref[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_PREF;
185 #else
186 // Assume 0 is neutral
187 float act_pref[INDI_NUM_ACT] = {0.0};
188 #endif
189 
190 #ifdef STABILIZATION_INDI_ACT_DYN
191 #warning STABILIZATION_INDI_ACT_DYN is deprecated, use STABILIZATION_INDI_ACT_FREQ instead.
192 #warning You now have to define the continuous time corner frequency in rad/s of the actuators.
193 #warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old values."
194 float act_dyn_discrete[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_DYN;
195 #else
196 float act_first_order_cutoff[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_FREQ;
197 float act_dyn_discrete[INDI_NUM_ACT]; // will be computed from freq at init
198 #endif
199 
203 #ifdef STABILIZATION_INDI_YAW_DISTURBANCE_LIMIT
204 float stablization_indi_yaw_dist_limit = STABILIZATION_INDI_YAW_DISTURBANCE_LIMIT;
205 #else // Put a rediculously high limit
207 #endif
208 
209 // variables needed for control
210 float actuator_state_filt_vect[INDI_NUM_ACT];
211 struct FloatRates angular_accel_ref = {0., 0., 0.};
212 struct FloatRates angular_rate_ref = {0., 0., 0.};
213 float angular_acceleration[3] = {0., 0., 0.};
214 float actuator_state[INDI_NUM_ACT];
215 float indi_u[INDI_NUM_ACT];
216 
217 float q_filt = 0.0;
218 float r_filt = 0.0;
219 
220 float stabilization_indi_filter_freq = 20.0; //Hz, for setting handler
221 
222 // variables needed for estimation
223 float g1g2_trans_mult[INDI_OUTPUTS][INDI_OUTPUTS];
224 float g1g2inv[INDI_OUTPUTS][INDI_OUTPUTS];
225 float actuator_state_filt_vectd[INDI_NUM_ACT];
226 float actuator_state_filt_vectdd[INDI_NUM_ACT];
227 float estimation_rate_d[INDI_NUM_ACT];
228 float estimation_rate_dd[INDI_NUM_ACT];
229 float du_estimation[INDI_NUM_ACT];
230 float ddu_estimation[INDI_NUM_ACT];
231 
232 // The learning rate per axis (roll, pitch, yaw, thrust)
233 float mu1[INDI_OUTPUTS] = {0.00001, 0.00001, 0.000003, 0.000002};
234 // The learning rate for the propeller inertia (scaled by 512 wrt mu1)
235 float mu2 = 0.002;
236 
237 // other variables
238 float act_obs[INDI_NUM_ACT];
239 
240 // Number of actuators used to provide thrust
243 
244 static struct Int32Eulers stab_att_sp_euler;
245 static struct Int32Quat stab_att_sp_quat;
246 
247 // Register actuator feedback if we rely on RPM information
248 #if STABILIZATION_INDI_RPM_FEEDBACK
249 #ifndef STABILIZATION_INDI_ACT_FEEDBACK_ID
250 #define STABILIZATION_INDI_ACT_FEEDBACK_ID ABI_BROADCAST
251 #endif
252 PRINT_CONFIG_VAR(STABILIZATION_INDI_ACT_FEEDBACK_ID)
253 
255 static void act_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback, uint8_t num_act);
256 PRINT_CONFIG_MSG("STABILIZATION_INDI_RPM_FEEDBACK")
257 #endif
258 
259 float g1g2_pseudo_inv[INDI_NUM_ACT][INDI_OUTPUTS];
260 float g2[INDI_NUM_ACT] = STABILIZATION_INDI_G2; //scaled by INDI_G_SCALING
261 #ifdef STABILIZATION_INDI_G1
262 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = STABILIZATION_INDI_G1;
263 #else // old defines TODO remove
264 #if INDI_OUTPUTS == 5
265 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = {STABILIZATION_INDI_G1_ROLL,
266  STABILIZATION_INDI_G1_PITCH, STABILIZATION_INDI_G1_YAW,
267  STABILIZATION_INDI_G1_THRUST, STABILIZATION_INDI_G1_THRUST_X
268  };
269 #else
270 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = {STABILIZATION_INDI_G1_ROLL,
271  STABILIZATION_INDI_G1_PITCH, STABILIZATION_INDI_G1_YAW, STABILIZATION_INDI_G1_THRUST
272  };
273 #endif
274 #endif
275 
276 float g1g2[INDI_OUTPUTS][INDI_NUM_ACT];
277 float g1_est[INDI_OUTPUTS][INDI_NUM_ACT];
278 float g2_est[INDI_NUM_ACT];
279 float g1_init[INDI_OUTPUTS][INDI_NUM_ACT];
280 float g2_init[INDI_NUM_ACT];
281 
288 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
289 Butterworth2LowPass rates_filt_so[3];
290 #else
291 static struct FirstOrderLowPass rates_filt_fo[3];
292 #endif
293 struct FloatVect3 body_accel_f;
294 
295 void init_filters(void);
296 void sum_g1_g2(void);
297 
298 #if PERIODIC_TELEMETRY
300 static void send_wls_v_stab(struct transport_tx *trans, struct link_device *dev)
301 {
302  send_wls_v("stab", &wls_stab_p, trans, dev);
303 }
304 static void send_wls_u_stab(struct transport_tx *trans, struct link_device *dev)
305 {
306  send_wls_u("stab", &wls_stab_p, trans, dev);
307 }
308 
309 static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
310 {
311  pprz_msg_send_EFF_MAT_STAB(trans, dev, AC_ID,
312  INDI_NUM_ACT, g1g2[0],
313  INDI_NUM_ACT, g1g2[1],
314  INDI_NUM_ACT, g1g2[2],
315  INDI_NUM_ACT, g1g2[3],
316  INDI_NUM_ACT, g2_est);
317 }
318 
319 static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
320 {
321  struct Int32Quat *quat = stateGetNedToBodyQuat_i();
322  pprz_msg_send_AHRS_REF_QUAT(trans, dev, AC_ID,
327  &(quat->qi),
328  &(quat->qx),
329  &(quat->qy),
330  &(quat->qz));
331 }
332 
333 static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
334 {
335  float zero = 0.0;
336  struct FloatRates *body_rates = stateGetBodyRates_f();
337  struct FloatEulers att, att_sp;
338 #if GUIDANCE_INDI_HYBRID
340  struct FloatQuat stab_att_sp_quat_f;
341  QUAT_FLOAT_OF_BFP(stab_att_sp_quat_f, stab_att_sp_quat);
342  float_eulers_of_quat_zxy(&att_sp, &stab_att_sp_quat_f);
343 #else
344  att = *stateGetNedToBodyEulers_f();
346 #endif
347  float temp_att[3] = {att.phi, att.theta, att.psi};
348  float temp_att_ref[3] = {att_sp.phi, att_sp.theta, att_sp.psi};
349  float temp_rate[3] = {body_rates->p, body_rates->q, body_rates->r};
350  float temp_rate_ref[3] = {angular_rate_ref.p, angular_rate_ref.q, angular_rate_ref.r};
351  float temp_ang_acc_ref[3] = {angular_accel_ref.p, angular_accel_ref.q, angular_accel_ref.r};
352  pprz_msg_send_STAB_ATTITUDE(trans, dev, AC_ID,
353  1, &zero, // att des
354  3, temp_att, // att
355  3, temp_att_ref, // att ref
356  3, temp_rate, // rate
357  3, temp_rate_ref, // rate ref
358  3, angular_acceleration, // ang.acc = rate.diff
359  3, temp_ang_acc_ref, // ang.acc.ref
360  1, &zero, // jerk ref
361  1, &zero); // u
362 }
363 #endif
364 
369 {
370  // Initialize filters
371  init_filters();
372 
373  int8_t i;
374 // If the deprecated STABILIZATION_INDI_ACT_DYN is used, convert it to the new FREQUENCY format
375 #ifdef STABILIZATION_INDI_ACT_FREQ
376  // Initialize the array of pointers to the rows of g1g2
377  for (i = 0; i < INDI_NUM_ACT; i++) {
378  act_dyn_discrete[i] = 1-exp(-act_first_order_cutoff[i]/PERIODIC_FREQUENCY);
379  }
380 #endif
381 
382 #if STABILIZATION_INDI_RPM_FEEDBACK
383  AbiBindMsgACT_FEEDBACK(STABILIZATION_INDI_ACT_FEEDBACK_ID, &act_feedback_ev, act_feedback_cb);
384 #endif
385 
388  float_vect_zero(estimation_rate_d, INDI_NUM_ACT);
389  float_vect_zero(estimation_rate_dd, INDI_NUM_ACT);
391 
392  //Calculate G1G2
393  sum_g1_g2();
394 
395  // Do not compute if not needed
396 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
397  //Calculate G1G2_PSEUDO_INVERSE
398  calc_g1g2_pseudo_inv();
399 #endif
400 
401  // Initialize the array of pointers to the rows of g1g2
402  for (i = 0; i < INDI_OUTPUTS; i++) {
403  Bwls[i] = g1g2[i];
404  }
405 
406  // Initialize the estimator matrices
407  float_vect_copy(g1_est[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
408  float_vect_copy(g2_est, g2, INDI_NUM_ACT);
409  // Remember the initial matrices
410  float_vect_copy(g1_init[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
411  float_vect_copy(g2_init, g2, INDI_NUM_ACT);
412 
413  // Assume all non-servos are delivering thrust
414  num_thrusters = INDI_NUM_ACT;
415  num_thrusters_x = 0;
416  for (i = 0; i < INDI_NUM_ACT; i++) {
419 
421 
423  }
424 
425 #if PERIODIC_TELEMETRY
431 #endif
432 }
433 
443 {
444  float_vect_zero(du_estimation, INDI_NUM_ACT);
445  float_vect_zero(ddu_estimation, INDI_NUM_ACT);
446 }
447 
449 {
451  float tau = 1.0 / (2.0 * M_PI * freq);
452  float sample_time = 1.0 / PERIODIC_FREQUENCY;
453 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
454  init_butterworth_2_low_pass(&rates_filt_so[0], tau, sample_time, stateGetBodyRates_f()->p);
455  init_butterworth_2_low_pass(&rates_filt_so[1], tau, sample_time, stateGetBodyRates_f()->q);
456  init_butterworth_2_low_pass(&rates_filt_so[2], tau, sample_time, stateGetBodyRates_f()->r);
457 #else
459  init_first_order_low_pass(&rates_filt_fo[1], tau, sample_time, stateGetBodyRates_f()->q);
460  init_first_order_low_pass(&rates_filt_fo[2], tau, sample_time, stateGetBodyRates_f()->r);
461 #endif
462 }
463 
467 void init_filters(void)
468 {
469  // tau = 1/(2*pi*Fc)
470  float tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF);
471  float tau_est = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_ESTIMATION_FILT_CUTOFF);
472  float sample_time = 1.0 / PERIODIC_FREQUENCY;
473  // Filtering of the gyroscope
474  int8_t i;
475  for (i = 0; i < 3; i++) {
476  init_butterworth_2_low_pass(&measurement_lowpass_filters[i], tau, sample_time, 0.0);
477  init_butterworth_2_low_pass(&estimation_output_lowpass_filters[i], tau_est, sample_time, 0.0);
478  }
479 
480  // Filtering of the actuators
481  for (i = 0; i < INDI_NUM_ACT; i++) {
482  init_butterworth_2_low_pass(&actuator_lowpass_filters[i], tau, sample_time, 0.0);
483  init_butterworth_2_low_pass(&estimation_input_lowpass_filters[i], tau_est, sample_time, 0.0);
484  }
485 
486  // Filtering the bodyx acceleration with same cutoff as gyroscope
488 
489  // Filtering of the accel body z
490  init_butterworth_2_low_pass(&acceleration_lowpass_filter, tau_est, sample_time, 0.0);
491 
492 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
493  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P);
494  init_butterworth_2_low_pass(&rates_filt_so[0], tau, sample_time, 0.0);
495  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q);
496  init_butterworth_2_low_pass(&rates_filt_so[1], tau, sample_time, 0.0);
497  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R);
498  init_butterworth_2_low_pass(&rates_filt_so[2], tau, sample_time, 0.0);
499 #else
500  // Init rate filter for feedback
501  float time_constants[3] = {1.0 / (2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P), 1.0 / (2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q), 1.0 / (2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R)};
502 
503  init_first_order_low_pass(&rates_filt_fo[0], time_constants[0], sample_time, stateGetBodyRates_f()->p);
504  init_first_order_low_pass(&rates_filt_fo[1], time_constants[1], sample_time, stateGetBodyRates_f()->q);
505  init_first_order_low_pass(&rates_filt_fo[2], time_constants[2], sample_time, stateGetBodyRates_f()->r);
506 #endif
507 }
508 
517 void stabilization_indi_rate_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
518 {
519 
520  // Propagate actuator filters
522  float actuator_state_filt_vect_prev[INDI_NUM_ACT];
523  for (int i = 0; i < INDI_NUM_ACT; i++) {
527  actuator_state_filt_vect_prev[i] = actuator_lowpass_filters[i].o[1];
528 
529  // calculate derivatives for estimation
530  float actuator_state_filt_vectd_prev = actuator_state_filt_vectd[i];
532  PERIODIC_FREQUENCY;
533  actuator_state_filt_vectdd[i] = (actuator_state_filt_vectd[i] - actuator_state_filt_vectd_prev) * PERIODIC_FREQUENCY;
534  }
535 
536  // Use the last actuator state for this computation
537  float g2_times_u_act_filt = float_vect_dot_product(g2, actuator_state_filt_vect_prev, INDI_NUM_ACT)/INDI_G_SCALING;
538 
539  // Predict angular acceleration u*B
540  float angular_acc_prediction_filt[INDI_OUTPUTS];
541  float_mat_vect_mul(angular_acc_prediction_filt, Bwls, actuator_state_filt_vect, INDI_OUTPUTS, INDI_NUM_ACT);
542  angular_acc_prediction_filt[2] -= g2_times_u_act_filt;
543 
544  /* Propagate the filter on the gyroscopes */
545  struct FloatRates *body_rates = stateGetBodyRates_f();
546  float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
547 
548  // Get the acceleration in body axes
549  struct Int32Vect3 *body_accel_i;
550  body_accel_i = stateGetAccelBody_i();
551  ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
552 
553  int8_t i;
554  for (i = 0; i < 3; i++) {
557 
559 
560  //Calculate the angular acceleration via finite difference
562  - measurement_lowpass_filters[i].o[1]) * PERIODIC_FREQUENCY;
563 
564  // Calculate derivatives for estimation
565  float estimation_rate_d_prev = estimation_rate_d[i];
567  PERIODIC_FREQUENCY;
568  estimation_rate_dd[i] = (estimation_rate_d[i] - estimation_rate_d_prev) * PERIODIC_FREQUENCY;
569  }
570 
571  // subtract u*B from angular acceleration
572  float angular_acc_disturbance_estimate[INDI_OUTPUTS];
573  float_vect_diff(angular_acc_disturbance_estimate, angular_acceleration, angular_acc_prediction_filt, 3);
574 
575  if (in_flight) {
576  // Limit the estimated disturbance in yaw for drones that are stable in sideslip
577  BoundAbs(angular_acc_disturbance_estimate[2], stablization_indi_yaw_dist_limit);
578  } else {
579  // Not in flight, so don't estimate disturbance
580  float_vect_zero(angular_acc_disturbance_estimate, INDI_OUTPUTS);
581  }
582 
583  //The rates used for feedback are by default the measured rates.
584  //If there is a lot of noise on the gyroscope, it might be good to use the filtered value for feedback.
585  //Note that due to the delay, the PD controller may need relaxed gains.
586  struct FloatRates rates_filt;
587 #if STABILIZATION_INDI_FILTER_ROLL_RATE
588 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
589  rates_filt.p = update_butterworth_2_low_pass(&rates_filt_so[0], body_rates->p);
590 #else
591  rates_filt.p = update_first_order_low_pass(&rates_filt_fo[0], body_rates->p);
592 #endif
593 #else
594  rates_filt.p = body_rates->p;
595 #endif
596 #if STABILIZATION_INDI_FILTER_PITCH_RATE
597 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
598  rates_filt.q = update_butterworth_2_low_pass(&rates_filt_so[1], body_rates->q);
599 #else
600  rates_filt.q = update_first_order_low_pass(&rates_filt_fo[1], body_rates->q);
601 #endif
602 #else
603  rates_filt.q = body_rates->q;
604 #endif
605 #if STABILIZATION_INDI_FILTER_YAW_RATE
606 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
607  rates_filt.r = update_butterworth_2_low_pass(&rates_filt_so[2], body_rates->r);
608 #else
609  rates_filt.r = update_first_order_low_pass(&rates_filt_fo[2], body_rates->r);
610 #endif
611 #else
612  rates_filt.r = body_rates->r;
613 #endif
614 
615  // calculate the virtual control (reference acceleration) based on a PD controller
616  struct FloatRates rate_sp = stab_sp_to_rates_f(sp);
617  angular_accel_ref.p = (rate_sp.p - rates_filt.p) * indi_gains.rate.p;
618  angular_accel_ref.q = (rate_sp.q - rates_filt.q) * indi_gains.rate.q;
619  angular_accel_ref.r = (rate_sp.r - rates_filt.r) * indi_gains.rate.r;
620 
621  // compute virtual thrust
622  struct FloatVect3 v_thrust = { 0.f, 0.f, 0.f };
623  if (thrust->type == THRUST_INCR_SP) {
624  v_thrust.x = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_X);
625  v_thrust.y = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Y);
626  v_thrust.z = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Z);
627 
628  // Compute estimated thrust
629  struct FloatVect3 thrust_filt = { 0.f, 0.f, 0.f };
630  for (i = 0; i < INDI_NUM_ACT; i++) {
632 #if INDI_OUTPUTS == 5
634 #endif
635  }
636  // Add the current estimated thrust to the increment
637  VECT3_ADD(v_thrust, thrust_filt);
638  } else {
639  // build incremental thrust
640  float th_cmd_z = (float)th_sp_to_thrust_i(thrust, 0, THRUST_AXIS_Z);
641  for (i = 0; i < INDI_NUM_ACT; i++) {
642  v_thrust.z += th_cmd_z * Bwls[3][i];
643 #if INDI_OUTPUTS == 5
644  // TODO set X thrust from RC in the thrust input setpoint
645  cmd[COMMAND_THRUST_X] = radio_control.values[RADIO_CONTROL_THRUST_X];
646  v_thrust.x += cmd[COMMAND_THRUST_X] * Bwls[4][i];
647 #endif
648  }
649  v_thrust.y = 0.f;
650  }
651 
652  // This term compensates for the spinup torque in the yaw axis
653  float g2_times_u = float_vect_dot_product(g2, indi_u, INDI_NUM_ACT)/INDI_G_SCALING;
654 
655  if (in_flight) {
656  // Limit the estimated disturbance in yaw for drones that are stable in sideslip
657  BoundAbs(angular_acc_disturbance_estimate[2], stablization_indi_yaw_dist_limit);
658  } else {
659  // Not in flight, so don't estimate disturbance
660  float_vect_zero(angular_acc_disturbance_estimate, INDI_OUTPUTS);
661  }
662 
663  // The control objective in array format
664  indi_v[0] = (angular_accel_ref.p - angular_acc_disturbance_estimate[0]);
665  indi_v[1] = (angular_accel_ref.q - angular_acc_disturbance_estimate[1]);
666  indi_v[2] = (angular_accel_ref.r - angular_acc_disturbance_estimate[2]) + g2_times_u;
667  indi_v[3] = v_thrust.z;
668 #if INDI_OUTPUTS == 5
669  indi_v[4] = v_thrust.x;
670 #endif
671 
672 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
673  // Calculate the increment for each actuator
674  for (i = 0; i < INDI_NUM_ACT; i++) {
675  indi_u[i] = (g1g2_pseudo_inv[i][0] * indi_v[0])
676  + (g1g2_pseudo_inv[i][1] * indi_v[1])
677  + (g1g2_pseudo_inv[i][2] * indi_v[2])
678  + (g1g2_pseudo_inv[i][3] * indi_v[3]);
679  }
680 #else
682 
683  // WLS Control Allocator
684  for (i = 0; i < INDI_OUTPUTS; i++) {
685  wls_stab_p.v[i] = indi_v[i];
686  }
687  wls_alloc(&wls_stab_p, Bwls, 0, 0, 10);
688  for (i = 0; i < INDI_NUM_ACT; i++) {
689  indi_u [i] = wls_stab_p.u[i];
690  }
691 #endif
692 
693  // Bound the inputs to the actuators
694  for (i = 0; i < INDI_NUM_ACT; i++) {
695  if (act_is_servo[i]) {
696  BoundAbs(indi_u[i], MAX_PPRZ);
697  } else {
698  if (autopilot_get_motors_on()) {
699  Bound(indi_u[i], 0, MAX_PPRZ);
700  } else {
701  indi_u[i] = -MAX_PPRZ;
702  }
703  }
704  }
705 
706  // Use online effectiveness estimation only when flying
707  if (in_flight && indi_use_adaptive) {
708  lms_estimation();
709  }
710 
711  /*Commit the actuator command*/
712  for (i = 0; i < INDI_NUM_ACT; i++) {
713  actuators_pprz[i] = (int16_t) indi_u[i];
714  }
715 
716  //update thrust command such that the current is correctly estimated
717  cmd[COMMAND_THRUST] = 0;
718  for (i = 0; i < INDI_NUM_ACT; i++) {
719  cmd[COMMAND_THRUST] += actuator_state[i] * (int32_t) act_is_thruster_z[i];
720  }
721  cmd[COMMAND_THRUST] /= num_thrusters;
722 
723 }
724 
729 {
730  // Calculate the min and max increments
731  for (uint8_t i = 0; i < INDI_NUM_ACT; i++) {
734  wls_stab_p.u_pref[i] = act_pref[i];
735 
736 #ifdef GUIDANCE_INDI_MIN_THROTTLE
737  float airspeed = stateGetAirspeed_f();
738  //limit minimum thrust ap can give
739  if (!act_is_servo[i]) {
742  wls_stab_p.u_min[i] = GUIDANCE_INDI_MIN_THROTTLE;
743  } else {
744  wls_stab_p.u_min[i] = GUIDANCE_INDI_MIN_THROTTLE_FWD;
745  }
746  }
747  }
748 #endif
749  }
750 }
751 
760 void stabilization_indi_attitude_run(bool in_flight, struct StabilizationSetpoint *att_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
761 {
762  stab_att_sp_euler = stab_sp_to_eulers_i(att_sp); // stab_att_sp_euler.psi still used in ref..
763  stab_att_sp_quat = stab_sp_to_quat_i(att_sp); // quat attitude setpoint
764 
765  /* attitude error in float */
766  struct FloatQuat att_err;
767  struct FloatQuat *att_quat = stateGetNedToBodyQuat_f();
768  struct FloatQuat quat_sp = stab_sp_to_quat_f(att_sp);
769 
770  float_quat_inv_comp_norm_shortest(&att_err, att_quat, &quat_sp);
771 
772  struct FloatVect3 att_fb;
773 #if TILT_TWIST_CTRL
774  struct FloatQuat tilt;
775  struct FloatQuat twist;
776  float_quat_tilt_twist(&tilt, &twist, &att_err);
777  att_fb.x = tilt.qx;
778  att_fb.y = tilt.qy;
779  att_fb.z = twist.qz;
780 #else
781  att_fb.x = att_err.qx;
782  att_fb.y = att_err.qy;
783  att_fb.z = att_err.qz;
784 #endif
785 
786  // local variable to compute rate setpoints based on attitude error
787  struct FloatRates rate_sp;
788  // calculate the virtual control (reference acceleration) based on a PD controller
789  rate_sp.p = indi_gains.att.p * att_fb.x / indi_gains.rate.p;
790  rate_sp.q = indi_gains.att.q * att_fb.y / indi_gains.rate.q;
791  rate_sp.r = indi_gains.att.r * att_fb.z / indi_gains.rate.r;
792 
793  // Add feed-forward rates to the attitude feedback part
794  struct FloatRates ff_rates = stab_sp_to_rates_f(att_sp);
795  RATES_ADD(rate_sp, ff_rates);
796 
797  // Store for telemetry
798  angular_rate_ref.p = rate_sp.p;
799  angular_rate_ref.q = rate_sp.q;
800  angular_rate_ref.r = rate_sp.r;
801 
802  // Possibly we can use some bounding here
803  /*BoundAbs(rate_sp.r, 5.0);*/
804 
805  /* compute the INDI command */
806  struct StabilizationSetpoint sp = stab_sp_from_rates_f(&rate_sp);
807  stabilization_indi_rate_run(in_flight, &sp, thrust, cmd);
808 }
809 
817 {
818 #if STABILIZATION_INDI_RPM_FEEDBACK
819  float_vect_copy(actuator_state, act_obs, INDI_NUM_ACT);
820 #else
821  //actuator dynamics
822  int8_t i;
823  float UNUSED prev_actuator_state;
824  for (i = 0; i < INDI_NUM_ACT; i++) {
825  prev_actuator_state = actuator_state[i];
826 
828  + act_dyn_discrete[i] * (indi_u[i] - actuator_state[i]);
829 
830 #ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
831  if ((actuator_state[i] - prev_actuator_state) > act_rate_limit[i]) {
832  actuator_state[i] = prev_actuator_state + act_rate_limit[i];
833  } else if ((actuator_state[i] - prev_actuator_state) < -act_rate_limit[i]) {
834  actuator_state[i] = prev_actuator_state - act_rate_limit[i];
835  }
836 #endif
837  }
838 
839 #endif
840 }
841 
852 void calc_g1_element(float ddx_error, int8_t i, int8_t j, float mu)
853 {
854  g1_est[i][j] = g1_est[i][j] - du_estimation[j] * mu * ddx_error;
855 }
856 
866 void calc_g2_element(float ddx_error, int8_t j, float mu)
867 {
868  g2_est[j] = g2_est[j] - ddu_estimation[j] * mu * ddx_error;
869 }
870 
876 void lms_estimation(void)
877 {
878 
879  // Get the acceleration in body axes
880  struct Int32Vect3 *body_accel_i;
881  body_accel_i = stateGetAccelBody_i();
882  ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
883 
884  // Filter the acceleration in z axis
886 
887  // Calculate the derivative of the acceleration via finite difference
888  float indi_accel_d = (acceleration_lowpass_filter.o[0]
889  - acceleration_lowpass_filter.o[1]) * PERIODIC_FREQUENCY;
890 
891  // Use xml setting for adaptive mu for lms
892  // Set default value if not defined
893 #ifndef STABILIZATION_INDI_ADAPTIVE_MU
894  float adaptive_mu_lr = 0.001;
895 #else
896  float adaptive_mu_lr = STABILIZATION_INDI_ADAPTIVE_MU;
897 #endif
898 
899  // scale the inputs to avoid numerical errors
900  float_vect_smul(du_estimation, actuator_state_filt_vectd, adaptive_mu_lr, INDI_NUM_ACT);
901  float_vect_smul(ddu_estimation, actuator_state_filt_vectdd, adaptive_mu_lr / PERIODIC_FREQUENCY, INDI_NUM_ACT);
902 
903  float ddx_estimation[INDI_OUTPUTS] = {estimation_rate_dd[0], estimation_rate_dd[1], estimation_rate_dd[2], indi_accel_d};
904 
905  //Estimation of G
906  // TODO: only estimate when du_norm2 is large enough (enough input)
907  /*float du_norm2 = du_estimation[0]*du_estimation[0] + du_estimation[1]*du_estimation[1] +du_estimation[2]*du_estimation[2] + du_estimation[3]*du_estimation[3];*/
908  int8_t i;
909  for (i = 0; i < INDI_OUTPUTS; i++) {
910  // Calculate the error between prediction and measurement
911  float ddx_error = - ddx_estimation[i];
912  int8_t j;
913  for (j = 0; j < INDI_NUM_ACT; j++) {
914  ddx_error += g1_est[i][j] * du_estimation[j];
915  if (i == 2) {
916  // Changing the momentum of the rotors gives a counter torque
917  ddx_error += g2_est[j] * ddu_estimation[j];
918  }
919  }
920 
921  // when doing the yaw axis, also use G2
922  if (i == 2) {
923  for (j = 0; j < INDI_NUM_ACT; j++) {
924  calc_g2_element(ddx_error, j, mu2);
925  }
926  } else if (i == 3) {
927  // If the acceleration change is very large (rough landing), don't adapt
928  if (fabs(indi_accel_d) > 60.0) {
929  ddx_error = 0.0;
930  }
931  }
932 
933  // Calculate the row of the G1 matrix corresponding to this axis
934  for (j = 0; j < INDI_NUM_ACT; j++) {
935  calc_g1_element(ddx_error, i, j, mu1[i]);
936  }
937  }
938 
939  bound_g_mat();
940 
941  // Save the calculated matrix to G1 and G2
942  // until thrust is included, first part of the array
943  float_vect_copy(g1[0], g1_est[0], INDI_OUTPUTS * INDI_NUM_ACT);
944  float_vect_copy(g2, g2_est, INDI_NUM_ACT);
945 
946  // Calculate sum of G1 and G2 for Bwls
947  sum_g1_g2();
948 
949 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
950  // Calculate the inverse of (G1+G2)
951  calc_g1g2_pseudo_inv();
952 #endif
953 }
954 
959 void sum_g1_g2(void)
960 {
961  int8_t i;
962  int8_t j;
963  for (i = 0; i < INDI_OUTPUTS; i++) {
964  for (j = 0; j < INDI_NUM_ACT; j++) {
965  if (i != 2) {
966  g1g2[i][j] = g1[i][j] / INDI_G_SCALING;
967  } else {
968  g1g2[i][j] = (g1[i][j] + g2[j]) / INDI_G_SCALING;
969  }
970  }
971  }
972 }
973 
974 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
979 void calc_g1g2_pseudo_inv(void)
980 {
981  //G1G2*transpose(G1G2)
982  //calculate matrix multiplication of its transpose INDI_OUTPUTSxnum_act x num_actxINDI_OUTPUTS
983  float element = 0;
984  int8_t row;
985  int8_t col;
986  int8_t i;
987  for (row = 0; row < INDI_OUTPUTS; row++) {
988  for (col = 0; col < INDI_OUTPUTS; col++) {
989  element = 0;
990  for (i = 0; i < INDI_NUM_ACT; i++) {
991  element = element + g1g2[row][i] * g1g2[col][i];
992  }
993  g1g2_trans_mult[row][col] = element;
994  }
995  }
996 
997  //there are numerical errors if the scaling is not right.
998  float_vect_scale(g1g2_trans_mult[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
999 
1000  //inverse of 4x4 matrix
1002 
1003  //scale back
1004  float_vect_scale(g1g2inv[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
1005 
1006  //G1G2'*G1G2inv
1007  //calculate matrix multiplication INDI_NUM_ACTxINDI_OUTPUTS x INDI_OUTPUTSxINDI_OUTPUTS
1008  for (row = 0; row < INDI_NUM_ACT; row++) {
1009  for (col = 0; col < INDI_OUTPUTS; col++) {
1010  element = 0;
1011  for (i = 0; i < INDI_OUTPUTS; i++) {
1012  element = element + g1g2[i][row] * g1g2inv[col][i];
1013  }
1014  g1g2_pseudo_inv[row][col] = element;
1015  }
1016  }
1017 }
1018 #endif
1019 
1020 #if STABILIZATION_INDI_RPM_FEEDBACK
1021 static void act_feedback_cb(uint8_t sender_id UNUSED, struct act_feedback_t *feedback, uint8_t num_act)
1022 {
1023  int8_t i;
1024  for (i = 0; i < num_act; i++) {
1025  // Sanity check that index is valid
1026  if (feedback[i].idx < INDI_NUM_ACT && feedback[i].set.rpm) {
1027  int8_t idx = feedback[i].idx;
1028  act_obs[idx] = (feedback[i].rpm - get_servo_min(idx));
1029  act_obs[idx] *= (MAX_PPRZ / (float)(get_servo_max(idx) - get_servo_min(idx)));
1030  Bound(act_obs[idx], 0, MAX_PPRZ);
1031  }
1032  }
1033 }
1034 #endif
1035 
1036 static void bound_g_mat(void)
1037 {
1038  int8_t i;
1039  int8_t j;
1040  for (j = 0; j < INDI_NUM_ACT; j++) {
1041  float max_limit;
1042  float min_limit;
1043 
1044  // Limit the values of the estimated G1 matrix
1045  for (i = 0; i < INDI_OUTPUTS; i++) {
1046  if (g1_init[i][j] > 0.0) {
1047  max_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1048  min_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1049  } else {
1050  max_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1051  min_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1052  }
1053 
1054  if (g1_est[i][j] > max_limit) {
1055  g1_est[i][j] = max_limit;
1056  }
1057  if (g1_est[i][j] < min_limit) {
1058  g1_est[i][j] = min_limit;
1059  }
1060  }
1061 
1062  // Do the same for the G2 matrix
1063  if (g2_init[j] > 0.0) {
1064  max_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1065  min_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1066  } else {
1067  max_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1068  min_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1069  }
1070 
1071  if (g2_est[j] > max_limit) {
1072  g2_est[j] = max_limit;
1073  }
1074  if (g2_est[j] < min_limit) {
1075  g2_est[j] = min_limit;
1076  }
1077  }
1078 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:295
uint8_t last_wp UNUSED
float q
in rad/s
float phi
in radians
float p
in rad/s
float r
in rad/s
float theta
in radians
float psi
in radians
static void float_vect_zero(float *a, const int n)
a = 0
void float_quat_inv_comp_norm_shortest(struct FloatQuat *b2c, struct FloatQuat *a2b, struct FloatQuat *a2c)
Composition (multiplication) of two quaternions with normalization.
static void float_vect_smul(float *o, const float *a, const float s, const int n)
o = a * s
static void float_mat_vect_mul(float *o, float **a, float *b, int m, int n)
o = a * b
static void float_vect_scale(float *a, const float s, const int n)
a *= s
static float float_vect_dot_product(const float *a, const float *b, const int n)
a.b
static void float_vect_copy(float *a, const float *b, const int n)
a = b
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
static void float_vect_diff(float *o, const float *a, const float *b, const int n)
o = a - b
void float_quat_tilt_twist(struct FloatQuat *tilt, struct FloatQuat *twist, struct FloatQuat *quat)
Tilt twist decomposition of a quaternion (z axis)
bool float_mat_inv_4d(float invOut[4][4], float mat_in[4][4])
4x4 Matrix inverse
euler angles
Roation quaternion.
angular rates
#define RATES_ADD(_a, _b)
Definition: pprz_algebra.h:344
#define QUAT_FLOAT_OF_BFP(_qf, _qi)
Definition: pprz_algebra.h:745
#define VECT3_ADD(_a, _b)
Definition: pprz_algebra.h:147
#define EULERS_FLOAT_OF_BFP(_ef, _ei)
Definition: pprz_algebra.h:709
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
Definition: pprz_algebra.h:795
euler angles
Rotation quaternion.
static struct Int32Quat * stateGetNedToBodyQuat_i(void)
Get vehicle body attitude quaternion (int).
Definition: state.h:1113
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1143
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
static struct FloatRates * stateGetBodyRates_f(void)
Get vehicle body angular rate (float).
Definition: state.h:1200
static struct Int32Vect3 * stateGetAccelBody_i(void)
Get acceleration in Body coordinates (int).
Definition: state.h:953
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition: state.h:1407
Butterworth2LowPass thrust_filt
static float p[2][2]
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static float update_first_order_low_pass(struct FirstOrderLowPass *filter, float value)
Update first order low pass filter state with a new value.
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static void init_first_order_low_pass(struct FirstOrderLowPass *filter, float tau, float sample_time, float value)
Init first order low pass filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
First order low pass filter structure.
Second order low pass filter structure.
Hardware independent API for actuators (servos, motor controllers).
int32_t rpm
RPM.
Definition: actuators.h:51
uint8_t idx
General index of the actuators (generated in airframe.h)
Definition: actuators.h:45
static float mu
Physical model parameters.
Definition: nps_fdm_rover.c:60
static uint32_t idx
#define MAX_PPRZ
Definition: paparazzi.h:8
static abi_event act_feedback_ev
Paparazzi floating point algebra.
struct RadioControl radio_control
Definition: radio_control.c:33
Generic interface for radio control modules.
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
Definition: radio_control.h:67
struct HorizontalGuidance guidance_h
Definition: guidance_h.c:45
#define GUIDANCE_H_MODE_NAV
Definition: guidance_h.h:58
#define GUIDANCE_H_MODE_HOVER
Definition: guidance_h.h:57
struct FloatRates stab_sp_to_rates_f(struct StabilizationSetpoint *sp)
float th_sp_to_incr_f(struct ThrustSetpoint *th, int32_t thrust, uint8_t axis)
struct Int32Quat stab_sp_to_quat_i(struct StabilizationSetpoint *sp)
struct Int32Eulers stab_sp_to_eulers_i(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_rates_f(struct FloatRates *rates)
struct FloatQuat stab_sp_to_quat_f(struct StabilizationSetpoint *sp)
int32_t th_sp_to_thrust_i(struct ThrustSetpoint *th, int32_t thrust, uint8_t axis)
#define THRUST_AXIS_X
#define THRUST_AXIS_Z
#define THRUST_AXIS_Y
Quaternion transformation functions.
Read an attitude setpoint from the RC.
static void calc_g1_element(float dx_error, int8_t i, int8_t j, float mu_extra)
Butterworth2LowPass acceleration_lowpass_filter
static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
void stabilization_indi_enter(void)
Function that resets important values upon engaging INDI.
Butterworth2LowPass acceleration_body_x_filter
float act_pref[INDI_NUM_ACT]
float * Bwls[INDI_OUTPUTS]
int32_t stabilization_att_indi_cmd[COMMANDS_NB]
struct Indi_gains indi_gains
void WEAK stabilization_indi_set_wls_settings(void)
Function that sets the u_min, u_max and u_pref if function not elsewhere defined.
#define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
bool act_is_thruster_x[INDI_NUM_ACT]
bool act_is_servo[INDI_NUM_ACT]
static struct FirstOrderLowPass rates_filt_fo[3]
float angular_acceleration[3]
static void send_wls_v_stab(struct transport_tx *trans, struct link_device *dev)
int32_t num_thrusters
float actuator_state_filt_vectd[INDI_NUM_ACT]
float r_filt
#define STABILIZATION_INDI_FILT_CUTOFF_P
static void bound_g_mat(void)
float mu1[INDI_OUTPUTS]
#define STABILIZATION_INDI_FILT_CUTOFF_Q
struct WLS_t wls_stab_p
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
static void calc_g2_element(float dx_error, int8_t j, float mu_extra)
float q_filt
static struct Int32Eulers stab_att_sp_euler
static void send_wls_u_stab(struct transport_tx *trans, struct link_device *dev)
float estimation_rate_d[INDI_NUM_ACT]
float du_estimation[INDI_NUM_ACT]
float actuator_state_filt_vectdd[INDI_NUM_ACT]
Butterworth2LowPass measurement_lowpass_filters[3]
void stabilization_indi_update_filt_freq(float freq)
bool act_is_thruster_z[INDI_NUM_ACT]
float g2[INDI_NUM_ACT]
struct FloatVect3 body_accel_f
float ddu_estimation[INDI_NUM_ACT]
float estimation_rate_dd[INDI_NUM_ACT]
float mu2
float act_obs[INDI_NUM_ACT]
int32_t num_thrusters_x
float g1[INDI_OUTPUTS][INDI_NUM_ACT]
void stabilization_indi_init(void)
Function that initializes important values upon engaging INDI.
struct FloatRates angular_rate_ref
float stablization_indi_yaw_dist_limit
Limit the maximum specific moment that can be compensated (units rad/s^2)
float g1g2inv[INDI_OUTPUTS][INDI_OUTPUTS]
void stabilization_indi_attitude_run(bool in_flight, struct StabilizationSetpoint *att_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
float actuator_state_filt_vect[INDI_NUM_ACT]
void stabilization_indi_rate_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
float act_first_order_cutoff[INDI_NUM_ACT]
float act_dyn_discrete[INDI_NUM_ACT]
struct FloatRates angular_accel_ref
float g1g2_trans_mult[INDI_OUTPUTS][INDI_OUTPUTS]
#define STABILIZATION_INDI_FILT_CUTOFF_R
bool indi_use_adaptive
float g2_init[INDI_NUM_ACT]
Butterworth2LowPass estimation_input_lowpass_filters[INDI_NUM_ACT]
void sum_g1_g2(void)
Function that sums g1 and g2 to obtain the g1g2 matrix It also undoes the scaling that was done to ma...
float g1g2_pseudo_inv[INDI_NUM_ACT][INDI_OUTPUTS]
float g2_est[INDI_NUM_ACT]
float g1_init[INDI_OUTPUTS][INDI_NUM_ACT]
static struct Int32Quat stab_att_sp_quat
float actuator_state[INDI_NUM_ACT]
static void lms_estimation(void)
Function that estimates the control effectiveness of each actuator online.
static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
#define INDI_ALLOWED_G_FACTOR
float g1_est[INDI_OUTPUTS][INDI_NUM_ACT]
float indi_v[INDI_OUTPUTS]
float stabilization_indi_filter_freq
float indi_u[INDI_NUM_ACT]
static void get_actuator_state(void)
Function that tries to get actuator feedback.
Butterworth2LowPass actuator_lowpass_filters[INDI_NUM_ACT]
void init_filters(void)
Function that resets the filters to zeros.
Butterworth2LowPass estimation_output_lowpass_filters[3]
#define INDI_G_SCALING
#define STABILIZATION_INDI_ESTIMATION_FILT_CUTOFF
#define STABILIZATION_INDI_FILT_CUTOFF
struct FloatRates rate
struct FloatRates att
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
Stabilization setpoint.
Definition: stabilization.h:53
union StabilizationSetpoint::@278 sp
Thrust setpoint // TODO to a setpoint header Structure to store the desired thrust vector with differ...
Definition: stabilization.h:82
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
static void act_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback, uint8_t num_act)
RPM callback for RPM based control throttle curves.
int int32_t
Typedef defining 32 bit int type.
Definition: vl53l1_types.h:83
short int16_t
Typedef defining 16 bit short type.
Definition: vl53l1_types.h:93
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
signed char int8_t
Typedef defining 8 bit char type.
Definition: vl53l1_types.h:103
void send_wls_v(char *name, struct WLS_t *WLS_p, struct transport_tx *trans, struct link_device *dev)
Definition: wls_alloc.c:61
void wls_alloc(struct WLS_t *WLS_p, float **B, float *u_guess, float *W_init, int imax)
active set algorithm for control allocation
Definition: wls_alloc.c:119
void send_wls_u(char *name, struct WLS_t *WLS_p, struct transport_tx *trans, struct link_device *dev)
Definition: wls_alloc.c:71
float u[WLS_N_U_MAX]
Definition: wls_alloc.h:71
float u_min[WLS_N_U_MAX]
Definition: wls_alloc.h:75
float u_max[WLS_N_U_MAX]
Definition: wls_alloc.h:76
float u_pref[WLS_N_U_MAX]
Definition: wls_alloc.h:74
float v[WLS_N_V_MAX]
Definition: wls_alloc.h:70
int nu
Definition: wls_alloc.h:67