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 #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
301 static void send_wls_v_stab(struct transport_tx *trans, struct link_device *dev)
302 {
303  send_wls_v("stab", &wls_stab_p, trans, dev);
304 }
305 static void send_wls_u_stab(struct transport_tx *trans, struct link_device *dev)
306 {
307  send_wls_u("stab", &wls_stab_p, trans, dev);
308 }
309 #endif
310 static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
311 {
312  pprz_msg_send_EFF_MAT_STAB(trans, dev, AC_ID,
313  INDI_NUM_ACT, g1g2[0],
314  INDI_NUM_ACT, g1g2[1],
315  INDI_NUM_ACT, g1g2[2],
316  INDI_NUM_ACT, g1g2[3],
317  INDI_NUM_ACT, g2_est);
318 }
319 
320 static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
321 {
322  struct Int32Quat *quat = stateGetNedToBodyQuat_i();
323  pprz_msg_send_AHRS_REF_QUAT(trans, dev, AC_ID,
328  &(quat->qi),
329  &(quat->qx),
330  &(quat->qy),
331  &(quat->qz));
332 }
333 
334 static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
335 {
336  float zero = 0.0;
337  struct FloatRates *body_rates = stateGetBodyRates_f();
338  struct FloatEulers att, att_sp;
339 #if GUIDANCE_INDI_HYBRID
341  struct FloatQuat stab_att_sp_quat_f;
342  QUAT_FLOAT_OF_BFP(stab_att_sp_quat_f, stab_att_sp_quat);
343  float_eulers_of_quat_zxy(&att_sp, &stab_att_sp_quat_f);
344 #else
345  att = *stateGetNedToBodyEulers_f();
347 #endif
348  float temp_att[3] = {att.phi, att.theta, att.psi};
349  float temp_att_ref[3] = {att_sp.phi, att_sp.theta, att_sp.psi};
350  float temp_rate[3] = {body_rates->p, body_rates->q, body_rates->r};
351  float temp_rate_ref[3] = {angular_rate_ref.p, angular_rate_ref.q, angular_rate_ref.r};
352  float temp_ang_acc_ref[3] = {angular_accel_ref.p, angular_accel_ref.q, angular_accel_ref.r};
353  pprz_msg_send_STAB_ATTITUDE(trans, dev, AC_ID,
354  1, &zero, // att des
355  3, temp_att, // att
356  3, temp_att_ref, // att ref
357  3, temp_rate, // rate
358  3, temp_rate_ref, // rate ref
359  3, angular_acceleration, // ang.acc = rate.diff
360  3, temp_ang_acc_ref, // ang.acc.ref
361  1, &zero, // jerk ref
362  1, &zero); // u
363 }
364 #endif
365 
370 {
371  // Initialize filters
372  init_filters();
373 
374  int8_t i;
375 // If the deprecated STABILIZATION_INDI_ACT_DYN is used, convert it to the new FREQUENCY format
376 #ifdef STABILIZATION_INDI_ACT_FREQ
377  // Initialize the array of pointers to the rows of g1g2
378  for (i = 0; i < INDI_NUM_ACT; i++) {
379  act_dyn_discrete[i] = 1-exp(-act_first_order_cutoff[i]/PERIODIC_FREQUENCY);
380  }
381 #endif
382 
383 #if STABILIZATION_INDI_RPM_FEEDBACK
384  AbiBindMsgACT_FEEDBACK(STABILIZATION_INDI_ACT_FEEDBACK_ID, &act_feedback_ev, act_feedback_cb);
385 #endif
386 
389  float_vect_zero(estimation_rate_d, INDI_NUM_ACT);
390  float_vect_zero(estimation_rate_dd, INDI_NUM_ACT);
392 
393  //Calculate G1G2
394  sum_g1_g2();
395 
396  // Do not compute if not needed
397 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
398  //Calculate G1G2_PSEUDO_INVERSE
399  calc_g1g2_pseudo_inv();
400 #endif
401 
402  // Initialize the array of pointers to the rows of g1g2
403  for (i = 0; i < INDI_OUTPUTS; i++) {
404  Bwls[i] = g1g2[i];
405  }
406 
407  // Initialize the estimator matrices
408  float_vect_copy(g1_est[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
409  float_vect_copy(g2_est, g2, INDI_NUM_ACT);
410  // Remember the initial matrices
411  float_vect_copy(g1_init[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
412  float_vect_copy(g2_init, g2, INDI_NUM_ACT);
413 
414  // Assume all non-servos are delivering thrust
415  num_thrusters = INDI_NUM_ACT;
416  num_thrusters_x = 0;
417  for (i = 0; i < INDI_NUM_ACT; i++) {
420 
422 
424  }
425 
426 #if PERIODIC_TELEMETRY
430  #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
433  #endif
434 #endif
435 }
436 
446 {
447  float_vect_zero(du_estimation, INDI_NUM_ACT);
448  float_vect_zero(ddu_estimation, INDI_NUM_ACT);
449 }
450 
452 {
454  float tau = 1.0 / (2.0 * M_PI * freq);
455  float sample_time = 1.0 / PERIODIC_FREQUENCY;
456 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
457  init_butterworth_2_low_pass(&rates_filt_so[0], tau, sample_time, stateGetBodyRates_f()->p);
458  init_butterworth_2_low_pass(&rates_filt_so[1], tau, sample_time, stateGetBodyRates_f()->q);
459  init_butterworth_2_low_pass(&rates_filt_so[2], tau, sample_time, stateGetBodyRates_f()->r);
460 #else
462  init_first_order_low_pass(&rates_filt_fo[1], tau, sample_time, stateGetBodyRates_f()->q);
463  init_first_order_low_pass(&rates_filt_fo[2], tau, sample_time, stateGetBodyRates_f()->r);
464 #endif
465 }
466 
470 void init_filters(void)
471 {
472  // tau = 1/(2*pi*Fc)
473  float tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF);
474  float tau_est = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_ESTIMATION_FILT_CUTOFF);
475  float sample_time = 1.0 / PERIODIC_FREQUENCY;
476  // Filtering of the gyroscope
477  int8_t i;
478  for (i = 0; i < 3; i++) {
479  init_butterworth_2_low_pass(&measurement_lowpass_filters[i], tau, sample_time, 0.0);
480  init_butterworth_2_low_pass(&estimation_output_lowpass_filters[i], tau_est, sample_time, 0.0);
481  }
482 
483  // Filtering of the actuators
484  for (i = 0; i < INDI_NUM_ACT; i++) {
485  init_butterworth_2_low_pass(&actuator_lowpass_filters[i], tau, sample_time, 0.0);
486  init_butterworth_2_low_pass(&estimation_input_lowpass_filters[i], tau_est, sample_time, 0.0);
487  }
488 
489  // Filtering the bodyx acceleration with same cutoff as gyroscope
491 
492  // Filtering of the accel body z
493  init_butterworth_2_low_pass(&acceleration_lowpass_filter, tau_est, sample_time, 0.0);
494 
495 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
496  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P);
497  init_butterworth_2_low_pass(&rates_filt_so[0], tau, sample_time, 0.0);
498  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q);
499  init_butterworth_2_low_pass(&rates_filt_so[1], tau, sample_time, 0.0);
500  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R);
501  init_butterworth_2_low_pass(&rates_filt_so[2], tau, sample_time, 0.0);
502 #else
503  // Init rate filter for feedback
504  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)};
505 
506  init_first_order_low_pass(&rates_filt_fo[0], time_constants[0], sample_time, stateGetBodyRates_f()->p);
507  init_first_order_low_pass(&rates_filt_fo[1], time_constants[1], sample_time, stateGetBodyRates_f()->q);
508  init_first_order_low_pass(&rates_filt_fo[2], time_constants[2], sample_time, stateGetBodyRates_f()->r);
509 #endif
510 }
511 
520 void stabilization_indi_rate_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
521 {
522 
523  // Propagate actuator filters
525  float actuator_state_filt_vect_prev[INDI_NUM_ACT];
526  for (int i = 0; i < INDI_NUM_ACT; i++) {
530  actuator_state_filt_vect_prev[i] = actuator_lowpass_filters[i].o[1];
531 
532  // calculate derivatives for estimation
533  float actuator_state_filt_vectd_prev = actuator_state_filt_vectd[i];
535  PERIODIC_FREQUENCY;
536  actuator_state_filt_vectdd[i] = (actuator_state_filt_vectd[i] - actuator_state_filt_vectd_prev) * PERIODIC_FREQUENCY;
537  }
538 
539  // Use the last actuator state for this computation
540  float g2_times_u_act_filt = float_vect_dot_product(g2, actuator_state_filt_vect_prev, INDI_NUM_ACT)/INDI_G_SCALING;
541 
542  // Predict angular acceleration u*B
543  float angular_acc_prediction_filt[INDI_OUTPUTS];
544  float_mat_vect_mul(angular_acc_prediction_filt, Bwls, actuator_state_filt_vect, INDI_OUTPUTS, INDI_NUM_ACT);
545  angular_acc_prediction_filt[2] -= g2_times_u_act_filt;
546 
547  /* Propagate the filter on the gyroscopes */
548  struct FloatRates *body_rates = stateGetBodyRates_f();
549  float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
550 
551  // Get the acceleration in body axes
552  struct Int32Vect3 *body_accel_i;
553  body_accel_i = stateGetAccelBody_i();
554  ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
555 
556  int8_t i;
557  for (i = 0; i < 3; i++) {
560 
562 
563  //Calculate the angular acceleration via finite difference
565  - measurement_lowpass_filters[i].o[1]) * PERIODIC_FREQUENCY;
566 
567  // Calculate derivatives for estimation
568  float estimation_rate_d_prev = estimation_rate_d[i];
570  PERIODIC_FREQUENCY;
571  estimation_rate_dd[i] = (estimation_rate_d[i] - estimation_rate_d_prev) * PERIODIC_FREQUENCY;
572  }
573 
574  // subtract u*B from angular acceleration
575  float angular_acc_disturbance_estimate[INDI_OUTPUTS];
576  float_vect_diff(angular_acc_disturbance_estimate, angular_acceleration, angular_acc_prediction_filt, 3);
577 
578  if (in_flight) {
579  // Limit the estimated disturbance in yaw for drones that are stable in sideslip
580  BoundAbs(angular_acc_disturbance_estimate[2], stablization_indi_yaw_dist_limit);
581  } else {
582  // Not in flight, so don't estimate disturbance
583  float_vect_zero(angular_acc_disturbance_estimate, INDI_OUTPUTS);
584  }
585 
586  //The rates used for feedback are by default the measured rates.
587  //If there is a lot of noise on the gyroscope, it might be good to use the filtered value for feedback.
588  //Note that due to the delay, the PD controller may need relaxed gains.
589  struct FloatRates rates_filt;
590 #if STABILIZATION_INDI_FILTER_ROLL_RATE
591 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
592  rates_filt.p = update_butterworth_2_low_pass(&rates_filt_so[0], body_rates->p);
593 #else
594  rates_filt.p = update_first_order_low_pass(&rates_filt_fo[0], body_rates->p);
595 #endif
596 #else
597  rates_filt.p = body_rates->p;
598 #endif
599 #if STABILIZATION_INDI_FILTER_PITCH_RATE
600 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
601  rates_filt.q = update_butterworth_2_low_pass(&rates_filt_so[1], body_rates->q);
602 #else
603  rates_filt.q = update_first_order_low_pass(&rates_filt_fo[1], body_rates->q);
604 #endif
605 #else
606  rates_filt.q = body_rates->q;
607 #endif
608 #if STABILIZATION_INDI_FILTER_YAW_RATE
609 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
610  rates_filt.r = update_butterworth_2_low_pass(&rates_filt_so[2], body_rates->r);
611 #else
612  rates_filt.r = update_first_order_low_pass(&rates_filt_fo[2], body_rates->r);
613 #endif
614 #else
615  rates_filt.r = body_rates->r;
616 #endif
617 
618  // calculate the virtual control (reference acceleration) based on a PD controller
619  struct FloatRates rate_sp = stab_sp_to_rates_f(sp);
620  angular_accel_ref.p = (rate_sp.p - rates_filt.p) * indi_gains.rate.p;
621  angular_accel_ref.q = (rate_sp.q - rates_filt.q) * indi_gains.rate.q;
622  angular_accel_ref.r = (rate_sp.r - rates_filt.r) * indi_gains.rate.r;
623 
624  // compute virtual thrust
625  struct FloatVect3 v_thrust = { 0.f, 0.f, 0.f };
626  if (thrust->type == THRUST_INCR_SP) {
627  v_thrust.x = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_X);
628  v_thrust.y = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Y);
629  v_thrust.z = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Z);
630 
631  // Compute estimated thrust
632  struct FloatVect3 thrust_filt = { 0.f, 0.f, 0.f };
633  for (i = 0; i < INDI_NUM_ACT; i++) {
635 #if INDI_OUTPUTS == 5
637 #endif
638  }
639  // Add the current estimated thrust to the increment
640  VECT3_ADD(v_thrust, thrust_filt);
641  } else {
642  // build incremental thrust
643  float th_cmd_z = (float)th_sp_to_thrust_i(thrust, 0, THRUST_AXIS_Z);
644  for (i = 0; i < INDI_NUM_ACT; i++) {
645  v_thrust.z += th_cmd_z * Bwls[3][i];
646 #if INDI_OUTPUTS == 5
647  // TODO set X thrust from RC in the thrust input setpoint
648  cmd[COMMAND_THRUST_X] = radio_control.values[RADIO_CONTROL_THRUST_X];
649  v_thrust.x += cmd[COMMAND_THRUST_X] * Bwls[4][i];
650 #endif
651  }
652  v_thrust.y = 0.f;
653  }
654 
655  // This term compensates for the spinup torque in the yaw axis
656  float g2_times_u = float_vect_dot_product(g2, indi_u, INDI_NUM_ACT)/INDI_G_SCALING;
657 
658  if (in_flight) {
659  // Limit the estimated disturbance in yaw for drones that are stable in sideslip
660  BoundAbs(angular_acc_disturbance_estimate[2], stablization_indi_yaw_dist_limit);
661  } else {
662  // Not in flight, so don't estimate disturbance
663  float_vect_zero(angular_acc_disturbance_estimate, INDI_OUTPUTS);
664  }
665 
666  // The control objective in array format
667  indi_v[0] = (angular_accel_ref.p - angular_acc_disturbance_estimate[0]);
668  indi_v[1] = (angular_accel_ref.q - angular_acc_disturbance_estimate[1]);
669  indi_v[2] = (angular_accel_ref.r - angular_acc_disturbance_estimate[2]) + g2_times_u;
670  indi_v[3] = v_thrust.z;
671 #if INDI_OUTPUTS == 5
672  indi_v[4] = v_thrust.x;
673 #endif
674 
675 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
676  // Calculate the increment for each actuator
677  for (i = 0; i < INDI_NUM_ACT; i++) {
678  indi_u[i] = (g1g2_pseudo_inv[i][0] * indi_v[0])
679  + (g1g2_pseudo_inv[i][1] * indi_v[1])
680  + (g1g2_pseudo_inv[i][2] * indi_v[2])
681  + (g1g2_pseudo_inv[i][3] * indi_v[3]);
682  }
683 #else
685 
686  // WLS Control Allocator
687  for (i = 0; i < INDI_OUTPUTS; i++) {
688  wls_stab_p.v[i] = indi_v[i];
689  }
690  wls_alloc(&wls_stab_p, Bwls, 0, 0, 10);
691  for (i = 0; i < INDI_NUM_ACT; i++) {
692  indi_u [i] = wls_stab_p.u[i];
693  }
694 #endif
695 
696  // Bound the inputs to the actuators
697  for (i = 0; i < INDI_NUM_ACT; i++) {
698  if (act_is_servo[i]) {
699  BoundAbs(indi_u[i], MAX_PPRZ);
700  } else {
701  if (autopilot_get_motors_on()) {
702  Bound(indi_u[i], 0, MAX_PPRZ);
703  } else {
704  indi_u[i] = -MAX_PPRZ;
705  }
706  }
707  }
708 
709  // Use online effectiveness estimation only when flying
710  if (in_flight && indi_use_adaptive) {
711  lms_estimation();
712  }
713 
714  /*Commit the actuator command*/
715  for (i = 0; i < INDI_NUM_ACT; i++) {
716  actuators_pprz[i] = (int16_t) indi_u[i];
717  }
718 
719  //update thrust command such that the current is correctly estimated
720  cmd[COMMAND_THRUST] = 0;
721  for (i = 0; i < INDI_NUM_ACT; i++) {
722  cmd[COMMAND_THRUST] += actuator_state[i] * (int32_t) act_is_thruster_z[i];
723  }
724  cmd[COMMAND_THRUST] /= num_thrusters;
725 
726 }
727 
731 #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
733 {
734  // Calculate the min and max increments
735  for (uint8_t i = 0; i < INDI_NUM_ACT; i++) {
738  wls_stab_p.u_pref[i] = act_pref[i];
739 
740 #ifdef GUIDANCE_INDI_MIN_THROTTLE
741  float airspeed = stateGetAirspeed_f();
742  //limit minimum thrust ap can give
743  if (!act_is_servo[i]) {
746  wls_stab_p.u_min[i] = GUIDANCE_INDI_MIN_THROTTLE;
747  } else {
748  wls_stab_p.u_min[i] = GUIDANCE_INDI_MIN_THROTTLE_FWD;
749  }
750  }
751  }
752 #endif
753  }
754 }
755 #endif
756 
765 void stabilization_indi_attitude_run(bool in_flight, struct StabilizationSetpoint *att_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
766 {
767  stab_att_sp_euler = stab_sp_to_eulers_i(att_sp); // stab_att_sp_euler.psi still used in ref..
768  stab_att_sp_quat = stab_sp_to_quat_i(att_sp); // quat attitude setpoint
769 
770  /* attitude error in float */
771  struct FloatQuat att_err;
772  struct FloatQuat *att_quat = stateGetNedToBodyQuat_f();
773  struct FloatQuat quat_sp = stab_sp_to_quat_f(att_sp);
774 
775  float_quat_inv_comp_norm_shortest(&att_err, att_quat, &quat_sp);
776 
777  struct FloatVect3 att_fb;
778 #if TILT_TWIST_CTRL
779  struct FloatQuat tilt;
780  struct FloatQuat twist;
781  float_quat_tilt_twist(&tilt, &twist, &att_err);
782  att_fb.x = tilt.qx;
783  att_fb.y = tilt.qy;
784  att_fb.z = twist.qz;
785 #else
786  att_fb.x = att_err.qx;
787  att_fb.y = att_err.qy;
788  att_fb.z = att_err.qz;
789 #endif
790 
791  // local variable to compute rate setpoints based on attitude error
792  struct FloatRates rate_sp;
793  // calculate the virtual control (reference acceleration) based on a PD controller
794  rate_sp.p = indi_gains.att.p * att_fb.x / indi_gains.rate.p;
795  rate_sp.q = indi_gains.att.q * att_fb.y / indi_gains.rate.q;
796  rate_sp.r = indi_gains.att.r * att_fb.z / indi_gains.rate.r;
797 
798  // Add feed-forward rates to the attitude feedback part
799  struct FloatRates ff_rates = stab_sp_to_rates_f(att_sp);
800  RATES_ADD(rate_sp, ff_rates);
801 
802  // Store for telemetry
803  angular_rate_ref.p = rate_sp.p;
804  angular_rate_ref.q = rate_sp.q;
805  angular_rate_ref.r = rate_sp.r;
806 
807  // Possibly we can use some bounding here
808  /*BoundAbs(rate_sp.r, 5.0);*/
809 
810  /* compute the INDI command */
811  struct StabilizationSetpoint sp = stab_sp_from_rates_f(&rate_sp);
812  stabilization_indi_rate_run(in_flight, &sp, thrust, cmd);
813 }
814 
822 {
823 #if STABILIZATION_INDI_RPM_FEEDBACK
824  float_vect_copy(actuator_state, act_obs, INDI_NUM_ACT);
825 #else
826  //actuator dynamics
827  int8_t i;
828  float UNUSED prev_actuator_state;
829  for (i = 0; i < INDI_NUM_ACT; i++) {
830  prev_actuator_state = actuator_state[i];
831 
833  + act_dyn_discrete[i] * (indi_u[i] - actuator_state[i]);
834 
835 #ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
836  if ((actuator_state[i] - prev_actuator_state) > act_rate_limit[i]) {
837  actuator_state[i] = prev_actuator_state + act_rate_limit[i];
838  } else if ((actuator_state[i] - prev_actuator_state) < -act_rate_limit[i]) {
839  actuator_state[i] = prev_actuator_state - act_rate_limit[i];
840  }
841 #endif
842  }
843 
844 #endif
845 }
846 
857 void calc_g1_element(float ddx_error, int8_t i, int8_t j, float mu)
858 {
859  g1_est[i][j] = g1_est[i][j] - du_estimation[j] * mu * ddx_error;
860 }
861 
871 void calc_g2_element(float ddx_error, int8_t j, float mu)
872 {
873  g2_est[j] = g2_est[j] - ddu_estimation[j] * mu * ddx_error;
874 }
875 
881 void lms_estimation(void)
882 {
883 
884  // Get the acceleration in body axes
885  struct Int32Vect3 *body_accel_i;
886  body_accel_i = stateGetAccelBody_i();
887  ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
888 
889  // Filter the acceleration in z axis
891 
892  // Calculate the derivative of the acceleration via finite difference
893  float indi_accel_d = (acceleration_lowpass_filter.o[0]
894  - acceleration_lowpass_filter.o[1]) * PERIODIC_FREQUENCY;
895 
896  // Use xml setting for adaptive mu for lms
897  // Set default value if not defined
898 #ifndef STABILIZATION_INDI_ADAPTIVE_MU
899  float adaptive_mu_lr = 0.001;
900 #else
901  float adaptive_mu_lr = STABILIZATION_INDI_ADAPTIVE_MU;
902 #endif
903 
904  // scale the inputs to avoid numerical errors
905  float_vect_smul(du_estimation, actuator_state_filt_vectd, adaptive_mu_lr, INDI_NUM_ACT);
906  float_vect_smul(ddu_estimation, actuator_state_filt_vectdd, adaptive_mu_lr / PERIODIC_FREQUENCY, INDI_NUM_ACT);
907 
908  float ddx_estimation[INDI_OUTPUTS] = {estimation_rate_dd[0], estimation_rate_dd[1], estimation_rate_dd[2], indi_accel_d};
909 
910  //Estimation of G
911  // TODO: only estimate when du_norm2 is large enough (enough input)
912  /*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];*/
913  int8_t i;
914  for (i = 0; i < INDI_OUTPUTS; i++) {
915  // Calculate the error between prediction and measurement
916  float ddx_error = - ddx_estimation[i];
917  int8_t j;
918  for (j = 0; j < INDI_NUM_ACT; j++) {
919  ddx_error += g1_est[i][j] * du_estimation[j];
920  if (i == 2) {
921  // Changing the momentum of the rotors gives a counter torque
922  ddx_error += g2_est[j] * ddu_estimation[j];
923  }
924  }
925 
926  // when doing the yaw axis, also use G2
927  if (i == 2) {
928  for (j = 0; j < INDI_NUM_ACT; j++) {
929  calc_g2_element(ddx_error, j, mu2);
930  }
931  } else if (i == 3) {
932  // If the acceleration change is very large (rough landing), don't adapt
933  if (fabs(indi_accel_d) > 60.0) {
934  ddx_error = 0.0;
935  }
936  }
937 
938  // Calculate the row of the G1 matrix corresponding to this axis
939  for (j = 0; j < INDI_NUM_ACT; j++) {
940  calc_g1_element(ddx_error, i, j, mu1[i]);
941  }
942  }
943 
944  bound_g_mat();
945 
946  // Save the calculated matrix to G1 and G2
947  // until thrust is included, first part of the array
948  float_vect_copy(g1[0], g1_est[0], INDI_OUTPUTS * INDI_NUM_ACT);
949  float_vect_copy(g2, g2_est, INDI_NUM_ACT);
950 
951  // Calculate sum of G1 and G2 for Bwls
952  sum_g1_g2();
953 
954 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
955  // Calculate the inverse of (G1+G2)
956  calc_g1g2_pseudo_inv();
957 #endif
958 }
959 
964 void sum_g1_g2(void)
965 {
966  int8_t i;
967  int8_t j;
968  for (i = 0; i < INDI_OUTPUTS; i++) {
969  for (j = 0; j < INDI_NUM_ACT; j++) {
970  if (i != 2) {
971  g1g2[i][j] = g1[i][j] / INDI_G_SCALING;
972  } else {
973  g1g2[i][j] = (g1[i][j] + g2[j]) / INDI_G_SCALING;
974  }
975  }
976  }
977 }
978 
979 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
984 void calc_g1g2_pseudo_inv(void)
985 {
986  //G1G2*transpose(G1G2)
987  //calculate matrix multiplication of its transpose INDI_OUTPUTSxnum_act x num_actxINDI_OUTPUTS
988  float element = 0;
989  int8_t row;
990  int8_t col;
991  int8_t i;
992  for (row = 0; row < INDI_OUTPUTS; row++) {
993  for (col = 0; col < INDI_OUTPUTS; col++) {
994  element = 0;
995  for (i = 0; i < INDI_NUM_ACT; i++) {
996  element = element + g1g2[row][i] * g1g2[col][i];
997  }
998  g1g2_trans_mult[row][col] = element;
999  }
1000  }
1001 
1002  //there are numerical errors if the scaling is not right.
1003  float_vect_scale(g1g2_trans_mult[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
1004 
1005  //inverse of 4x4 matrix
1007 
1008  //scale back
1009  float_vect_scale(g1g2inv[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
1010 
1011  //G1G2'*G1G2inv
1012  //calculate matrix multiplication INDI_NUM_ACTxINDI_OUTPUTS x INDI_OUTPUTSxINDI_OUTPUTS
1013  for (row = 0; row < INDI_NUM_ACT; row++) {
1014  for (col = 0; col < INDI_OUTPUTS; col++) {
1015  element = 0;
1016  for (i = 0; i < INDI_OUTPUTS; i++) {
1017  element = element + g1g2[i][row] * g1g2inv[col][i];
1018  }
1019  g1g2_pseudo_inv[row][col] = element;
1020  }
1021  }
1022 }
1023 #endif
1024 
1025 #if STABILIZATION_INDI_RPM_FEEDBACK
1026 static void act_feedback_cb(uint8_t sender_id UNUSED, struct act_feedback_t *feedback, uint8_t num_act)
1027 {
1028  int8_t i;
1029  for (i = 0; i < num_act; i++) {
1030  // Sanity check that index is valid
1031  if (feedback[i].idx < INDI_NUM_ACT && feedback[i].set.rpm) {
1032  int8_t idx = feedback[i].idx;
1033  act_obs[idx] = (feedback[i].rpm - get_servo_min(idx));
1034  act_obs[idx] *= (MAX_PPRZ / (float)(get_servo_max(idx) - get_servo_min(idx)));
1035  Bound(act_obs[idx], 0, MAX_PPRZ);
1036  }
1037  }
1038 }
1039 #endif
1040 
1041 static void bound_g_mat(void)
1042 {
1043  int8_t i;
1044  int8_t j;
1045  for (j = 0; j < INDI_NUM_ACT; j++) {
1046  float max_limit;
1047  float min_limit;
1048 
1049  // Limit the values of the estimated G1 matrix
1050  for (i = 0; i < INDI_OUTPUTS; i++) {
1051  if (g1_init[i][j] > 0.0) {
1052  max_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1053  min_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1054  } else {
1055  max_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1056  min_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1057  }
1058 
1059  if (g1_est[i][j] > max_limit) {
1060  g1_est[i][j] = max_limit;
1061  }
1062  if (g1_est[i][j] < min_limit) {
1063  g1_est[i][j] = min_limit;
1064  }
1065  }
1066 
1067  // Do the same for the G2 matrix
1068  if (g2_init[j] > 0.0) {
1069  max_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1070  min_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1071  } else {
1072  max_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1073  min_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1074  }
1075 
1076  if (g2_est[j] > max_limit) {
1077  g2_est[j] = max_limit;
1078  }
1079  if (g2_est[j] < min_limit) {
1080  g2_est[j] = min_limit;
1081  }
1082  }
1083 }
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:1276
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1306
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1294
static struct FloatRates * stateGetBodyRates_f(void)
Get vehicle body angular rate (float).
Definition: state.h:1367
static struct Int32Vect3 * stateGetAccelBody_i(void)
Get acceleration in Body coordinates (int).
Definition: state.h:1094
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition: state.h:1590
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
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
#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