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 
37 
39 #include "state.h"
40 #include "generated/airframe.h"
43 #include "modules/core/abi.h"
45 #include "math/wls/wls_alloc.h"
46 #include <stdio.h>
47 
48 // Factor that the estimated G matrix is allowed to deviate from initial one
49 #define INDI_ALLOWED_G_FACTOR 2.0
50 
51 #ifdef STABILIZATION_INDI_FILT_CUTOFF_P
52 #define STABILIZATION_INDI_FILTER_ROLL_RATE TRUE
53 #else
54 #define STABILIZATION_INDI_FILT_CUTOFF_P 20.0
55 #endif
56 
57 #ifdef STABILIZATION_INDI_FILT_CUTOFF_Q
58 #define STABILIZATION_INDI_FILTER_PITCH_RATE TRUE
59 #else
60 #define STABILIZATION_INDI_FILT_CUTOFF_Q 20.0
61 #endif
62 
63 #ifdef STABILIZATION_INDI_FILT_CUTOFF_R
64 #define STABILIZATION_INDI_FILTER_YAW_RATE TRUE
65 #else
66 #define STABILIZATION_INDI_FILT_CUTOFF_R 20.0
67 #endif
68 
69 // Default is WLS
70 #ifndef STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
71 #define STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE FALSE
72 #endif
73 
74 #ifndef STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
75 #define STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER FALSE
76 #endif
77 
78 // Airspeed [m/s] at which the forward flight throttle limit is used instead of
79 // the hover throttle limit.
80 #ifndef STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
81 #define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD 8.0
82 #endif
83 
84 #if INDI_OUTPUTS > 4
85 #ifndef STABILIZATION_INDI_G1_THRUST_X
86 #error "You must define STABILIZATION_INDI_G1_THRUST_X for your number of INDI_OUTPUTS"
87 #endif
88 #endif
89 
90 #ifdef SetCommandsFromRC
91 #warning SetCommandsFromRC not used: STAB_INDI writes actuators directly
92 #endif
93 
94 #ifdef SetAutoCommandsFromRC
95 #warning SetAutoCommandsFromRC not used: STAB_INDI writes actuators directly
96 #endif
97 
98 
99 #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
100 #if INDI_NUM_ACT > WLS_N_U
101 #error Matrix-WLS_N_U too small or not defined: define WLS_N_U >= INDI_NUM_ACT in airframe file
102 #endif
103 #if INDI_OUTPUTS > WLS_N_V
104 #error Matrix-WLS_N_V too small or not defined: define WLS_N_U >= INDI_OUTPUTS in airframe file
105 #endif
106 #endif
107 
108 float u_min_stab_indi[INDI_NUM_ACT];
109 float u_max_stab_indi[INDI_NUM_ACT];
110 float u_pref_stab_indi[INDI_NUM_ACT];
111 float indi_v[INDI_OUTPUTS];
112 float *Bwls[INDI_OUTPUTS];
113 int num_iter = 0;
114 
115 static void lms_estimation(void);
116 static void get_actuator_state(void);
117 static void calc_g1_element(float dx_error, int8_t i, int8_t j, float mu_extra);
118 static void calc_g2_element(float dx_error, int8_t j, float mu_extra);
119 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
120 static void calc_g1g2_pseudo_inv(void);
121 #endif
122 static void bound_g_mat(void);
123 
125 struct Indi_gains indi_gains = {
126  .att = {
127  STABILIZATION_INDI_REF_ERR_P,
128  STABILIZATION_INDI_REF_ERR_Q,
129  STABILIZATION_INDI_REF_ERR_R
130  },
131  .rate = {
132  STABILIZATION_INDI_REF_RATE_P,
133  STABILIZATION_INDI_REF_RATE_Q,
134  STABILIZATION_INDI_REF_RATE_R
135  },
136 };
137 
138 #if STABILIZATION_INDI_USE_ADAPTIVE
139 bool indi_use_adaptive = true;
140 #else
141 bool indi_use_adaptive = false;
142 #endif
143 
144 #ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
145 float act_rate_limit[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_RATE_LIMIT;
146 #endif
147 
148 #ifdef STABILIZATION_INDI_ACT_IS_SERVO
149 bool act_is_servo[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_IS_SERVO;
150 #else
151 bool act_is_servo[INDI_NUM_ACT] = {0};
152 #endif
153 
154 #ifdef STABILIZATION_INDI_ACT_IS_THRUSTER_X
155 bool act_is_thruster_x[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_IS_THRUSTER_X;
156 #else
157 bool act_is_thruster_x[INDI_NUM_ACT] = {0};
158 #endif
159 
160 bool act_is_thruster_z[INDI_NUM_ACT];
161 
162 #ifdef STABILIZATION_INDI_ACT_PREF
163 // Preferred (neutral, least energy) actuator value
164 float act_pref[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_PREF;
165 #else
166 // Assume 0 is neutral
167 float act_pref[INDI_NUM_ACT] = {0.0};
168 #endif
169 
170 #ifdef STABILIZATION_INDI_ACT_DYN
171 #warning STABILIZATION_INDI_ACT_DYN is deprecated, use STABILIZATION_INDI_ACT_FREQ instead.
172 #warning You now have to define the continuous time corner frequency in rad/s of the actuators.
173 #warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old values."
174 float act_dyn_discrete[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_DYN;
175 #else
176 float act_first_order_cutoff[INDI_NUM_ACT] = STABILIZATION_INDI_ACT_FREQ;
177 float act_dyn_discrete[INDI_NUM_ACT]; // will be computed from freq at init
178 #endif
179 
180 #ifdef STABILIZATION_INDI_WLS_PRIORITIES
181 static float Wv[INDI_OUTPUTS] = STABILIZATION_INDI_WLS_PRIORITIES;
182 #else
183 //State prioritization {W Roll, W pitch, W yaw, TOTAL THRUST}
184 #if INDI_OUTPUTS == 5
185 static float Wv[INDI_OUTPUTS] = {1000, 1000, 1, 100, 100};
186 #else
187 static float Wv[INDI_OUTPUTS] = {1000, 1000, 1, 100};
188 #endif
189 #endif
190 
194 #ifdef STABILIZATION_INDI_WLS_WU
195 float indi_Wu[INDI_NUM_ACT] = STABILIZATION_INDI_WLS_WU;
196 #else
197 float indi_Wu[INDI_NUM_ACT] = {[0 ... INDI_NUM_ACT - 1] = 1.0};
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 float rate_vect_prev[3] = {0., 0., 0.};
217 
218 float q_filt = 0.0;
219 float r_filt = 0.0;
220 
221 // variables needed for estimation
222 float g1g2_trans_mult[INDI_OUTPUTS][INDI_OUTPUTS];
223 float g1g2inv[INDI_OUTPUTS][INDI_OUTPUTS];
224 float actuator_state_filt_vectd[INDI_NUM_ACT];
225 float actuator_state_filt_vectdd[INDI_NUM_ACT];
226 float estimation_rate_d[INDI_NUM_ACT];
227 float estimation_rate_dd[INDI_NUM_ACT];
228 float du_estimation[INDI_NUM_ACT];
229 float ddu_estimation[INDI_NUM_ACT];
230 
231 // The learning rate per axis (roll, pitch, yaw, thrust)
232 float mu1[INDI_OUTPUTS] = {0.00001, 0.00001, 0.000003, 0.000002};
233 // The learning rate for the propeller inertia (scaled by 512 wrt mu1)
234 float mu2 = 0.002;
235 
236 // other variables
237 float act_obs[INDI_NUM_ACT];
238 
239 // Number of actuators used to provide thrust
242 
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 
260 static void thrust_cb(uint8_t sender_id, struct FloatVect3 thrust_increment);
263 
264 float g1g2_pseudo_inv[INDI_NUM_ACT][INDI_OUTPUTS];
265 float g2[INDI_NUM_ACT] = STABILIZATION_INDI_G2; //scaled by INDI_G_SCALING
266 #ifdef STABILIZATION_INDI_G1
267 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = STABILIZATION_INDI_G1;
268 #else // old defines TODO remove
269 #if INDI_OUTPUTS == 5
270 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = {STABILIZATION_INDI_G1_ROLL,
271  STABILIZATION_INDI_G1_PITCH, STABILIZATION_INDI_G1_YAW,
272  STABILIZATION_INDI_G1_THRUST, STABILIZATION_INDI_G1_THRUST_X
273  };
274 #else
275 float g1[INDI_OUTPUTS][INDI_NUM_ACT] = {STABILIZATION_INDI_G1_ROLL,
276  STABILIZATION_INDI_G1_PITCH, STABILIZATION_INDI_G1_YAW, STABILIZATION_INDI_G1_THRUST
277  };
278 #endif
279 #endif
280 
281 float g1g2[INDI_OUTPUTS][INDI_NUM_ACT];
282 float g1_est[INDI_OUTPUTS][INDI_NUM_ACT];
283 float g2_est[INDI_NUM_ACT];
284 float g1_init[INDI_OUTPUTS][INDI_NUM_ACT];
285 float g2_init[INDI_NUM_ACT];
286 
292 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
293 Butterworth2LowPass rates_filt_so[3];
294 #else
295 static struct FirstOrderLowPass rates_filt_fo[3];
296 #endif
297 struct FloatVect3 body_accel_f;
298 
299 void init_filters(void);
300 void sum_g1_g2(void);
301 
302 #if PERIODIC_TELEMETRY
304 static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
305 {
306  float zero = 0.0;
307  pprz_msg_send_EFF_MAT_G(trans, dev, AC_ID,
308  1, &zero,
309  1, &zero,
310  1, &zero,
311  INDI_NUM_ACT, g1g2[0],
312  INDI_NUM_ACT, g1g2[1],
313  INDI_NUM_ACT, g1g2[2],
314  INDI_NUM_ACT, g1g2[3],
315  INDI_NUM_ACT, g2_est);
316 }
317 
318 static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
319 {
320  struct Int32Quat *quat = stateGetNedToBodyQuat_i();
321  pprz_msg_send_AHRS_REF_QUAT(trans, dev, AC_ID,
326  &(quat->qi),
327  &(quat->qx),
328  &(quat->qy),
329  &(quat->qz));
330 }
331 
332 static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
333 {
334  float zero = 0.0;
335  struct FloatRates *body_rates = stateGetBodyRates_f();
336  pprz_msg_send_STAB_ATTITUDE(trans, dev, AC_ID,
337  &zero, &zero, &zero, // att
338  &zero, &zero, &zero, // att.ref
339  &body_rates->p, // rate
340  &body_rates->q,
341  &body_rates->r,
342  &angular_rate_ref.p, // rate.ref
345  &angular_acceleration[0], // ang.acc
348  &angular_accel_ref.p, // ang.acc.ref
351  1, &zero, // inputs
352  INDI_NUM_ACT, indi_u); // out
353 }
354 #endif
355 
360 {
361  // Initialize filters
362  init_filters();
363 
364  int8_t i;
365 // If the deprecated STABILIZATION_INDI_ACT_DYN is used, convert it to the new FREQUENCY format
366 #ifdef STABILIZATION_INDI_ACT_FREQ
367  // Initialize the array of pointers to the rows of g1g2
368  for (i = 0; i < INDI_NUM_ACT; i++) {
369  act_dyn_discrete[i] = 1-exp(-act_first_order_cutoff[i]/PERIODIC_FREQUENCY);
370  }
371 #endif
372 
373 #if STABILIZATION_INDI_RPM_FEEDBACK
374  AbiBindMsgACT_FEEDBACK(STABILIZATION_INDI_ACT_FEEDBACK_ID, &act_feedback_ev, act_feedback_cb);
375 #endif
376  AbiBindMsgTHRUST(THRUST_INCREMENT_ID, &thrust_ev, thrust_cb);
377 
380  float_vect_zero(estimation_rate_d, INDI_NUM_ACT);
381  float_vect_zero(estimation_rate_dd, INDI_NUM_ACT);
383 
384  //Calculate G1G2
385  sum_g1_g2();
386 
387  // Do not compute if not needed
388 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
389  //Calculate G1G2_PSEUDO_INVERSE
390  calc_g1g2_pseudo_inv();
391 #endif
392 
393  // Initialize the array of pointers to the rows of g1g2
394  for (i = 0; i < INDI_OUTPUTS; i++) {
395  Bwls[i] = g1g2[i];
396  }
397 
398  // Initialize the estimator matrices
399  float_vect_copy(g1_est[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
400  float_vect_copy(g2_est, g2, INDI_NUM_ACT);
401  // Remember the initial matrices
402  float_vect_copy(g1_init[0], g1[0], INDI_OUTPUTS * INDI_NUM_ACT);
403  float_vect_copy(g2_init, g2, INDI_NUM_ACT);
404 
405  // Assume all non-servos are delivering thrust
406  num_thrusters = INDI_NUM_ACT;
407  num_thrusters_x = 0;
408  for (i = 0; i < INDI_NUM_ACT; i++) {
411 
413 
415  }
416 
417 #if PERIODIC_TELEMETRY
421 #endif
422 }
423 
433 {
434  /* reset psi setpoint to current psi angle */
436 
438 
439  float_vect_zero(du_estimation, INDI_NUM_ACT);
440  float_vect_zero(ddu_estimation, INDI_NUM_ACT);
441 }
442 
446 void init_filters(void)
447 {
448  // tau = 1/(2*pi*Fc)
449  float tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF);
450  float tau_est = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_ESTIMATION_FILT_CUTOFF);
451  float sample_time = 1.0 / PERIODIC_FREQUENCY;
452  // Filtering of the gyroscope
453  int8_t i;
454  for (i = 0; i < 3; i++) {
455  init_butterworth_2_low_pass(&measurement_lowpass_filters[i], tau, sample_time, 0.0);
456  init_butterworth_2_low_pass(&estimation_output_lowpass_filters[i], tau_est, sample_time, 0.0);
457  }
458 
459  // Filtering of the actuators
460  for (i = 0; i < INDI_NUM_ACT; i++) {
461  init_butterworth_2_low_pass(&actuator_lowpass_filters[i], tau, sample_time, 0.0);
462  init_butterworth_2_low_pass(&estimation_input_lowpass_filters[i], tau_est, sample_time, 0.0);
463  }
464 
465  // Filtering of the accel body z
466  init_butterworth_2_low_pass(&acceleration_lowpass_filter, tau_est, sample_time, 0.0);
467 
468 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
469  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P);
470  init_butterworth_2_low_pass(&rates_filt_so[0], tau, sample_time, 0.0);
471  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q);
472  init_butterworth_2_low_pass(&rates_filt_so[1], tau, sample_time, 0.0);
473  tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R);
474  init_butterworth_2_low_pass(&rates_filt_so[2], tau, sample_time, 0.0);
475 #else
476  // Init rate filter for feedback
477  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)};
478 
479  init_first_order_low_pass(&rates_filt_fo[0], time_constants[0], sample_time, stateGetBodyRates_f()->p);
480  init_first_order_low_pass(&rates_filt_fo[1], time_constants[1], sample_time, stateGetBodyRates_f()->q);
481  init_first_order_low_pass(&rates_filt_fo[2], time_constants[2], sample_time, stateGetBodyRates_f()->r);
482 #endif
483 }
484 
489 {
490  /* set failsafe to zero roll/pitch and current heading */
493  stab_att_sp_quat.qx = 0;
494  stab_att_sp_quat.qy = 0;
496 }
497 
504 {
505  // stab_att_sp_euler.psi still used in ref..
506  stab_att_sp_euler = *rpy;
507 
510 }
511 
516 {
517  stab_att_sp_quat = *quat;
520 }
521 
529 {
530  // stab_att_sp_euler.psi still used in ref..
532 
533  // compute sp_euler phi/theta for debugging/telemetry
534  /* Rotate horizontal commands to body frame by psi */
536  int32_t s_psi, c_psi;
537  PPRZ_ITRIG_SIN(s_psi, psi);
538  PPRZ_ITRIG_COS(c_psi, psi);
539  stab_att_sp_euler.phi = (-s_psi * cmd->x + c_psi * cmd->y) >> INT32_TRIG_FRAC;
540  stab_att_sp_euler.theta = -(c_psi * cmd->x + s_psi * cmd->y) >> INT32_TRIG_FRAC;
541 
544 }
545 
552 {
556 }
557 
565 void stabilization_indi_rate_run(struct FloatRates rate_sp, bool in_flight)
566 {
567 
568  // Propagate actuator filters
570  float actuator_state_filt_vect_prev[INDI_NUM_ACT];
571  for (int i = 0; i < INDI_NUM_ACT; i++) {
575  actuator_state_filt_vect_prev[i] = actuator_lowpass_filters[i].o[1];
576 
577  // calculate derivatives for estimation
578  float actuator_state_filt_vectd_prev = actuator_state_filt_vectd[i];
580  PERIODIC_FREQUENCY;
581  actuator_state_filt_vectdd[i] = (actuator_state_filt_vectd[i] - actuator_state_filt_vectd_prev) * PERIODIC_FREQUENCY;
582  }
583 
584  // Use the last actuator state for this computation
585  float g2_times_u_act_filt = float_vect_dot_product(g2, actuator_state_filt_vect_prev, INDI_NUM_ACT)/INDI_G_SCALING;
586 
587  // Predict angular acceleration u*B
588  float angular_acc_prediction_filt[INDI_OUTPUTS];
589  float_mat_vect_mul(angular_acc_prediction_filt, Bwls, actuator_state_filt_vect, INDI_OUTPUTS, INDI_NUM_ACT);
590  angular_acc_prediction_filt[2] -= g2_times_u_act_filt;
591 
592  /* Propagate the filter on the gyroscopes */
593  struct FloatRates *body_rates = stateGetBodyRates_f();
594  float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
595  int8_t i;
596  for (i = 0; i < 3; i++) {
599 
600  //Calculate the angular acceleration via finite difference
602  - measurement_lowpass_filters[i].o[1]) * PERIODIC_FREQUENCY;
603 
604  // Calculate derivatives for estimation
605  float estimation_rate_d_prev = estimation_rate_d[i];
607  PERIODIC_FREQUENCY;
608  estimation_rate_dd[i] = (estimation_rate_d[i] - estimation_rate_d_prev) * PERIODIC_FREQUENCY;
609  }
610 
611  // subtract u*B from angular acceleration
612  float angular_acc_disturbance_estimate[INDI_OUTPUTS];
613  float_vect_diff(angular_acc_disturbance_estimate, angular_acceleration, angular_acc_prediction_filt, 3);
614 
615  //The rates used for feedback are by default the measured rates.
616  //If there is a lot of noise on the gyroscope, it might be good to use the filtered value for feedback.
617  //Note that due to the delay, the PD controller may need relaxed gains.
618  struct FloatRates rates_filt;
619 #if STABILIZATION_INDI_FILTER_ROLL_RATE
620 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
621  rates_filt.p = update_butterworth_2_low_pass(&rates_filt_so[0], body_rates->p);
622 #else
623  rates_filt.p = update_first_order_low_pass(&rates_filt_fo[0], body_rates->p);
624 #endif
625 #else
626  rates_filt.p = body_rates->p;
627 #endif
628 #if STABILIZATION_INDI_FILTER_PITCH_RATE
629 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
630  rates_filt.q = update_butterworth_2_low_pass(&rates_filt_so[1], body_rates->q);
631 #else
632  rates_filt.q = update_first_order_low_pass(&rates_filt_fo[1], body_rates->q);
633 #endif
634 #else
635  rates_filt.q = body_rates->q;
636 #endif
637 #if STABILIZATION_INDI_FILTER_YAW_RATE
638 #if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
639  rates_filt.r = update_butterworth_2_low_pass(&rates_filt_so[2], body_rates->r);
640 #else
641  rates_filt.r = update_first_order_low_pass(&rates_filt_fo[2], body_rates->r);
642 #endif
643 #else
644  rates_filt.r = body_rates->r;
645 #endif
646 
647  //calculate the virtual control (reference acceleration) based on a PD controller
648  angular_accel_ref.p = (rate_sp.p - rates_filt.p) * indi_gains.rate.p;
649  angular_accel_ref.q = (rate_sp.q - rates_filt.q) * indi_gains.rate.q;
650  angular_accel_ref.r = (rate_sp.r - rates_filt.r) * indi_gains.rate.r;
651 
652  struct FloatVect3 v_thrust;
653  v_thrust.x = 0.0;
654  v_thrust.y = 0.0;
655  v_thrust.z = 0.0;
657  //update thrust command such that the current is correctly estimated
658  stabilization_cmd[COMMAND_THRUST] = 0;
659  float current_thrust_filt_z = 0;
660  for (i = 0; i < INDI_NUM_ACT; i++) {
661  stabilization_cmd[COMMAND_THRUST] += actuator_state[i] * (int32_t) act_is_thruster_z[i];
662  current_thrust_filt_z += Bwls[3][i]* actuator_lowpass_filters[i].o[0] * (int32_t) act_is_thruster_z[i];
663  }
664  stabilization_cmd[COMMAND_THRUST] /= num_thrusters;
665 
666  // Add the increment to the current estimated thrust
667  v_thrust.z = current_thrust_filt_z + indi_thrust_increment.z;
668 
669 #if INDI_OUTPUTS == 5
670  stabilization_cmd[COMMAND_THRUST_X] = 0;
671  float current_thrust_filt_x = 0;
672  for (i = 0; i < INDI_NUM_ACT; i++) {
673  stabilization_cmd[COMMAND_THRUST_X] += actuator_state[i] * (int32_t) act_is_thruster_x[i];
674  current_thrust_filt_x += Bwls[4][i]* actuator_lowpass_filters[i].o[0] * (int32_t) act_is_thruster_x[i];
675  }
676  stabilization_cmd[COMMAND_THRUST_X] /= num_thrusters_x;
677 
678  v_thrust.x = current_thrust_filt_x + indi_thrust_increment.x;
679 #endif
680 
681  } else {
682  // incremental thrust
683  for (i = 0; i < INDI_NUM_ACT; i++) {
684  v_thrust.z += stabilization_cmd[COMMAND_THRUST] * Bwls[3][i];
685 #if INDI_OUTPUTS == 5
686  stabilization_cmd[COMMAND_THRUST_X] = radio_control.values[RADIO_CONTROL_THRUST_X];
687  v_thrust.x += stabilization_cmd[COMMAND_THRUST_X] * Bwls[4][i];
688 #endif
689  }
690  }
691 
692  // This term compensates for the spinup torque in the yaw axis
693  float g2_times_u = float_vect_dot_product(g2, indi_u, INDI_NUM_ACT)/INDI_G_SCALING;
694 
695  if (in_flight) {
696  // Limit the estimated disturbance in yaw for drones that are stable in sideslip
697  BoundAbs(angular_acc_disturbance_estimate[2], stablization_indi_yaw_dist_limit);
698  } else {
699  // Not in flight, so don't estimate disturbance
700  float_vect_zero(angular_acc_disturbance_estimate, INDI_OUTPUTS);
701  }
702 
703  // The control objective in array format
704  indi_v[0] = (angular_accel_ref.p - angular_acc_disturbance_estimate[0]);
705  indi_v[1] = (angular_accel_ref.q - angular_acc_disturbance_estimate[1]);
706  indi_v[2] = (angular_accel_ref.r - angular_acc_disturbance_estimate[2]) + g2_times_u;
707  indi_v[3] = v_thrust.z;
708 #if INDI_OUTPUTS == 5
709  indi_v[4] = v_thrust.x;
710 #endif
711 
712 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
713  // Calculate the increment for each actuator
714  for (i = 0; i < INDI_NUM_ACT; i++) {
715  indi_u[i] = (g1g2_pseudo_inv[i][0] * indi_v[0])
716  + (g1g2_pseudo_inv[i][1] * indi_v[1])
717  + (g1g2_pseudo_inv[i][2] * indi_v[2])
718  + (g1g2_pseudo_inv[i][3] * indi_v[3]);
719  }
720 #else
722 
723  // WLS Control Allocator
724  num_iter =
726  INDI_NUM_ACT, INDI_OUTPUTS);
727 #endif
728 
729  // Bound the inputs to the actuators
730  for (i = 0; i < INDI_NUM_ACT; i++) {
731  if (act_is_servo[i]) {
732  BoundAbs(indi_u[i], MAX_PPRZ);
733  } else {
734  if (autopilot_get_motors_on()) {
735  Bound(indi_u[i], 0, MAX_PPRZ);
736  } else {
737  indi_u[i] = -MAX_PPRZ;
738  }
739  }
740  }
741 
742  // Use online effectiveness estimation only when flying
743  if (in_flight && indi_use_adaptive) {
744  lms_estimation();
745  }
746 
747  /*Commit the actuator command*/
748  for (i = 0; i < INDI_NUM_ACT; i++) {
749  actuators_pprz[i] = (int16_t) indi_u[i];
750  }
751 }
752 
757 {
758  // Calculate the min and max increments
759  for (uint8_t i = 0; i < INDI_NUM_ACT; i++) {
762  u_pref_stab_indi[i] = act_pref[i];
763 
764 #ifdef GUIDANCE_INDI_MIN_THROTTLE
765  float airspeed = stateGetAirspeed_f();
766  //limit minimum thrust ap can give
767  if (!act_is_servo[i]) {
770  u_min_stab_indi[i] = GUIDANCE_INDI_MIN_THROTTLE;
771  } else {
772  u_min_stab_indi[i] = GUIDANCE_INDI_MIN_THROTTLE_FWD;
773  }
774  }
775  }
776 #endif
777  }
778 }
779 
786 void stabilization_indi_attitude_run(struct Int32Quat quat_sp, bool in_flight)
787 {
788  /* attitude error */
789  struct FloatQuat att_err;
790  struct FloatQuat *att_quat = stateGetNedToBodyQuat_f();
791  struct FloatQuat quat_sp_f;
792 
793  QUAT_FLOAT_OF_BFP(quat_sp_f, quat_sp);
794  float_quat_inv_comp_norm_shortest(&att_err, att_quat, &quat_sp_f);
795 
796  struct FloatVect3 att_fb;
797 
798 #if TILT_TWIST_CTRL
799  struct FloatQuat tilt;
800  struct FloatQuat twist;
801  float_quat_tilt_twist(&tilt, &twist, &att_err);
802  att_fb.x = tilt.qx;
803  att_fb.y = tilt.qy;
804  att_fb.z = twist.qz;
805 #else
806  att_fb.x = att_err.qx;
807  att_fb.y = att_err.qy;
808  att_fb.z = att_err.qz;
809 #endif
810 
811  // local variable to compute rate setpoints based on attitude error
812  struct FloatRates rate_sp;
813 
814  // calculate the virtual control (reference acceleration) based on a PD controller
815  rate_sp.p = indi_gains.att.p * att_fb.x / indi_gains.rate.p;
816  rate_sp.q = indi_gains.att.q * att_fb.y / indi_gains.rate.q;
817  rate_sp.r = indi_gains.att.r * att_fb.z / indi_gains.rate.r;
818 
819  // Add feed-forward rates to the attitude feedback part
820  RATES_ADD(rate_sp, stab_att_ff_rates);
821 
822  // Store for telemetry
823  angular_rate_ref.p = rate_sp.p;
824  angular_rate_ref.q = rate_sp.q;
825  angular_rate_ref.r = rate_sp.r;
826 
827  // Possibly we can use some bounding here
828  /*BoundAbs(rate_sp.r, 5.0);*/
829 
830  /* compute the INDI command */
831  stabilization_indi_rate_run(rate_sp, in_flight);
832 
833  // Reset thrust increment boolean
835 }
836 
837 // This function reads rc commands
838 void stabilization_indi_read_rc(bool in_flight, bool in_carefree, bool coordinated_turn)
839 {
840  struct FloatQuat q_sp;
841 #if USE_EARTH_BOUND_RC_SETPOINT
842  stabilization_attitude_read_rc_setpoint_quat_earth_bound_f(&q_sp, in_flight, in_carefree, coordinated_turn);
843 #else
844  stabilization_attitude_read_rc_setpoint_quat_f(&q_sp, in_flight, in_carefree, coordinated_turn);
845 #endif
846 
848 }
849 
857 {
858 #if STABILIZATION_INDI_RPM_FEEDBACK
859  float_vect_copy(actuator_state, act_obs, INDI_NUM_ACT);
860 #else
861  //actuator dynamics
862  int8_t i;
863  float UNUSED prev_actuator_state;
864  for (i = 0; i < INDI_NUM_ACT; i++) {
865  prev_actuator_state = actuator_state[i];
866 
868  + act_dyn_discrete[i] * (indi_u[i] - actuator_state[i]);
869 
870 #ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
871  if ((actuator_state[i] - prev_actuator_state) > act_rate_limit[i]) {
872  actuator_state[i] = prev_actuator_state + act_rate_limit[i];
873  } else if ((actuator_state[i] - prev_actuator_state) < -act_rate_limit[i]) {
874  actuator_state[i] = prev_actuator_state - act_rate_limit[i];
875  }
876 #endif
877  }
878 
879 #endif
880 }
881 
892 void calc_g1_element(float ddx_error, int8_t i, int8_t j, float mu)
893 {
894  g1_est[i][j] = g1_est[i][j] - du_estimation[j] * mu * ddx_error;
895 }
896 
906 void calc_g2_element(float ddx_error, int8_t j, float mu)
907 {
908  g2_est[j] = g2_est[j] - ddu_estimation[j] * mu * ddx_error;
909 }
910 
916 void lms_estimation(void)
917 {
918 
919  // Get the acceleration in body axes
920  struct Int32Vect3 *body_accel_i;
921  body_accel_i = stateGetAccelBody_i();
922  ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
923 
924  // Filter the acceleration in z axis
926 
927  // Calculate the derivative of the acceleration via finite difference
928  float indi_accel_d = (acceleration_lowpass_filter.o[0]
929  - acceleration_lowpass_filter.o[1]) * PERIODIC_FREQUENCY;
930 
931  // Use xml setting for adaptive mu for lms
932  // Set default value if not defined
933 #ifndef STABILIZATION_INDI_ADAPTIVE_MU
934  float adaptive_mu_lr = 0.001;
935 #else
936  float adaptive_mu_lr = STABILIZATION_INDI_ADAPTIVE_MU;
937 #endif
938 
939  // scale the inputs to avoid numerical errors
940  float_vect_smul(du_estimation, actuator_state_filt_vectd, adaptive_mu_lr, INDI_NUM_ACT);
941  float_vect_smul(ddu_estimation, actuator_state_filt_vectdd, adaptive_mu_lr / PERIODIC_FREQUENCY, INDI_NUM_ACT);
942 
943  float ddx_estimation[INDI_OUTPUTS] = {estimation_rate_dd[0], estimation_rate_dd[1], estimation_rate_dd[2], indi_accel_d};
944 
945  //Estimation of G
946  // TODO: only estimate when du_norm2 is large enough (enough input)
947  /*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];*/
948  int8_t i;
949  for (i = 0; i < INDI_OUTPUTS; i++) {
950  // Calculate the error between prediction and measurement
951  float ddx_error = - ddx_estimation[i];
952  int8_t j;
953  for (j = 0; j < INDI_NUM_ACT; j++) {
954  ddx_error += g1_est[i][j] * du_estimation[j];
955  if (i == 2) {
956  // Changing the momentum of the rotors gives a counter torque
957  ddx_error += g2_est[j] * ddu_estimation[j];
958  }
959  }
960 
961  // when doing the yaw axis, also use G2
962  if (i == 2) {
963  for (j = 0; j < INDI_NUM_ACT; j++) {
964  calc_g2_element(ddx_error, j, mu2);
965  }
966  } else if (i == 3) {
967  // If the acceleration change is very large (rough landing), don't adapt
968  if (fabs(indi_accel_d) > 60.0) {
969  ddx_error = 0.0;
970  }
971  }
972 
973  // Calculate the row of the G1 matrix corresponding to this axis
974  for (j = 0; j < INDI_NUM_ACT; j++) {
975  calc_g1_element(ddx_error, i, j, mu1[i]);
976  }
977  }
978 
979  bound_g_mat();
980 
981  // Save the calculated matrix to G1 and G2
982  // until thrust is included, first part of the array
983  float_vect_copy(g1[0], g1_est[0], INDI_OUTPUTS * INDI_NUM_ACT);
984  float_vect_copy(g2, g2_est, INDI_NUM_ACT);
985 
986  // Calculate sum of G1 and G2 for Bwls
987  sum_g1_g2();
988 
989 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
990  // Calculate the inverse of (G1+G2)
991  calc_g1g2_pseudo_inv();
992 #endif
993 }
994 
999 void sum_g1_g2(void)
1000 {
1001  int8_t i;
1002  int8_t j;
1003  for (i = 0; i < INDI_OUTPUTS; i++) {
1004  for (j = 0; j < INDI_NUM_ACT; j++) {
1005  if (i != 2) {
1006  g1g2[i][j] = g1[i][j] / INDI_G_SCALING;
1007  } else {
1008  g1g2[i][j] = (g1[i][j] + g2[j]) / INDI_G_SCALING;
1009  }
1010  }
1011  }
1012 }
1013 
1014 #if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
1019 void calc_g1g2_pseudo_inv(void)
1020 {
1021  //G1G2*transpose(G1G2)
1022  //calculate matrix multiplication of its transpose INDI_OUTPUTSxnum_act x num_actxINDI_OUTPUTS
1023  float element = 0;
1024  int8_t row;
1025  int8_t col;
1026  int8_t i;
1027  for (row = 0; row < INDI_OUTPUTS; row++) {
1028  for (col = 0; col < INDI_OUTPUTS; col++) {
1029  element = 0;
1030  for (i = 0; i < INDI_NUM_ACT; i++) {
1031  element = element + g1g2[row][i] * g1g2[col][i];
1032  }
1033  g1g2_trans_mult[row][col] = element;
1034  }
1035  }
1036 
1037  //there are numerical errors if the scaling is not right.
1038  float_vect_scale(g1g2_trans_mult[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
1039 
1040  //inverse of 4x4 matrix
1042 
1043  //scale back
1044  float_vect_scale(g1g2inv[0], 1000.0, INDI_OUTPUTS * INDI_OUTPUTS);
1045 
1046  //G1G2'*G1G2inv
1047  //calculate matrix multiplication INDI_NUM_ACTxINDI_OUTPUTS x INDI_OUTPUTSxINDI_OUTPUTS
1048  for (row = 0; row < INDI_NUM_ACT; row++) {
1049  for (col = 0; col < INDI_OUTPUTS; col++) {
1050  element = 0;
1051  for (i = 0; i < INDI_OUTPUTS; i++) {
1052  element = element + g1g2[i][row] * g1g2inv[col][i];
1053  }
1054  g1g2_pseudo_inv[row][col] = element;
1055  }
1056  }
1057 }
1058 #endif
1059 
1060 #if STABILIZATION_INDI_RPM_FEEDBACK
1061 static void act_feedback_cb(uint8_t sender_id UNUSED, struct act_feedback_t *feedback, uint8_t num_act)
1062 {
1063  int8_t i;
1064  for (i = 0; i < num_act; i++) {
1065  // Sanity check that index is valid
1066  if (feedback[i].idx < INDI_NUM_ACT && feedback[i].set.rpm) {
1067  int8_t idx = feedback[i].idx;
1068  act_obs[idx] = (feedback[i].rpm - get_servo_min(idx));
1069  act_obs[idx] *= (MAX_PPRZ / (float)(get_servo_max(idx) - get_servo_min(idx)));
1070  Bound(act_obs[idx], 0, MAX_PPRZ);
1071  }
1072  }
1073 }
1074 #endif
1075 
1079 static void thrust_cb(uint8_t UNUSED sender_id, struct FloatVect3 thrust_increment)
1080 {
1081  indi_thrust_increment = thrust_increment;
1083 }
1084 
1085 static void bound_g_mat(void)
1086 {
1087  int8_t i;
1088  int8_t j;
1089  for (j = 0; j < INDI_NUM_ACT; j++) {
1090  float max_limit;
1091  float min_limit;
1092 
1093  // Limit the values of the estimated G1 matrix
1094  for (i = 0; i < INDI_OUTPUTS; i++) {
1095  if (g1_init[i][j] > 0.0) {
1096  max_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1097  min_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1098  } else {
1099  max_limit = g1_init[i][j] / INDI_ALLOWED_G_FACTOR;
1100  min_limit = g1_init[i][j] * INDI_ALLOWED_G_FACTOR;
1101  }
1102 
1103  if (g1_est[i][j] > max_limit) {
1104  g1_est[i][j] = max_limit;
1105  }
1106  if (g1_est[i][j] < min_limit) {
1107  g1_est[i][j] = min_limit;
1108  }
1109  }
1110 
1111  // Do the same for the G2 matrix
1112  if (g2_init[j] > 0.0) {
1113  max_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1114  min_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1115  } else {
1116  max_limit = g2_init[j] / INDI_ALLOWED_G_FACTOR;
1117  min_limit = g2_init[j] * INDI_ALLOWED_G_FACTOR;
1118  }
1119 
1120  if (g2_est[j] > max_limit) {
1121  g2_est[j] = max_limit;
1122  }
1123  if (g2_est[j] < min_limit) {
1124  g2_est[j] = min_limit;
1125  }
1126  }
1127 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
#define THRUST_INCREMENT_ID
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:290
uint8_t last_wp UNUSED
if(GpsFixValid() &&e_identification_started)
float q
in rad/s
float p
in rad/s
float r
in rad/s
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
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
#define FLOAT_RATES_ZERO(_r)
Roation quaternion.
angular rates
#define QUAT_BFP_OF_REAL(_qi, _qf)
Definition: pprz_algebra.h:752
#define RATES_ADD(_a, _b)
Definition: pprz_algebra.h:344
#define QUAT_FLOAT_OF_BFP(_qf, _qi)
Definition: pprz_algebra.h:745
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
Definition: pprz_algebra.h:795
int32_t phi
in rad with INT32_ANGLE_FRAC
int32_t psi
in rad with INT32_ANGLE_FRAC
int32_t theta
in rad with INT32_ANGLE_FRAC
void int32_eulers_of_quat(struct Int32Eulers *e, struct Int32Quat *q)
#define INT32_TRIG_FRAC
void int32_quat_of_eulers(struct Int32Quat *q, struct Int32Eulers *e)
Quaternion from Euler angles.
euler angles
Rotation quaternion.
static struct Int32Quat * stateGetNedToBodyQuat_i(void)
Get vehicle body attitude quaternion (int).
Definition: state.h:1113
static struct Int32Eulers * stateGetNedToBodyEulers_i(void)
Get vehicle body attitude euler angles (int).
Definition: state.h:1125
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
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.
#define PPRZ_ITRIG_SIN(_s, _a)
#define PPRZ_ITRIG_COS(_c, _a)
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:50
#define GUIDANCE_H_MODE_NAV
Definition: guidance_h.h:60
#define GUIDANCE_H_MODE_HOVER
Definition: guidance_h.h:59
General attitude stabilization interface for rotorcrafts.
int32_t stabilization_cmd[COMMANDS_NB]
Stabilization commands.
Definition: stabilization.c:34
struct FloatRates stab_sp_to_rates_f(struct StabilizationSetpoint *sp)
struct Int32Quat stab_sp_to_quat_i(struct StabilizationSetpoint *sp)
struct Int32Eulers stab_sp_to_eulers_i(struct StabilizationSetpoint *sp)
void quat_from_earth_cmd_i(struct Int32Quat *quat, struct Int32Vect2 *cmd, int32_t heading)
Quaternion transformation functions.
int32_t stabilization_attitude_get_heading_i(void)
void stabilization_attitude_read_rc_setpoint_quat_earth_bound_f(struct FloatQuat *q_sp, bool in_flight, bool in_carefree, bool coordinated_turn)
void stabilization_attitude_read_rc_setpoint_quat_f(struct FloatQuat *q_sp, bool in_flight, bool in_carefree, bool coordinated_turn)
Read attitude setpoint from RC as quaternion Interprets the stick positions as axes.
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_read_rc(bool in_flight, bool in_carefree, bool coordinated_turn)
void stabilization_indi_enter(void)
Function that resets important values upon engaging INDI.
static float Wv[INDI_OUTPUTS]
float act_pref[INDI_NUM_ACT]
float * Bwls[INDI_OUTPUTS]
int32_t stabilization_att_indi_cmd[COMMANDS_NB]
float u_min_stab_indi[INDI_NUM_ACT]
struct Indi_gains indi_gains
void WEAK stabilization_indi_set_wls_settings(void)
Function that sets the du_min, du_max and du_pref if function not elsewhere defined.
#define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
void stabilization_indi_set_failsafe_setpoint(void)
Function that calculates the failsafe setpoint.
bool act_is_thruster_x[INDI_NUM_ACT]
bool act_is_servo[INDI_NUM_ACT]
void stabilization_indi_attitude_run(struct Int32Quat quat_sp, bool in_flight)
static struct FirstOrderLowPass rates_filt_fo[3]
float angular_acceleration[3]
int32_t num_thrusters
void stabilization_indi_set_earth_cmd_i(struct Int32Vect2 *cmd, int32_t heading)
float actuator_state_filt_vectd[INDI_NUM_ACT]
float indi_Wu[INDI_NUM_ACT]
Weighting of different actuators in the cost function.
float r_filt
#define STABILIZATION_INDI_FILT_CUTOFF_P
static void bound_g_mat(void)
float u_max_stab_indi[INDI_NUM_ACT]
float mu1[INDI_OUTPUTS]
#define STABILIZATION_INDI_FILT_CUTOFF_Q
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
static void calc_g2_element(float dx_error, int8_t j, float mu_extra)
float q_filt
struct Int32Eulers stab_att_sp_euler
with INT32_ANGLE_FRAC
float estimation_rate_d[INDI_NUM_ACT]
float du_estimation[INDI_NUM_ACT]
float actuator_state_filt_vectdd[INDI_NUM_ACT]
static void thrust_cb(uint8_t sender_id, struct FloatVect3 thrust_increment)
abi_event thrust_ev
Butterworth2LowPass measurement_lowpass_filters[3]
bool act_is_thruster_z[INDI_NUM_ACT]
bool indi_thrust_increment_set
void stabilization_indi_rate_run(struct FloatRates rate_sp, bool in_flight)
float g2[INDI_NUM_ACT]
struct FloatVect3 body_accel_f
float u_pref_stab_indi[INDI_NUM_ACT]
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
void stabilization_indi_set_stab_sp(struct StabilizationSetpoint *sp)
Set attitude setpoint from stabilization setpoint struct.
float rate_vect_prev[3]
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_set_rpy_setpoint_i(struct Int32Eulers *rpy)
float actuator_state_filt_vect[INDI_NUM_ACT]
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]
struct FloatVect3 indi_thrust_increment
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]
struct Int32Quat stab_att_sp_quat
with INT32_QUAT_FRAC
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]
void stabilization_indi_set_quat_setpoint_i(struct Int32Quat *quat)
int num_iter
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]
struct FloatRates stab_att_ff_rates
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:42
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
float heading
Definition: wedgebug.c:258
int wls_alloc(float *u, float *v, float *umin, float *umax, float **B, float *u_guess, float *W_init, float *Wv, float *Wu, float *up, float gamma_sq, int imax, int n_u, int n_v)
active set algorithm for control allocation
Definition: wls_alloc.c:108