Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
oneloop_andi.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Tomaso De Ponti <tmldeponti@tudelft.nl>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
26 
32 
45 
78 /* Include necessary header files */
81 #include "state.h"
82 #include "generated/airframe.h"
85 #include "modules/core/abi.h"
87 #include "math/wls/wls_alloc.h"
91 #include "modules/core/commands.h"
93 #include <stdio.h>
94 #if INS_EXT_POSE
96 #endif
97 
98 #include "modules/gps/gps.h" // DELETE FIX
99 //#include "nps/nps_fdm.h"
100 
101 // Number of real actuators (e.g. motors, servos)
102 #ifndef ONELOOP_ANDI_NUM_THRUSTERS
103 float num_thrusters_oneloop = 4.0; // Number of motors used for thrust
104 #else
105 float num_thrusters_oneloop = ONELOOP_ANDI_NUM_THRUSTERS;
106 #endif
107 
108 #ifndef ONELOOP_ANDI_SCHEDULING
109 #define ONELOOP_ANDI_SCHEDULING FALSE
110 #endif
111 
112 #ifdef ONELOOP_ANDI_FILT_CUTOFF
113 float oneloop_andi_filt_cutoff = ONELOOP_ANDI_FILT_CUTOFF;
114 #else
116 #endif
117 
118 #ifdef ONELOOP_ANDI_FILT_CUTOFF_ACC
119 float oneloop_andi_filt_cutoff_a = ONELOOP_ANDI_FILT_CUTOFF_ACC;
120 #else
122 #endif
123 
124 #ifdef ONELOOP_ANDI_FILT_CUTOFF_VEL
125 float oneloop_andi_filt_cutoff_v = ONELOOP_ANDI_FILT_CUTOFF_VEL;
126 #else
128 #endif
129 
130 #ifdef ONELOOP_ANDI_FILT_CUTOFF_POS
131 float oneloop_andi_filt_cutoff_pos = ONELOOP_ANDI_FILT_CUTOFF_POS;
132 #else
134 #endif
135 
136 #ifdef ONELOOP_ANDI_FILT_CUTOFF_P
137 #define ONELOOP_ANDI_FILTER_ROLL_RATE TRUE
138 float oneloop_andi_filt_cutoff_p = ONELOOP_ANDI_FILT_CUTOFF_P;
139 #else
141 #endif
142 
143 #ifdef ONELOOP_ANDI_FILT_CUTOFF_Q
144 #define ONELOOP_ANDI_FILTER_PITCH_RATE TRUE
145 float oneloop_andi_filt_cutoff_q = ONELOOP_ANDI_FILT_CUTOFF_Q;
146 #else
148 #endif
149 
150 #ifdef ONELOOP_ANDI_FILT_CUTOFF_R
151 #define ONELOOP_ANDI_FILTER_YAW_RATE TRUE
152 float oneloop_andi_filt_cutoff_r = ONELOOP_ANDI_FILT_CUTOFF_R;
153 #else
155 #endif
156 
157 #ifndef MAX_R
158 float max_r = RadOfDeg(120.0);
159 #else
160 float max_r = RadOfDeg(MAX_R);
161 #endif
162 
163 #ifdef ONELOOP_ANDI_ACT_IS_SERVO
164 bool actuator_is_servo[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_IS_SERVO;
165 #else
167 #endif
168 
169 #ifdef ONELOOP_ANDI_ACT_DYN
170 float act_dynamics[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_DYN;
171 #else
172 #error "You must specify the actuator dynamics"
174 #endif
175 
176 #ifdef ONELOOP_ANDI_ACT_MAX
177 float act_max[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_MAX;
178 #else
180 #endif
181 
182 #ifdef ONELOOP_ANDI_ACT_MIN
183 float act_min[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_MIN;
184 #else
185 float act_min[ANDI_NUM_ACT_TOT] = = {0.0};
186 #endif
187 
188 #ifdef ONELOOP_ANDI_ACT_MAX_NORM
189 float act_max_norm[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_MAX_NORM;
190 #else
192 #endif
193 
194 #ifdef ONELOOP_ANDI_ACT_MIN_NORM
195 float act_min_norm[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_ACT_MIN_NORM;
196 #else
198 #endif
199 
200 #ifdef ONELOOP_ANDI_NU_NORM_MAX
201 float nu_norm_max = ONELOOP_ANDI_NU_NORM_MAX;
202 #else
203 float nu_norm_max = 1.0;
204 #endif
205 
206 #ifdef ONELOOP_ANDI_WV // {ax_dot,ay_dot,az_dot,p_ddot,q_ddot,r_ddot}
207 static float Wv[ANDI_OUTPUTS] = ONELOOP_ANDI_WV;
208 static float Wv_wls[ANDI_OUTPUTS] = ONELOOP_ANDI_WV;
209 #else
210 static float Wv[ANDI_OUTPUTS] = {1.0};
211 static float Wv_wls[ANDI_OUTPUTS] = {1.0};
212 #endif
213 
214 #ifdef ONELOOP_ANDI_WU // {de,dr,daL,daR,mF,mB,mL,mR,mP,phi,theta}
215 static float Wu[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_WU;
216 #else
217 static float Wu[ANDI_NUM_ACT_TOT] = {1.0};
218 #endif
219 
220 #ifdef ONELOOP_ANDI_U_PREF
221 static float u_pref[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_U_PREF;
222 #else
223 static float u_pref[ANDI_NUM_ACT_TOT] = {0.0};
224 #endif
225 
226 #ifndef ONELOOP_ANDI_DEBUG_MODE
227 #define ONELOOP_ANDI_DEBUG_MODE FALSE
228 #endif
229 
230 // Assume phi and theta are the first actuators after the real ones unless otherwise specified
231 #define ONELOOP_ANDI_MAX_BANK act_max[COMMAND_ROLL] // assuming abs of max and min is the same
232 #define ONELOOP_ANDI_MAX_PHI act_max[COMMAND_ROLL] // assuming abs of max and min is the same
233 
234 #define ONELOOP_ANDI_MAX_THETA act_max[COMMAND_PITCH] // assuming abs of max and min is the same
235 
236 #ifndef ONELOOP_THETA_PREF_MAX
237 float theta_pref_max = RadOfDeg(20.0);
238 #else
239 float theta_pref_max = RadOfDeg(ONELOOP_THETA_PREF_MAX);
240 #endif
241 
242 #if ANDI_NUM_ACT_TOT != WLS_N_U
243 #error Matrix-WLS_N_U is not equal to the number of actuators: define WLS_N_U == ANDI_NUM_ACT_TOT in airframe file
244 #define WLS_N_U == ANDI_NUM_ACT_TOT
245 #endif
246 #if ANDI_OUTPUTS != WLS_N_V
247 #error Matrix-WLS_N_V is not equal to the number of controlled axis: define WLS_N_V == ANDI_OUTPUTS in airframe file
248 #define WLS_N_V == ANDI_OUTPUTS
249 #endif
250 
251 #ifndef ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD
252 #define ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD 10.0
253 #endif
254 
255 /* Declaration of Navigation Variables*/
256 #ifdef NAV_HYBRID_MAX_DECELERATION
258 #else
259 float max_a_nav = 4.0; // (35[N]/6.5[Kg]) = 5.38[m/s2] [0.8 SF]
260 #endif
261 
262 #ifdef ONELOOP_MAX_JERK
263 float max_j_nav = ONELOOP_MAX_JERK;
264 #else
265 float max_j_nav = 500.0; // Pusher Test shows erros above 2[Hz] ramp commands [0.6 SF]
266 #endif
267 
268 #ifdef ONELOOP_MAX_ANGULAR_JERK
269 float max_j_ang = ONELOOP_MAX_ANGULAR_JERK;
270 #else
271 float max_j_ang = 1000.0;
272 #endif
273 
274 #ifdef NAV_HYBRID_MAX_AIRSPEED
275 float max_v_nav = NAV_HYBRID_MAX_AIRSPEED; // Consider implications of difference Ground speed and airspeed
276 #else
277 float max_v_nav = 5.0;
278 #endif
279 float max_as = 19.0f;
280 
281 #ifdef NAV_HYBRID_MAX_SPEED_V
282 float max_v_nav_v = NAV_HYBRID_MAX_SPEED_V;
283 #else
284 float max_v_nav_v = 1.5;
285 #endif
286 #ifndef FWD_SIDESLIP_GAIN
287 float fwd_sideslip_gain = 0.2;
288 #else
289 float fwd_sideslip_gain = FWD_SIDESLIP_GAIN;
290 #endif
291 
292 /* Define Section of the functions used in this module*/
293 void init_poles(void);
294 void calc_normalization(void);
295 void normalize_nu(void);
296 void G1G2_oneloop(int ctrl_type);
297 void get_act_state_oneloop(void);
299 void init_filter(void);
300 void init_controller(void);
301 void float_rates_of_euler_dot_vec(float r[3], float e[3], float edot[3]);
302 void float_euler_dot_of_rates_vec(float r[3], float e[3], float edot[3]);
303 void err_nd(float err[], float a[], float b[], float k[], int n);
304 void err_sum_nd(float err[], float a[], float b[], float k[], float c[], int n);
305 void integrate_nd(float dt, float a[], float a_dot[], int n);
306 void vect_bound_nd(float vect[], float bound, int n);
307 void acc_body_bound(struct FloatVect2* vect, float bound);
308 float bound_v_from_a(float e_x[], float v_bound, float a_bound, int n);
309 void rm_2nd(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float x_des, float k1_rm, float k2_rm);
310 void rm_3rd(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float* x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm);
311 void rm_3rd_head(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float* x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm);
312 void rm_3rd_attitude(float dt, float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x_des[3], bool ow_psi, float psi_overwrite[4], float k1_rm[3], float k2_rm[3], float k3_rm[3], float max_ang_jerk);
313 void rm_3rd_pos(float dt, float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_des[], float k1_rm[], float k2_rm[], float k3_rm[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n);
314 void rm_2nd_pos(float dt, float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_d_des[], float k2_rm[], float k3_rm[], float x_2d_bound, float x_3d_bound, int n);
315 void rm_1st_pos(float dt, float x_2d_ref[], float x_3d_ref[], float x_2d_des[], float k3_rm[], float x_3d_bound, int n);
316 void ec_3rd_att(float y_4d[3], float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x[3], float x_d[3], float x_2d[3], float k1_e[3], float k2_e[3], float k3_e[3], float max_ang_jerk);
317 void ec_3rd_pos(float y_4d[], float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x[], float x_d[], float x_2d[], float k1_e[], float k2_e[], float k3_e[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n);
318 void calc_model(void);
319 float oneloop_andi_sideslip(void);
320 void reshape_wind(void);
321 void chirp_pos(float time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]);
322 void chirp_call(bool* chirp_on, bool* chirp_first_call, float* t_0_chirp, float* time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]);
323 
324 /*Define general struct of the Oneloop ANDI controller*/
326 
327 /* Oneloop Misc variables*/
328 static float use_increment = 0.0;
329 static float nav_target[3]; // Can be a position, speed or acceleration depending on the guidance H mode
330 static float nav_target_new[3];
331 static float dt_1l = 1./PERIODIC_FREQUENCY;
332 static float g = 9.81; // [m/s^2] Gravitational Acceleration
333 float k_as = 2.0;
335 
336 /* Oneloop Control Variables*/
344 static float a_thrust = 0.0;
345 static float g2_ff= 0.0;
346 
347 /*Attitude related variables*/
348 struct Int32Eulers stab_att_sp_euler_1l;// here for now to correct warning, can be better eploited in the future
349 struct Int32Quat stab_att_sp_quat_1l; // here for now to correct warning, can be better eploited in the future
351 struct FloatEulers eulers_zxy;
352 //static float psi_des_rad = 0.0;
353 float psi_des_rad = 0.0;
354 float psi_des_deg = 0.0;
355 static float psi_vec[4] = {0.0, 0.0, 0.0, 0.0};
356 bool heading_manual = false;
357 bool yaw_stick_in_auto = false;
358 bool ctrl_off = false;
359 /*WLS Settings*/
360 static float gamma_wls = 100; //30; //This is actually sqrt(gamma) in the WLS algorithm
364 static float pitch_pref = 0;
365 static int number_iter = 0;
366 
367 /*Complementary Filter Variables*/
368 static float model_pred[ANDI_OUTPUTS];
369 static float model_pred_ar[3];
370 static float ang_acc[3];
371 static float ang_rate[3];
372 static float lin_acc[3];
373 
374 /*Chirp test Variables*/
375 bool chirp_on = false;
376 bool chirp_first_call = true;
377 float time_elapsed_chirp = 0.0;
378 float t_0_chirp = 0.0;
379 float f0_chirp = 0.8 / (2.0 * M_PI);
380 float f1_chirp = 0.8 / (2.0 * M_PI);
381 float t_chirp = 45.0;
382 float A_chirp = 1.0;
384 float p_ref_0[3] = {0.0, 0.0, 0.0};
385 
386 /*Declaration of Reference Model and Error Controller Gains*/
387 struct PolePlacement p_att_e;
388 struct PolePlacement p_att_rm;
389 /*Position Loop*/
390 struct PolePlacement p_pos_e;
391 struct PolePlacement p_pos_rm;
392 /*Altitude Loop*/
393 struct PolePlacement p_alt_e;
394 struct PolePlacement p_alt_rm;
395 /*Heading Loop*/
396 struct PolePlacement p_head_e;
397 struct PolePlacement p_head_rm;
398 /*Gains of EC and RM ANDI*/
399 struct Gains3rdOrder k_att_e;
400 struct Gains3rdOrder k_att_rm;
401 struct Gains3rdOrder k_pos_e;
402 struct Gains3rdOrder k_pos_rm;
403 /*Gains of EC and RM INDI*/
406 
407 /* Effectiveness Matrix definition */
412 
413 /*Filters Initialization*/
414 static Butterworth2LowPass filt_accel_ned[3]; // Low pass filter for acceleration NED (1) - oneloop_andi_filt_cutoff_a (tau_a)
415 static Butterworth2LowPass filt_veloc_ned[3]; // Low pass filter for velocity NED - oneloop_andi_filt_cutoff_a (tau_a)
416 static Butterworth2LowPass rates_filt_bt[3]; // Low pass filter for angular rates - ONELOOP_ANDI_FILT_CUTOFF_P/Q/R
417 static Butterworth2LowPass model_pred_la_filt[3]; // Low pass filter for model prediction linear acceleration (1) - oneloop_andi_filt_cutoff_a (tau_a)
418 static Butterworth2LowPass ang_rate_lowpass_filters[3]; // Low pass filter for attitude derivative measurements - oneloop_andi_filt_cutoff (tau)
419 static Butterworth2LowPass model_pred_aa_filt[3]; // Low pass filter for model prediction angular acceleration - oneloop_andi_filt_cutoff (tau)
420 static Butterworth2LowPass model_pred_ar_filt[3]; // Low pass filter for model prediction angular rates - ONELOOP_ANDI_FILT_CUTOFF_P/Q/R
421 static Butterworth2LowPass accely_filt; // Low pass filter for acceleration in y direction - oneloop_andi_filt_cutoff (tau)
422 static Butterworth2LowPass airspeed_filt; // Low pass filter for airspeed - oneloop_andi_filt_cutoff (tau)
423 
424 /* Define messages of the module*/
425 #if PERIODIC_TELEMETRY
427 
428 static void send_eff_mat_stab_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
429 {
430  float zero = 0.0;
431  pprz_msg_send_EFF_MAT_STAB(trans, dev, AC_ID,
434  ANDI_NUM_ACT, EFF_MAT_G[5],
435  1, &zero,
436  1, &zero);
437 }
438 
439 static void send_eff_mat_guid_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
440 {
441  pprz_msg_send_EFF_MAT_GUID(trans, dev, AC_ID,
445 }
446 static void send_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
447 {
448  pprz_msg_send_STAB_ATTITUDE(trans, dev, AC_ID,
449  3, eulers_zxy_des,
458 }
459 
460 static void send_guidance_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
461 {
462  pprz_msg_send_GUIDANCE(trans, dev, AC_ID,
483  &oneloop_andi.gui_ref.jer[2]);
484 }
485 
486 static void debug_vect(struct transport_tx *trans, struct link_device *dev, char *name, float *data, int datasize)
487 {
488  pprz_msg_send_DEBUG_VECT(trans, dev, AC_ID,
489  strlen(name), name,
490  datasize, data);
491 }
492 
493 static void send_oneloop_debug(struct transport_tx *trans, struct link_device *dev)
494 {
495  float temp_debug_vect[7];
496  temp_debug_vect[0] = model_pred[0];
497  temp_debug_vect[1] = model_pred[1];
498  temp_debug_vect[2] = model_pred[2];
499  temp_debug_vect[3] = model_pred[3];
500  temp_debug_vect[4] = model_pred[4];
501  temp_debug_vect[5] = model_pred[5];
502  temp_debug_vect[6] = RW.as;
503  debug_vect(trans, dev, "model_pred_as", temp_debug_vect, 7);
504 }
505 #endif
506 
508 static float positive_non_zero(float input)
509 {
510  if (input < FLT_EPSILON) {
511  input = 0.00001;
512  }
513  return input;
514 }
515 
518 static float k_e_1_2_f_v2(float omega, float zeta) {
519  omega = positive_non_zero(omega);
520  zeta = positive_non_zero(zeta);
521  return (omega * omega);
522 }
523 
524 static float k_e_2_2_f_v2(float omega, float zeta) {
525  omega = positive_non_zero(omega);
526  zeta = positive_non_zero(zeta);
527  return (2* zeta * omega);
528 }
529 
530 static float k_e_1_3_f_v2(float omega_n, UNUSED float zeta, float p1) {
531  omega_n = positive_non_zero(omega_n);
532  p1 = positive_non_zero(p1);
533  return (omega_n * omega_n * p1);
534 }
535 
536 static float k_e_2_3_f_v2(float omega_n, float zeta, float p1) {
537  omega_n = positive_non_zero(omega_n);
538  zeta = positive_non_zero(zeta);
539  p1 = positive_non_zero(p1);
540  return (omega_n * omega_n + 2 * zeta * omega_n * p1);
541 }
542 
543 static float k_e_3_3_f_v2(float omega_n, float zeta, float p1) {
544  omega_n = positive_non_zero(omega_n);
545  zeta = positive_non_zero(zeta);
546  p1 = positive_non_zero(p1);
547  return (2 * zeta * omega_n + p1);
548 }
549 
552 static float k_rm_1_3_f(float omega_n, float zeta, float p1) {
553  omega_n = positive_non_zero(omega_n);
554  zeta = positive_non_zero(zeta);
555  p1 = positive_non_zero(p1);
556  return (omega_n * omega_n * p1) / (omega_n * omega_n + omega_n * p1 * zeta * 2.0);
557 }
558 
559 static float k_rm_2_3_f(float omega_n, float zeta, float p1) {
560  omega_n = positive_non_zero(omega_n);
561  zeta = positive_non_zero(zeta);
562  p1 = positive_non_zero(p1);
563  return (omega_n * omega_n + omega_n * p1 * zeta * 2.0) / (p1 + omega_n * zeta * 2.0);
564 }
565 
566 static float k_rm_3_3_f(float omega_n, float zeta, float p1) {
567  omega_n = positive_non_zero(omega_n);
568  zeta = positive_non_zero(zeta);
569  p1 = positive_non_zero(p1);
570  return p1 + omega_n * zeta * 2.0;
571 }
572 
574 void float_rates_of_euler_dot_vec(float r[3], float e[3], float edot[3])
575 {
576  float sphi = sinf(e[0]);
577  float cphi = cosf(e[0]);
578  float stheta = sinf(e[1]);
579  float ctheta = cosf(e[1]);
580  r[0] = edot[0] - stheta * edot[2];
581  r[1] = cphi * edot[1] + sphi * ctheta * edot[2];
582  r[2] = -sphi * edot[1] + cphi * ctheta * edot[2];
583 }
584 
586 void float_euler_dot_of_rates_vec(float r[3], float e[3], float edot[3])
587 {
588  float sphi = sinf(e[0]);
589  float cphi = cosf(e[0]);
590  float stheta = sinf(e[1]);
591  float ctheta = cosf(e[1]);
592  if (fabs(ctheta) < FLT_EPSILON){
593  ctheta = FLT_EPSILON;
594  }
595  edot[0] = r[0] + sphi*stheta/ctheta*r[1] + cphi*stheta/ctheta*r[2];
596  edot[1] = cphi*r[1] - sphi*r[2];
597  edot[2] = sphi/ctheta*r[1] + cphi/ctheta*r[2];
598 }
599 
601 void err_nd(float err[], float a[], float b[], float k[], int n)
602 {
603  int8_t i;
604  for (i = 0; i < n; i++) {
605  err[i] = k[i] * (a[i] - b[i]);
606  }
607 }
608 
610 void err_sum_nd(float err[], float a[], float b[], float k[], float c[], int n)
611 {
612  int8_t i;
613  for (i = 0; i < n; i++) {
614  err[i] = k[i] * (a[i] - b[i]);
615  err[i] += c[i];
616  }
617 }
618 
620 void integrate_nd(float dt, float a[], float a_dot[], int n)
621 {
622  int8_t i;
623  for (i = 0; i < n; i++) {
624  a[i] = a[i] + dt * a_dot[i];
625  }
626 }
627 
629 void vect_bound_nd(float vect[], float bound, int n) {
630  float norm = float_vect_norm(vect,n);
631  norm = positive_non_zero(norm);
632  if((norm-bound) > FLT_EPSILON) {
633  float scale = bound/norm;
634  int8_t i;
635  for(i = 0; i < n; i++) {
636  vect[i] *= scale;
637  }
638  }
639 }
640 
642 void acc_body_bound(struct FloatVect2* vect, float bound) {
643  int n = 2;
644  float v[2] = {vect->x, vect->y};
645  float norm = float_vect_norm(v,n);
646  norm = positive_non_zero(norm);
647  if((norm-bound) > FLT_EPSILON) {
648  v[0] = Min(v[0], bound);
649  float acc_b_y_2 = bound*bound - v[0]*v[0];
650  acc_b_y_2 = positive_non_zero(acc_b_y_2);
651  v[1] = sqrtf(acc_b_y_2);
652  }
653  vect->x = v[0];
654  vect->y = v[1];
655 }
656 
658 float bound_v_from_a(float e_x[], float v_bound, float a_bound, int n) {
659  float norm = float_vect_norm(e_x,n);
660  norm = fmaxf(norm, 1.0);
661  float v_bound_a = sqrtf(fabs(2.0 * a_bound * norm));
662  return fminf(v_bound, v_bound_a);
663 }
664 
679 void rm_3rd_attitude(float dt, float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x_des[3], bool ow_psi, float psi_overwrite[4], float k1_rm[3], float k2_rm[3], float k3_rm[3], float max_ang_jerk){
680  float e_x[3];
681  float e_x_rates[3];
682  float e_x_d[3];
683  float e_x_2d[3];
684  float x_d_eul_ref[3];
685  err_nd(e_x, x_des, x_ref, k1_rm, 3);
686  float temp_diff = x_des[2] - x_ref[2];
687  NormRadAngle(temp_diff);
688  e_x[2] = k1_rm[2] * temp_diff; // Correction for Heading error +-Pi
689  float_rates_of_euler_dot_vec(e_x_rates, x_ref, e_x);
690  err_nd(e_x_d, e_x_rates, x_d_ref, k2_rm, 3);
691  err_nd(e_x_2d, e_x_d, x_2d_ref, k3_rm, 3);
692  float_vect_copy(x_3d_ref,e_x_2d,3);
693  vect_bound_nd(x_3d_ref, max_ang_jerk, 3);
694  if(ow_psi){x_3d_ref[2] = psi_overwrite[3];}
695  integrate_nd(dt, x_2d_ref, x_3d_ref, 3);
696  if(ow_psi){x_2d_ref[2] = psi_overwrite[2];}
697  integrate_nd(dt, x_d_ref, x_2d_ref, 3);
698  if(ow_psi){x_d_ref[2] = psi_overwrite[1];}
699  float_euler_dot_of_rates_vec(x_d_ref, x_ref, x_d_eul_ref);
700  integrate_nd(dt, x_ref, x_d_eul_ref, 3);
701  if(ow_psi){x_ref[2] = psi_overwrite[0];}
702  NormRadAngle(x_ref[2]);
703  //printf("k1_rm: %f %f %f\n", k1_rm[0], k1_rm[1], k1_rm[2]);
704  //printf("k2_rm: %f %f %f\n", k2_rm[0], k2_rm[1], k2_rm[2]);
705  //printf("k3_rm: %f %f %f\n", k3_rm[0], k3_rm[1], k3_rm[2]);
706 }
707 
720 void rm_3rd(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float* x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm){
721  float e_x = k1_rm * (x_des- *x_ref);
722  float e_x_d = k2_rm * (e_x- *x_d_ref);
723  float e_x_2d = k3_rm * (e_x_d- *x_2d_ref);
724  *x_3d_ref = e_x_2d;
725  *x_2d_ref = (*x_2d_ref + dt * (*x_3d_ref));
726  *x_d_ref = (*x_d_ref + dt * (*x_2d_ref));
727  *x_ref = (*x_ref + dt * (*x_d_ref ));
728 }
729 
742 void rm_3rd_head(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float* x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm){
743  float temp_diff = x_des - *x_ref;
744  NormRadAngle(temp_diff);
745  float e_x = k1_rm * temp_diff;
746  float e_x_d = k2_rm * (e_x- *x_d_ref);
747  float e_x_2d = k3_rm * (e_x_d- *x_2d_ref);
748  *x_3d_ref = e_x_2d;
749  *x_2d_ref = (*x_2d_ref + dt * (*x_3d_ref));
750  *x_d_ref = (*x_d_ref + dt * (*x_2d_ref));
751  *x_ref = (*x_ref + dt * (*x_d_ref ));
752 }
753 
770 void rm_3rd_pos(float dt, float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_des[], float k1_rm[], float k2_rm[], float k3_rm[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n){
771  float e_x[n];
772  float e_x_d[n];
773  float e_x_2d[n];
774  err_nd(e_x, x_des, x_ref, k1_rm, n);
775  float max_x_d = bound_v_from_a(e_x, x_d_bound, x_2d_bound, n);
776  vect_bound_nd(e_x, max_x_d, n);
777  err_nd(e_x_d, e_x, x_d_ref, k2_rm, n);
778  vect_bound_nd(e_x_d,x_2d_bound, n);
779  err_nd(e_x_2d, e_x_d, x_2d_ref, k3_rm, n);
780  float_vect_copy(x_3d_ref,e_x_2d,n);
781  vect_bound_nd(x_3d_ref, x_3d_bound, n);
782  integrate_nd(dt, x_2d_ref, x_3d_ref, n);
783  integrate_nd(dt, x_d_ref, x_2d_ref, n);
784  integrate_nd(dt, x_ref, x_d_ref, n);
785 }
786 
800 void rm_2nd_pos(float dt, float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_d_des[], float k2_rm[], float k3_rm[], float x_2d_bound, float x_3d_bound, int n){
801  float e_x_d[n];
802  float e_x_2d[n];
803  err_nd(e_x_d, x_d_des, x_d_ref, k2_rm, n);
804  vect_bound_nd(e_x_d,x_2d_bound, n);
805  err_nd(e_x_2d, e_x_d, x_2d_ref, k3_rm, n);
806  float_vect_copy(x_3d_ref,e_x_2d,n);
807  vect_bound_nd(x_3d_ref, x_3d_bound, n);
808  integrate_nd(dt, x_2d_ref, x_3d_ref, n);
809  integrate_nd(dt, x_d_ref, x_2d_ref, n);
810 }
811 
822 void rm_1st_pos(float dt, float x_2d_ref[], float x_3d_ref[], float x_2d_des[], float k3_rm[], float x_3d_bound, int n){
823  float e_x_2d[n];
824  err_nd(e_x_2d, x_2d_des, x_2d_ref, k3_rm, n);
825  float_vect_copy(x_3d_ref,e_x_2d,n);
826  vect_bound_nd(x_3d_ref, x_3d_bound, n);
827  integrate_nd(dt, x_2d_ref, x_3d_ref, n);
828 }
829 
830 
843 void rm_2nd(float dt, float* x_ref, float* x_d_ref, float* x_2d_ref, float x_des, float k1_rm, float k2_rm){
844  float e_x = k1_rm * (x_des- *x_ref);
845  float e_x_d = k2_rm * (e_x- *x_d_ref);
846  *x_2d_ref = e_x_d;
847  *x_d_ref = (*x_d_ref + dt * (*x_2d_ref));
848  *x_ref = (*x_ref + dt * (*x_d_ref ));
849 }
850 
866 static float ec_3rd(float x_ref, float x_d_ref, float x_2d_ref, float x_3d_ref, float x, float x_d, float x_2d, float k1_e, float k2_e, float k3_e){
867  float y_4d = k1_e*(x_ref-x)+k2_e*(x_d_ref-x_d)+k3_e*(x_2d_ref-x_2d)+x_3d_ref;
868  return y_4d;
869 }
870 void ec_3rd_pos( float y_4d[], float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x[], float x_d[], float x_2d[], float k1_e[], float k2_e[], float k3_e[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n){
871  float e_x_d[n];
872  float e_x_2d[n];
873 
874  err_sum_nd(e_x_d, x_ref, x, k1_e, x_d_ref, n);
875  vect_bound_nd(e_x_d, x_d_bound, n);
876 
877  err_sum_nd(e_x_2d, e_x_d, x_d, k2_e, x_2d_ref, n);
878  vect_bound_nd(e_x_2d,x_2d_bound, n);
879 
880  err_sum_nd(y_4d, e_x_2d, x_2d, k3_e, x_3d_ref, n);
881  vect_bound_nd(y_4d, x_3d_bound, n);
882 }
898 void ec_3rd_att(float y_4d[3], float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x[3], float x_d[3], float x_2d[3], float k1_e[3], float k2_e[3], float k3_e[3], float max_ang_jerk){
899  float y_4d_1[3];
900  float y_4d_2[3];
901  float y_4d_3[3];
902  err_nd(y_4d_1, x_ref, x, k1_e, 3);
903  float temp_diff = x_ref[2] - x[2];
904  NormRadAngle(temp_diff);
905  float e_x = temp_diff;
906  y_4d_1[2] = k1_e[2] * e_x; // Correction for Heading error +-Pi
907  err_nd(y_4d_2, x_d_ref, x_d, k2_e, 3);
908  err_nd(y_4d_3, x_2d_ref, x_2d, k3_e, 3);
909  float_vect_copy(y_4d,x_3d_ref,3);
910  float_vect_sum(y_4d, y_4d, y_4d_1, 3);
911  float_vect_sum(y_4d, y_4d, y_4d_2, 3);
912  float_vect_sum(y_4d, y_4d, y_4d_3, 3);
913  vect_bound_nd(y_4d, max_ang_jerk, 3);
914 }
915 
923 static float w_approx(float p1, float p2, float p3, float rm_k){
924  p1 = positive_non_zero(p1);
925  p2 = positive_non_zero(p2);
926  p3 = positive_non_zero(p3);
927  rm_k = positive_non_zero(rm_k);
928  float tao = (p1*p2+p1*p3+p2*p3)/(p1*p2*p3)/(rm_k);
929  tao = positive_non_zero(tao);
930  return 1.0/tao;
931 }
932 
937 void init_poles(void){
938 
939  // Attitude Controller Poles----------------------------------------------------------
940  float slow_pole = 15.1; // Pole of the slowest dynamics used in the attitude controller
941 
942  p_att_e.omega_n = 4.50;
943  p_att_e.zeta = 1.0;
944  p_att_e.p3 = slow_pole;
945 
946  p_att_rm.omega_n = 4.71;
947  p_att_rm.zeta = 1.0;
949 
950  p_head_e.omega_n = 1.80;
951  p_head_e.zeta = 1.0;
952  p_head_e.p3 = slow_pole;
953 
954  p_head_rm.omega_n = 2.56;
955  p_head_rm.zeta = 1.0;
957 
958  act_dynamics[COMMAND_ROLL] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
959  act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
960 
961  // Position Controller Poles----------------------------------------------------------
962  slow_pole = act_dynamics[COMMAND_ROLL]; // Pole of the slowest dynamics used in the position controller
963 
964  p_pos_e.omega_n = 1.0;
965  p_pos_e.zeta = 1.0;
966  p_pos_e.p3 = slow_pole;
967 
968  p_pos_rm.omega_n = 0.93;
969  p_pos_rm.zeta = 1.0;
971 
972  p_alt_e.omega_n = 1.0;// 3.0;
973  p_alt_e.zeta = 1.0;
974  p_alt_e.p3 = slow_pole;
975 
976  p_alt_rm.omega_n = 0.93; //1.93;
977  p_alt_rm.zeta = 1.0;
979 }
984 void init_controller(void){
985  /*Register a variable from nav_hybrid. Should be improved when nav hybrid is final.*/
986  float max_wind = 20.0;
987  max_v_nav = nav_max_speed + max_wind;
988  max_a_nav = nav_max_acceleration_sp;
989  /*Some calculations in case new poles have been specified*/
994 
995  //--ANDI Controller gains --------------------------------------------------------------------------------
996  /*Attitude Loop*/
1000  k_att_e.k1[1] = k_att_e.k1[0];
1001  k_att_e.k2[1] = k_att_e.k2[0];
1002  k_att_e.k3[1] = k_att_e.k3[0];
1003 
1007  k_att_rm.k1[1] = k_att_rm.k1[0];
1008  k_att_rm.k2[1] = k_att_rm.k2[0];
1009  k_att_rm.k3[1] = k_att_rm.k3[0];
1010 
1011  //printf("Attitude RM Gains: %f %f %f\n", k_att_rm.k1[0], k_att_rm.k2[0], k_att_rm.k3[0]);
1012  //printf("Attitude E Gains: %f %f %f\n", k_att_e.k1[0], k_att_e.k2[0], k_att_e.k3[0]);
1013  /*Heading Loop NAV*/
1017 
1021 
1022  /*Position Loop*/
1023  // k_pos_e.k1[0] = k_e_1_3_f_v2(p_pos_e.omega_n, p_pos_e.zeta, p_pos_e.p3);
1024  // k_pos_e.k2[0] = k_e_2_3_f_v2(p_pos_e.omega_n, p_pos_e.zeta, p_pos_e.p3);
1025  // k_pos_e.k3[0] = k_e_3_3_f_v2(p_pos_e.omega_n, p_pos_e.zeta, p_pos_e.p3);
1029  k_pos_e.k1[1] = k_pos_e.k1[0];
1030  k_pos_e.k2[1] = k_pos_e.k2[0];
1031  k_pos_e.k3[1] = k_pos_e.k3[0];
1032 
1036  k_pos_rm.k1[1] = k_pos_rm.k1[0];
1037  k_pos_rm.k2[1] = k_pos_rm.k2[0];
1038  k_pos_rm.k3[1] = k_pos_rm.k3[0];
1041 
1042  /*Altitude Loop*/
1043  // k_pos_e.k1[2] = k_e_1_3_f_v2(p_alt_e.omega_n, p_alt_e.zeta, p_alt_e.p3);
1044  // k_pos_e.k2[2] = k_e_2_3_f_v2(p_alt_e.omega_n, p_alt_e.zeta, p_alt_e.p3);
1045  // k_pos_e.k3[2] = k_e_3_3_f_v2(p_alt_e.omega_n, p_alt_e.zeta, p_alt_e.p3);
1049 
1053 
1054  //--INDI Controller gains --------------------------------------------------------------------------------
1055  /*Attitude Loop*/
1058  k_att_e_indi.k3[0] = 1.0;
1059  k_att_e_indi.k1[1] = k_att_e_indi.k1[0];
1060  k_att_e_indi.k2[1] = k_att_e_indi.k2[0];
1061  k_att_e_indi.k3[1] = k_att_e_indi.k3[0];
1062 
1063  /*Heading Loop NAV*/
1066  k_att_e_indi.k3[2] = 1.0;
1067 
1068  /*Position Loop*/
1071  k_pos_e_indi.k3[0] = 1.0;
1072  k_pos_e_indi.k1[1] = k_pos_e_indi.k1[0];
1073  k_pos_e_indi.k2[1] = k_pos_e_indi.k2[0];
1074  k_pos_e_indi.k3[1] = k_pos_e_indi.k3[0];
1075 
1076  /*Altitude Loop*/
1079  k_pos_e_indi.k3[2] = 1.0;
1080 
1081  //------------------------------------------------------------------------------------------
1082  /*Approximated Dynamics*/
1083  act_dynamics[COMMAND_ROLL] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
1084  act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
1085 }
1086 
1087 
1089 void init_filter(void)
1090 {
1091  //printf("oneloop andi filt cutoff PQR: %f %f %f\n", oneloop_andi_filt_cutoff_p,oneloop_andi_filt_cutoff_q,oneloop_andi_filt_cutoff_r);
1092  float tau = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff);
1093  float tau_a = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff_a);
1094  float tau_v = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff_v);
1095  float sample_time = 1.0 / PERIODIC_FREQUENCY;
1096 
1097  // Filtering of the Inputs with 3 dimensions (e.g. rates and accelerations)
1098  int8_t i;
1099  for (i = 0; i < 3; i++) {
1100  init_butterworth_2_low_pass(&ang_rate_lowpass_filters[i], tau, sample_time, 0.0);
1101  init_butterworth_2_low_pass(&model_pred_aa_filt[i], tau, sample_time, 0.0);
1102  init_butterworth_2_low_pass(&filt_accel_ned[i], tau_a, sample_time, 0.0 );
1103  init_butterworth_2_low_pass(&filt_veloc_ned[i], tau_v, sample_time, 0.0 );
1104  init_butterworth_2_low_pass(&model_pred_la_filt[i], tau_a, sample_time, 0.0);
1105  }
1106 
1107  // Init rate filter for feedback
1108  float time_constants[3] = {1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_p), 1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_q), 1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_r)};
1109  init_butterworth_2_low_pass(&rates_filt_bt[0], time_constants[0], sample_time, stateGetBodyRates_f()->p);
1110  init_butterworth_2_low_pass(&rates_filt_bt[1], time_constants[1], sample_time, stateGetBodyRates_f()->q);
1111  init_butterworth_2_low_pass(&rates_filt_bt[2], time_constants[2], sample_time, stateGetBodyRates_f()->r);
1112  init_butterworth_2_low_pass(&model_pred_ar_filt[0], time_constants[0], sample_time, 0.0);
1113  init_butterworth_2_low_pass(&model_pred_ar_filt[1], time_constants[1], sample_time, 0.0);
1114  init_butterworth_2_low_pass(&model_pred_ar_filt[2], time_constants[2], sample_time, 0.0);
1115 
1116  // Some other filters
1117  init_butterworth_2_low_pass(&accely_filt, tau, sample_time, 0.0);
1118  init_butterworth_2_low_pass(&airspeed_filt, tau, sample_time, 0.0);
1119 }
1120 
1121 
1124  struct NedCoor_f *accel = stateGetAccelNed_f();
1125  struct NedCoor_f *veloc = stateGetSpeedNed_f();
1126  struct FloatRates *body_rates = stateGetBodyRates_f();
1127  float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
1134  calc_model();
1135  int8_t i;
1136 
1137  for (i = 0; i < 3; i++) {
1141  update_butterworth_2_low_pass(&rates_filt_bt[i], rate_vect[i]);
1142  lin_acc[i] = filt_accel_ned[i].o[0] + model_pred[i] - model_pred_la_filt[i].o[0];
1143  ang_acc[i] = (ang_rate_lowpass_filters[i].o[0]- ang_rate_lowpass_filters[i].o[1]) * PERIODIC_FREQUENCY + model_pred[3+i] - model_pred_aa_filt[i].o[0];
1144  model_pred_ar[i] = model_pred_ar[i] + ang_acc[i] / PERIODIC_FREQUENCY;
1146  ang_rate[i] = rates_filt_bt[i].o[0] + model_pred_ar[i] - model_pred_ar_filt[i].o[0];
1147  }
1148  // Propagate filter for sideslip correction
1149  float accely = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->y);
1151  float airspeed_meas = stateGetAirspeed_f();
1152  Bound(airspeed_meas, 0.0, 30.0);
1154 }
1155 
1158 {
1159  oneloop_andi.half_loop = true;
1161  init_poles();
1162  // Make sure that the dynamics are positive and non-zero
1163  int8_t i;
1164  for (i = 0; i < ANDI_NUM_ACT_TOT; i++) {
1166  }
1167  // Initialize Effectiveness matrix
1170  for (i = 0; i < ANDI_OUTPUTS; i++) {
1171  bwls_1l[i] = EFF_MAT_G[i];
1172  }
1173  // Initialize filters and other variables
1174  init_filter();
1175  init_controller();
1190  eulers_zxy_des.phi = 0.0;
1191  eulers_zxy_des.theta = 0.0;
1192  eulers_zxy_des.psi = 0.0;
1195 
1196  // Start telemetry
1197  #if PERIODIC_TELEMETRY
1198  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_STAB_ATTITUDE, send_oneloop_andi);
1203  #endif
1204 }
1205 
1212 void oneloop_andi_enter(bool half_loop_sp, int ctrl_type)
1213 {
1214  ele_min = 0.0;
1215  oneloop_andi.half_loop = half_loop_sp;
1216  oneloop_andi.ctrl_type = ctrl_type;
1218  psi_des_deg = DegOfRad(eulers_zxy.psi);
1221  int8_t i;
1222  for (i = 0; i < ANDI_OUTPUTS; i++) {
1223  bwls_1l[i] = EFF_MAT_G[i];
1224  }
1225  init_filter();
1226  init_controller();
1227  /* Stabilization Reset */
1236  eulers_zxy_des.phi = 0.0;
1237  eulers_zxy_des.theta = 0.0;
1241  /*Guidance Reset*/
1242 }
1243 
1251 void oneloop_andi_RM(bool half_loop, struct FloatVect3 PSA_des, int rm_order_h, int rm_order_v, bool in_flight_oneloop)
1252 {
1253  // Initialize some variables
1254  a_thrust = 0.0;
1255  nav_target[0] = PSA_des.x;
1256  nav_target[1] = PSA_des.y;
1257  nav_target[2] = PSA_des.z;
1258  float thrust_cmd_1l = 0.0;
1259  float des_r = 0.0;
1260  // Generate reference signals with reference model
1261  if(half_loop){
1262  // Disregard X and Y jerk objectives
1263  Wv_wls[0] = 0.0;
1264  Wv_wls[1] = 0.0;
1265  // Overwrite references with actual signals (for consistent plotting)
1270  // Set desired attitude with stick input
1273  // Set desired Yaw rate with stick input
1274  des_r = (float) (radio_control_get(RADIO_YAW))/MAX_PPRZ*max_r; // Get yaw rate from stick
1275  BoundAbs(des_r,max_r); // Bound yaw rate
1276  float delta_psi_des_rad = des_r * dt_1l; // Integrate desired Yaw rate to get desired change in yaw
1277  float delta_psi_rad = eulers_zxy_des.psi-eulers_zxy.psi; // Calculate current yaw difference between des and actual
1278  NormRadAngle(delta_psi_rad); // Normalize the difference
1279  if (fabs(delta_psi_rad) > RadOfDeg(30.0)){ // If difference is bigger than 10 deg do not further increment desired
1280  delta_psi_des_rad = 0.0;
1281  }
1282  psi_des_rad += delta_psi_des_rad; // Incrementdesired yaw
1283  NormRadAngle(psi_des_rad);
1284  // Register Attitude Setpoints from previous loop
1285  if (!in_flight_oneloop){
1287  }
1289  float att_des[3] = {eulers_zxy_des.phi, eulers_zxy_des.theta, eulers_zxy_des.psi};
1290  // Create commands adhoc to get actuators to the wanted level
1291  thrust_cmd_1l = (float) radio_control_get(RADIO_THROTTLE);
1292  Bound(thrust_cmd_1l,0.0,MAX_PPRZ);
1293  int8_t i;
1294  for (i = 0; i < ANDI_NUM_ACT; i++) {
1295  a_thrust +=(thrust_cmd_1l - use_increment*actuator_state_1l[i]) * bwls_1l[2][i] / (ratio_u_un[i] * ratio_vn_v[aD]);
1296  }
1298  }else{
1299  // Make sure X and Y jerk objectives are active
1300  Wv_wls[0] = Wv[0];
1301  Wv_wls[1] = Wv[1];
1302  // Generate Reference signals for positioning using RM
1303  if (rm_order_h == 3){
1305  } else if (rm_order_h == 2){
1308  reshape_wind();//returns accel sp as nav target new
1310  // rm_2nd_pos(dt_1l, oneloop_andi.gui_ref.vel, oneloop_andi.gui_ref.acc, oneloop_andi.gui_ref.jer, nav_target_new, k_pos_rm.k2, k_pos_rm.k3, max_a_nav, max_j_nav, 2);
1311  } else if (rm_order_h == 1){
1315  }
1316  // Update desired Heading (psi_des_rad) based on previous loop or changed setting
1317  if (heading_manual){
1318  psi_des_rad = RadOfDeg(psi_des_deg);
1319  if (yaw_stick_in_auto){
1321  }
1322  } else {
1323  float ref_mag_vel = float_vect_norm(oneloop_andi.gui_ref.vel,2);
1325  NormRadAngle(psi_des_rad);
1326  if (ref_mag_vel > 3.0){
1327  float psi_gs = atan2f(oneloop_andi.gui_ref.vel[1],oneloop_andi.gui_ref.vel[0]);
1328  float delta_des_gs = psi_gs-psi_des_rad; // Calculate current yaw difference between des and gs
1329  NormRadAngle(delta_des_gs);
1330  if (fabs(delta_des_gs) > RadOfDeg(60.0)){ // If difference is bigger than 60 deg bound the des psi angle so that it does not deviate too much
1331  delta_des_gs *= RadOfDeg(60.0)/fabs(delta_des_gs);
1332  psi_des_rad = psi_gs - delta_des_gs;
1333  NormRadAngle(psi_des_rad);
1334  }
1335  }
1336  }
1337  // Register Attitude Setpoints from previous loop
1338  if (!in_flight_oneloop){
1340  }
1342  float att_des[3] = {eulers_zxy_des.phi, eulers_zxy_des.theta, eulers_zxy_des.psi};
1343  // The RM functions want an array as input. Create a single entry array and write the vertical guidance entries.
1344  float single_value_ref[1] = {oneloop_andi.gui_ref.pos[2]};
1345  float single_value_d_ref[1] = {oneloop_andi.gui_ref.vel[2]};
1346  float single_value_2d_ref[1] = {oneloop_andi.gui_ref.acc[2]};
1347  float single_value_3d_ref[1] = {oneloop_andi.gui_ref.jer[2]};
1348  float single_value_nav_target[1] = {nav_target[2]};
1349  float single_value_k1_rm[1] = {k_pos_rm.k1[2]};
1350  float single_value_k2_rm[1] = {k_pos_rm.k2[2]};
1351  float single_value_k3_rm[1] = {k_pos_rm.k3[2]};
1352  if (rm_order_v == 3){
1353  rm_3rd_pos(dt_1l, single_value_ref, single_value_d_ref, single_value_2d_ref, single_value_3d_ref, single_value_nav_target, single_value_k1_rm, single_value_k2_rm, single_value_k3_rm, max_v_nav_v, max_a_nav, max_j_nav, 1);
1354  oneloop_andi.gui_ref.pos[2] = single_value_ref[0];
1355  oneloop_andi.gui_ref.vel[2] = single_value_d_ref[0];
1356  oneloop_andi.gui_ref.acc[2] = single_value_2d_ref[0];
1357  oneloop_andi.gui_ref.jer[2] = single_value_3d_ref[0];
1358  } else if (rm_order_v == 2){
1359  rm_2nd_pos(dt_1l, single_value_d_ref, single_value_2d_ref, single_value_3d_ref, single_value_nav_target, single_value_k2_rm, single_value_k3_rm, max_a_nav, max_j_nav, 1);
1361  oneloop_andi.gui_ref.vel[2] = single_value_d_ref[0];
1362  oneloop_andi.gui_ref.acc[2] = single_value_2d_ref[0];
1363  oneloop_andi.gui_ref.jer[2] = single_value_3d_ref[0];
1364  } else if (rm_order_v == 1){
1365  rm_1st_pos(dt_1l, single_value_2d_ref, single_value_3d_ref, single_value_nav_target, single_value_k3_rm, max_j_nav, 1);
1368  oneloop_andi.gui_ref.acc[2] = single_value_2d_ref[0];
1369  oneloop_andi.gui_ref.jer[2] = single_value_3d_ref[0];
1370  }
1371  // Run chirp test if turnerd on (overwrite the guidance references)
1373  // Generate Reference signals for attitude using RM
1374  // FIX ME ow not yet defined, will be useful in the future to have accurate psi tracking in NAV functions
1375  bool ow_psi = false;
1377  }
1378 }
1379 
1388 void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des, int rm_order_h, int rm_order_v)
1389 {
1390  // At beginnig of the loop: (1) Register Attitude, (2) Initialize gains of RM and EC, (3) Calculate Normalization of Actuators Signals, (4) Propagate Actuator Model, (5) Update effectiveness matrix
1392  init_controller();
1396  int8_t i;
1397  for (i = 0; i < ANDI_OUTPUTS; i++) {
1398  bwls_1l[i] = EFF_MAT_G[i];
1399  }
1400 
1401  // If drone is not on the ground use incremental law
1402  use_increment = 0.0;
1403  bool in_flight_oneloop = false;
1404  if(in_flight) {
1405  use_increment = 1.0;
1406  in_flight_oneloop = true;
1407  }
1409  in_flight_oneloop = false;
1410  }
1411 
1412  // Register the state of the drone in the variables used in RM and EC
1413  // (1) Attitude related
1417  oneloop_andi_propagate_filters(); //needs to be after update of attitude vector
1418  oneloop_andi.sta_state.att_d[0] = ang_rate[0];//rates_filt_bt[0].o[0];
1419  oneloop_andi.sta_state.att_d[1] = ang_rate[1];//rates_filt_bt[1].o[0];
1420  oneloop_andi.sta_state.att_d[2] = ang_rate[2];//rates_filt_bt[2].o[0];
1424  // (2) Position related
1434 
1435  // Calculated feedforward signal for yaW CONTROL
1436  g2_ff = 0.0;
1437 
1438  for (i = 0; i < ANDI_NUM_ACT; i++) {
1440  g2_ff += G2_RW[i] * act_dynamics[i] * andi_du[i];
1441  } else if (oneloop_andi.ctrl_type == CTRL_INDI){
1442  g2_ff += G2_RW[i]* andi_du_n[i];
1443  }
1444  }
1445  //G2 is scaled by ANDI_G_SCALING to make it readable
1446  g2_ff = g2_ff;
1447  // Run the Reference Model (RM)
1448  oneloop_andi_RM(half_loop, PSA_des, rm_order_h, rm_order_v, in_flight_oneloop);
1449  // Guidance Pseudo Control Vector (nu) based on error controller
1450  if(half_loop){
1451  nu[0] = 0.0;
1452  nu[1] = 0.0;
1453  nu[2] = a_thrust;
1454  ctrl_off = false;
1455  }else{
1458  // nu[0] = ec_3rd(oneloop_andi.gui_ref.pos[0], oneloop_andi.gui_ref.vel[0], oneloop_andi.gui_ref.acc[0], oneloop_andi.gui_ref.jer[0], oneloop_andi.gui_state.pos[0], oneloop_andi.gui_state.vel[0], oneloop_andi.gui_state.acc[0], k_pos_e.k1[0], k_pos_e.k2[0], k_pos_e.k3[0]);
1459  // nu[1] = ec_3rd(oneloop_andi.gui_ref.pos[1], oneloop_andi.gui_ref.vel[1], oneloop_andi.gui_ref.acc[1], oneloop_andi.gui_ref.jer[1], oneloop_andi.gui_state.pos[1], oneloop_andi.gui_state.vel[1], oneloop_andi.gui_state.acc[1], k_pos_e.k1[1], k_pos_e.k2[1], k_pos_e.k3[1]);
1460  // nu[2] = ec_3rd(oneloop_andi.gui_ref.pos[2], oneloop_andi.gui_ref.vel[2], oneloop_andi.gui_ref.acc[2], oneloop_andi.gui_ref.jer[2], oneloop_andi.gui_state.pos[2], oneloop_andi.gui_state.vel[2], oneloop_andi.gui_state.acc[2], k_pos_e.k1[2], k_pos_e.k2[2], k_pos_e.k3[2]);
1461  } else if (oneloop_andi.ctrl_type == CTRL_INDI){
1465  }
1466  }
1467  // Attitude Pseudo Control Vector (nu) based on error controller
1468  float y_4d_att[3];
1471  } else if (oneloop_andi.ctrl_type == CTRL_INDI){
1472  float dummy0[3] = {0.0, 0.0, 0.0};
1474  }
1475  nu[3] = y_4d_att[0];
1476  nu[4] = y_4d_att[1];
1477  nu[5] = y_4d_att[2] + g2_ff;
1478  if (!chirp_on){
1481  Bound(pitch_pref,0.0,theta_pref_max);
1482  }
1483  u_pref[COMMAND_PITCH] = pitch_pref;
1484  // Calculate the min and max increments
1485  for (i = 0; i < ANDI_NUM_ACT_TOT; i++) {
1486  switch (i) {
1487  case COMMAND_MOTOR_FRONT:
1488  case COMMAND_MOTOR_RIGHT:
1489  case COMMAND_MOTOR_BACK:
1490  case COMMAND_MOTOR_LEFT:
1491  du_min_1l[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
1492  du_pref_1l[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
1493  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1495  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1496  } else
1497  {
1498  du_max_1l[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
1499  }
1500  break;
1501  case COMMAND_MOTOR_PUSHER:
1502  case COMMAND_RUDDER:
1503  du_min_1l[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
1504  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1505  du_pref_1l[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
1506  break;
1507  case COMMAND_AILERONS:
1508  if(RW.skew.deg > 25.0){
1509  du_min_1l[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
1510  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1511  } else {
1512  du_min_1l[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
1513  du_max_1l[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
1514  }
1515  du_pref_1l[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
1516  break;
1517  case COMMAND_FLAPS:
1518  if(RW.skew.deg > 50.0){
1519  du_min_1l[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
1520  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1521  } else {
1522  du_min_1l[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
1523  du_max_1l[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
1524  }
1525  du_pref_1l[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
1526  break;
1527  case COMMAND_ELEVATOR:
1528  du_min_1l[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
1529  du_max_1l[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
1530  u_pref[i] = RW.ele_pref;
1531  du_pref_1l[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
1532  break;
1533  case COMMAND_ROLL:
1537  break;
1538  case COMMAND_PITCH:
1540  du_min_1l[i] = (RadOfDeg(-17.0) - oneloop_andi.sta_state.att[i-ANDI_NUM_ACT])/ratio_u_un[i];
1541  du_max_1l[i] = (RadOfDeg(17.0) - oneloop_andi.sta_state.att[i-ANDI_NUM_ACT])/ratio_u_un[i];
1542  } else {
1545  }
1547  break;
1548  }
1549  }
1550 
1551  // WLS Control Allocator
1552  normalize_nu();
1554  for (i = 0; i < ANDI_NUM_ACT_TOT; i++){
1555  andi_du[i] = (float)(andi_du_n[i] * ratio_u_un[i]);
1556  }
1557 
1558  if (in_flight_oneloop) {
1559  // Add the increments to the actuators
1561  andi_u[COMMAND_ROLL] = andi_du[COMMAND_ROLL] + oneloop_andi.sta_state.att[0];
1562  andi_u[COMMAND_PITCH] = andi_du[COMMAND_PITCH] + oneloop_andi.sta_state.att[1];
1563  } else {
1564  // Not in flight, so don't increment
1566  andi_u[COMMAND_ROLL] = andi_du[COMMAND_ROLL];
1567  andi_u[COMMAND_PITCH] = andi_du[COMMAND_PITCH];
1568  }
1569 
1570 #ifdef COMMAND_MOTOR_PUSHER
1571  if ((half_loop)){
1572  andi_u[COMMAND_MOTOR_PUSHER] = radio_control.values[RADIO_AUX4];
1573  }
1574 #endif
1575  // TODO : USE THE PROVIDED MAX AND MIN and change limits for phi and theta
1576  // Bound the inputs to the actuators
1577  for (i = 0; i < ANDI_NUM_ACT_TOT; i++) {
1578  Bound(andi_u[i], act_min[i], act_max[i]);
1579  }
1580 
1581  /*Commit the actuator command*/
1582  for (i = 0; i < ANDI_NUM_ACT; i++) {
1583  //actuators_pprz[i] = (int16_t) andi_u[i];
1584  commands[i] = (int16_t) andi_u[i];
1585  }
1586  commands[COMMAND_THRUST] = (commands[COMMAND_MOTOR_FRONT] + commands[COMMAND_MOTOR_RIGHT] + commands[COMMAND_MOTOR_BACK] + commands[COMMAND_MOTOR_LEFT])/num_thrusters_oneloop;
1587  autopilot.throttle = commands[COMMAND_THRUST];
1588  stabilization.cmd[COMMAND_THRUST] = commands[COMMAND_THRUST];
1590  eulers_zxy_des.phi = andi_u[COMMAND_ROLL];
1591  eulers_zxy_des.theta = andi_u[COMMAND_PITCH];
1592  } else {
1593  eulers_zxy_des.phi = andi_u[COMMAND_ROLL];
1594  eulers_zxy_des.theta = andi_u[COMMAND_PITCH];
1595  }
1596  if (heading_manual){
1597  psi_des_deg = DegOfRad(psi_des_rad);
1598  }
1599 
1600  stabilization.cmd[COMMAND_ROLL] = (int16_t) (DegOfRad(eulers_zxy_des.phi ) * MAX_PPRZ / DegOfRad(ONELOOP_ANDI_MAX_PHI ));
1601  stabilization.cmd[COMMAND_PITCH] = (int16_t) (DegOfRad(eulers_zxy_des.theta) * MAX_PPRZ / DegOfRad(ONELOOP_ANDI_MAX_THETA));
1602  stabilization.cmd[COMMAND_YAW] = (int16_t) (psi_des_deg * MAX_PPRZ / 180.0);
1603 }
1604 
1607 {
1608  int8_t i;
1609  float prev_actuator_state_1l;
1610  for (i = 0; i < ANDI_NUM_ACT; i++) {
1611  prev_actuator_state_1l = actuator_state_1l[i];
1612  actuator_state_1l[i] = prev_actuator_state_1l + act_dynamics_d[i] * (andi_u[i] - prev_actuator_state_1l);
1613  if(!autopilot_get_motors_on()){
1614  actuator_state_1l[i] = 0.0;
1615  }
1616  Bound(actuator_state_1l[i],act_min[i], act_max[i]);
1617  }
1618 }
1619 
1624 void G1G2_oneloop(int ctrl_type) {
1625  int i = 0;
1626  float scaler = 1.0;
1627  for (i = 0; i < ANDI_NUM_ACT_TOT; i++) {
1628 
1629  switch (i) {
1630  case (COMMAND_MOTOR_FRONT):
1631  case (COMMAND_MOTOR_RIGHT):
1632  case (COMMAND_MOTOR_BACK):
1633  case (COMMAND_MOTOR_LEFT):
1634  case (COMMAND_MOTOR_PUSHER):
1635  case (COMMAND_ELEVATOR):
1636  case (COMMAND_RUDDER):
1637  case (COMMAND_AILERONS):
1638  case (COMMAND_FLAPS):
1639  if(ctrl_type == CTRL_ANDI){
1640  scaler = act_dynamics[i] * ratio_u_un[i];
1641  } else if (ctrl_type == CTRL_INDI){
1642  scaler = ratio_u_un[i];
1643  }
1644  break;
1645  case (COMMAND_ROLL):
1646  case (COMMAND_PITCH):
1647  if(ctrl_type == CTRL_ANDI){
1648  scaler = act_dynamics[i] * ratio_u_un[i];
1649  } else if (ctrl_type == CTRL_INDI){
1650  scaler = ratio_u_un[i];
1651  }
1652  break;
1653  default:
1654  break;
1655  }
1656  int j = 0;
1657  for (j = 0; j < ANDI_OUTPUTS; j++) {
1658  EFF_MAT_G[j][i] = EFF_MAT_RW[j][i] * scaler * ratio_vn_v[j];
1659  if (airspeed_filt.o[0] < ELE_MIN_AS && i == COMMAND_ELEVATOR){
1660  EFF_MAT_G[j][i] = 0.0;
1661  }
1663  EFF_MAT_G[j][i] = 0.0;
1664  }
1665  if (ctrl_off && i < 4 && j == 5){ //hack test
1666  EFF_MAT_G[j][i] = 0.0;
1667  }
1668  if (ctrl_off && i < 4 && j == 4){ //hack test
1669  EFF_MAT_G[j][i] = 0.0;
1670  }
1671  if (ctrl_off && i < 4 && j == 3){ //hack test
1672  EFF_MAT_G[j][i] = 0.0;
1673  }
1674  }
1675  }
1676 }
1677 
1680  int8_t i;
1681  for (i = 0; i < ANDI_NUM_ACT_TOT; i++){
1682  act_dynamics_d[i] = 1.0-exp(-act_dynamics[i]*dt_1l);
1683  Bound(act_dynamics_d[i],0.00001,1.0);
1684  Bound(act_max[i],0,MAX_PPRZ);
1685  Bound(act_min[i],-MAX_PPRZ,0);
1686  float ratio_numerator = act_max[i]-act_min[i];
1687  ratio_numerator = positive_non_zero(ratio_numerator);// make sure numerator is non-zero
1688  float ratio_denominator = act_max_norm[i]-act_min_norm[i];
1689  ratio_denominator = positive_non_zero(ratio_denominator); // make sure denominator is non-zero
1690  ratio_u_un[i] = ratio_numerator/ratio_denominator;
1691  ratio_u_un[i] = positive_non_zero(ratio_u_un[i]);// make sure ratio is not zero
1692  }
1693  for (i = 0; i < ANDI_OUTPUTS; i++){
1694  float ratio_numerator = positive_non_zero(nu_norm_max);
1695  float ratio_denominator = 1.0;
1696  switch (i) {
1697  case (aN):
1698  case (aE):
1699  case (aD):
1700  ratio_denominator = positive_non_zero(max_j_nav);
1701  ratio_vn_v[i] = ratio_numerator/ratio_denominator;
1702  break;
1703  case (ap):
1704  case (aq):
1705  case (ar):
1706  ratio_denominator = positive_non_zero(max_j_ang);
1707  ratio_vn_v[i] = ratio_numerator/ratio_denominator;
1708  break;
1709  }
1710  }
1711 }
1712 
1714 void normalize_nu(void){
1715  int8_t i;
1716  for (i = 0; i < ANDI_OUTPUTS; i++){
1717  nu_n[i] = nu[i] * ratio_vn_v[i];
1718  }
1719 }
1720 
1722 void calc_model(void){
1723  int8_t i;
1724  int8_t j;
1725  // // Absolute Model Prediction :
1726  float sphi = sinf(eulers_zxy.phi);
1727  float cphi = cosf(eulers_zxy.phi);
1728  float stheta = sinf(eulers_zxy.theta);
1729  float ctheta = cosf(eulers_zxy.theta);
1730  float spsi = sinf(eulers_zxy.psi);
1731  float cpsi = cosf(eulers_zxy.psi);
1732  // Thrust and Pusher force estimation
1733  float L = RW.wing.L / RW.m; // Lift specific force
1734  float T = RW.T / RW.m; // Thrust specific force. Minus gravity is a guesstimate.
1735  float P = RW.P / RW.m; // Pusher specific force
1736 
1737  model_pred[0] = -(cpsi * stheta + ctheta * sphi * spsi) * T + (cpsi * ctheta - sphi * spsi * stheta) * P - sphi * spsi * L;
1738  model_pred[1] = -(spsi * stheta - cpsi * ctheta * sphi) * T + (ctheta * spsi + cpsi * sphi * stheta) * P + cpsi * sphi * L;
1739  model_pred[2] = g - cphi * ctheta * T - cphi * stheta * P - cphi * L;
1740  for (i = 3; i < ANDI_OUTPUTS; i++){ // For loop for prediction of angular acceleration
1741  model_pred[i] = 0.0; //
1742  for (j = 0; j < ANDI_NUM_ACT; j++){
1743  if(j == COMMAND_ELEVATOR){
1744  model_pred[i] = model_pred[i] + (actuator_state_1l[j] - RW.ele_pref) * EFF_MAT_RW[i][j]; // Ele pref is incidence angle
1745  } else {
1746  model_pred[i] = model_pred[i] + actuator_state_1l[j] * EFF_MAT_RW[i][j];
1747  }
1748  }
1749  }
1750 }
1751 
1753 void oneloop_from_nav(bool in_flight)
1754 {
1755  if (!in_flight) {
1757  }
1758  struct FloatVect3 PSA_des;
1759  PSA_des.x = stateGetPositionNed_f()->x;
1760  PSA_des.y = stateGetPositionNed_f()->y;
1761  PSA_des.z = stateGetPositionNed_f()->z;
1762  int rm_order_h = 3;
1763  int rm_order_v = 3;
1764  // Oneloop controller wants desired targets and handles reference generation internally
1765  switch (nav.setpoint_mode) {
1766  case NAV_SETPOINT_MODE_POS:
1769  rm_order_h = 3;
1770  break;
1774  rm_order_h = 2;
1775  break;
1776  }
1777  switch (nav.vertical_mode) {
1778  case NAV_VERTICAL_MODE_ALT:
1780  rm_order_v = 3;
1781  break;
1784  rm_order_v = 2;
1785  break;
1786  }
1787  oneloop_andi_run(in_flight, false, PSA_des, rm_order_h, rm_order_v);
1788 }
1789 
1792 {
1793  // Coordinated turn
1794  // feedforward estimate angular rotation omega = g*tan(phi)/v
1795  float omega = 0.0;
1796  const float max_phi = RadOfDeg(ONELOOP_ANDI_MAX_BANK);
1797  float airspeed_turn = airspeed_filt.o[0];
1798  Bound(airspeed_turn, 1.0f, 30.0f);
1799  // Use the current roll angle to determine the corresponding heading rate of change.
1800  float coordinated_turn_roll = eulers_zxy.phi;
1801  // Prevent flipping
1802  if( (eulers_zxy.theta > 0.0f) && ( fabs(eulers_zxy.phi) < eulers_zxy.theta)) {
1803  coordinated_turn_roll = ((eulers_zxy.phi > 0.0f) - (eulers_zxy.phi < 0.0f)) * eulers_zxy.theta;
1804  }
1805  BoundAbs(coordinated_turn_roll, max_phi);
1806  omega = g / airspeed_turn * tanf(coordinated_turn_roll);
1807  #ifdef FWD_SIDESLIP_GAIN
1808  // Add sideslip correction
1809  omega -= accely_filt.o[0]*fwd_sideslip_gain;
1810  #endif
1811  return omega;
1812 }
1813 
1815 static float chirp_pos_p_ref(float delta_t, float f0, float k, float A){
1816  float p_ref_fun = sinf(delta_t * M_PI * (f0 + k * delta_t) * 2.0);
1817  return (A * p_ref_fun);
1818 }
1820 static float chirp_pos_v_ref(float delta_t, float f0, float k, float A){
1821  float v_ref_fun = cosf(delta_t * M_PI * (f0 + k * delta_t) * 2.0) * (M_PI * (f0 + k * delta_t) * 2.0 + k * delta_t * M_PI * 2.0);
1822  return (A * v_ref_fun);
1823 }
1825 static float chirp_pos_a_ref(float delta_t, float f0, float k, float A){
1826  float a_ref_fun = -sinf(delta_t * M_PI * (f0 + k * delta_t) * 2.0) * pow((M_PI * (f0 + k * delta_t) * 2.0 + k * delta_t * M_PI * 2.0), 2) + k * M_PI * cosf(delta_t * M_PI * (f0 + k * delta_t) * 2.0) * 4.0;
1827  return (A * a_ref_fun);
1828 }
1830 static float chirp_pos_j_ref(float delta_t, float f0, float k, float A){
1831  float j_ref_fun = -cosf(delta_t * M_PI * (f0 + k * delta_t) * 2.0) * pow((M_PI * (f0 + k * delta_t) * 2.0 + k * delta_t * M_PI * 2.0), 3) - k * M_PI * sinf(delta_t * M_PI * (f0 + k * delta_t) * 2.0) * (M_PI * (f0 + k * delta_t) * 2.0 + k * delta_t * M_PI * 2.0) * 1.2e+1;
1832  return (A * j_ref_fun);
1833 }
1834 
1846 void chirp_pos(float time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]) {
1847  f0 = positive_non_zero(f0);
1848  f1 = positive_non_zero(f1);
1850  A = positive_non_zero(A);
1851  if ((f1-f0) < -FLT_EPSILON){
1852  f1 = f0;
1853  }
1854  // 0 body x, 1 body y, 2 body z, 3 pitch pref
1855  if (n > 3){
1856  n = 0;
1857  }
1858  if (n < 0){
1859  n = 0;
1860  }
1861  // i think there should not be a problem with f1 being equal to f0
1862  float k = (f1 - f0) / t_chirp;
1863  float p_ref_chirp = chirp_pos_p_ref(time_elapsed, f0, k, A);
1864  float v_ref_chirp = chirp_pos_v_ref(time_elapsed, f0, k, A);
1865  float a_ref_chirp = chirp_pos_a_ref(time_elapsed, f0, k, A);
1866  float j_ref_chirp = chirp_pos_j_ref(time_elapsed, f0, k, A);
1867 
1868  float spsi = sinf(psi);
1869  float cpsi = cosf(psi);
1870  float mult_0 = 0.0;
1871  float mult_1 = 0.0;
1872  float mult_2 = 0.0;
1873  if (n == 0){
1874  mult_0 = cpsi;
1875  mult_1 = spsi;
1876  mult_2 = 0.0;
1877  }else if(n==1){
1878  mult_0 = -spsi;
1879  mult_1 = cpsi;
1880  mult_2 = 0.0;
1881  }else if(n==2){
1882  mult_0 = 0.0;
1883  mult_1 = 0.0;
1884  mult_2 = 1.0;
1885  }
1886  // Do not overwrite the reference if chirp is not on that axis
1887  if (n == 2){
1888  p_ref[2] = p_ref_0[2] + p_ref_chirp * mult_2;
1889  v_ref[2] = v_ref_chirp * mult_2;
1890  a_ref[2] = a_ref_chirp * mult_2;
1891  j_ref[2] = j_ref_chirp * mult_2;
1892  } else if (n < 2){
1893  p_ref[0] = p_ref_0[0] + p_ref_chirp * mult_0;
1894  p_ref[1] = p_ref_0[1] + p_ref_chirp * mult_1;
1895  v_ref[0] = v_ref_chirp * mult_0;
1896  v_ref[1] = v_ref_chirp * mult_1;
1897  a_ref[0] = a_ref_chirp * mult_0;
1898  a_ref[1] = a_ref_chirp * mult_1;
1899  j_ref[0] = j_ref_chirp * mult_0;
1900  j_ref[1] = j_ref_chirp * mult_1;
1901  } else { //Pitch preferred chirp, for now a little bit hacked in...
1902  pitch_pref = p_ref_chirp;
1903  pitch_pref = (pitch_pref / A + 1.0) * (theta_pref_max / 2.0);
1904  float pitch_offset = RadOfDeg(5.0);
1905  pitch_pref = pitch_pref + pitch_offset;
1906  Bound(pitch_pref,0.0,25.0);
1907  }
1908 }
1909 
1910 void chirp_call(bool *chirp_on, bool *chirp_first_call, float* t_0, float* time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]){
1911  if (*chirp_on){
1912  if (*chirp_first_call){
1913  *time_elapsed = 0.0;
1914  *chirp_first_call = false;
1915  *t_0 = get_sys_time_float();
1916  p_ref_0[0] = p_ref[0];
1917  p_ref_0[1] = p_ref[1];
1918  p_ref_0[2] = p_ref[2];
1919  }
1920  if (*time_elapsed < t_chirp){
1921  *time_elapsed = get_sys_time_float() - *t_0;
1922  chirp_pos(*time_elapsed, f0, f1, t_chirp, A, n, psi, p_ref, v_ref, a_ref, j_ref, p_ref_0);
1923  } else {
1924  *chirp_on = false;
1925  *chirp_first_call = true;
1926  *time_elapsed = 0.0;
1927  *t_0 = 0.0;
1929  }
1930  }
1931 }
1932 
1935  return ! motors_on;
1936 }
1937 
1938 
1939 void reshape_wind(void)
1940 {
1941  float psi = eulers_zxy.psi;
1942  float cpsi = cosf(psi);
1943  float spsi = sinf(psi);
1944  float airspeed = airspeed_filt.o[0];
1945  struct FloatVect2 NT_v_NE = {nav_target[0], nav_target[1]}; // Nav target in North and East frame
1946  //struct FloatVect2 NT_v_B = {0.0, 0.0}; // Nav target in body frame (Overwritten later)
1947  struct FloatVect2 airspeed_v = { cpsi * airspeed, spsi * airspeed };
1948  struct FloatVect2 windspeed;
1949  struct FloatVect2 groundspeed = { oneloop_andi.gui_state.vel[0], oneloop_andi.gui_state.vel[1] };
1950  struct FloatVect2 des_as_NE;
1951  struct FloatVect2 des_as_B;
1952  struct FloatVect2 des_acc_B;
1953  VECT2_DIFF(windspeed, groundspeed, airspeed_v); // Wind speed in North and East frame
1954  VECT2_DIFF(des_as_NE, NT_v_NE, windspeed); // Desired airspeed in North and East frame
1955  float norm_des_as = FLOAT_VECT2_NORM(des_as_NE);
1956  //float norm_wind = FLOAT_VECT2_NORM(windspeed);
1957  //float norm_gs = FLOAT_VECT2_NORM(groundspeed);
1958  //float norm_nt = FLOAT_VECT2_NORM(NT_v_NE);
1959  nav_target_new[0] = NT_v_NE.x;
1960  nav_target_new[1] = NT_v_NE.y;
1961  // if the desired airspeed is larger than the max airspeed or we are in force forward reshape gs des to cancel wind and fly at max airspeed
1962  if ((norm_des_as > max_as)||(rotwing_state_settings.force_forward)){
1963  //printf("reshaping wind\n");
1964  float groundspeed_factor = 0.0f;
1965  if (FLOAT_VECT2_NORM(windspeed) < max_as) {
1966  //printf("we can achieve wind cancellation\n");
1967  float av = NT_v_NE.x * NT_v_NE.x + NT_v_NE.y * NT_v_NE.y; // norm squared of nav target
1968  float bv = -2.f * (windspeed.x * NT_v_NE.x + windspeed.y * NT_v_NE.y);
1969  float cv = windspeed.x * windspeed.x + windspeed.y * windspeed.y - max_as * max_as;
1970  float dv = bv * bv - 4.0f * av * cv;
1971  // dv can only be positive, but just in case
1972  if (dv < 0.0f) {
1973  dv = fabsf(dv);
1974  }
1975  float d_sqrt = sqrtf(dv);
1976  groundspeed_factor = (-bv + d_sqrt) / (2.0f * av);
1977  }
1978  des_as_NE.x = groundspeed_factor * NT_v_NE.x - windspeed.x;
1979  des_as_NE.y = groundspeed_factor * NT_v_NE.y - windspeed.y;
1980  NT_v_NE.x = groundspeed_factor * NT_v_NE.x;
1981  NT_v_NE.y = groundspeed_factor * NT_v_NE.y;
1982  }
1983  norm_des_as = FLOAT_VECT2_NORM(des_as_NE); // Recalculate norm of desired airspeed
1984  //NT_v_B.x = cpsi * NT_v_NE.x + spsi * NT_v_NE.y; // Nav target in body x frame
1985  //NT_v_B.y = -spsi * NT_v_NE.x + cpsi * NT_v_NE.y; // Nav target in body y frame
1986  des_as_B.x = norm_des_as; // Desired airspeed in body x frame
1987  des_as_B.y = 0.0; // Desired airspeed in body y frame
1988  // If flying fast or if in force forward mode, make turns instead of straight lines
1990  float delta_psi = atan2f(des_as_NE.y, des_as_NE.x) - psi;
1991  FLOAT_ANGLE_NORMALIZE(delta_psi);
1992  des_acc_B.y = delta_psi * 5.0;//gih_params.heading_bank_gain;
1993  des_acc_B.x = (des_as_B.x - airspeed) * k_pos_rm.k2[0];//gih_params.speed_gain;
1994  //printf("des_acc_B: %f, des_acc_B.x: %f, des_acc_B.y: %f\n", sqrtf(des_acc_B.x*des_acc_B.x+des_acc_B.y*des_acc_B.y),des_acc_B.x, des_acc_B.y);
1995  //printf("max_a_nav: %f\n", max_a_nav);
1996  acc_body_bound(&des_acc_B, max_a_nav); // Scale down side acceleration if norm is too large
1997  //printf("bnd_acc_B: %f, des_acc_B.x: %f, des_acc_B.y: %f\n", sqrtf(des_acc_B.x*des_acc_B.x+des_acc_B.y*des_acc_B.y),des_acc_B.x, des_acc_B.y);
1998  nav_target_new[0] = cpsi * des_acc_B.x - spsi * des_acc_B.y;
1999  nav_target_new[1] = spsi * des_acc_B.x + cpsi * des_acc_B.y;
2000  } else {
2001  nav_target_new[0] = (NT_v_NE.x - groundspeed.x) * k_pos_rm.k2[0];
2002  nav_target_new[1] = (NT_v_NE.y - groundspeed.y) * k_pos_rm.k2[1];
2003  }
2005  //printf("norm_as : %f, as_x : %f, as_y : %f\n", airspeed, airspeed_v.x, airspeed_v.y);
2006  //printf("norm_des_as: %f, des_as_x: %f, des_as_y: %f\n", sqrtf(des_as_NE.x*des_as_NE.x+des_as_NE.y*des_as_NE.y), des_as_NE.x, des_as_NE.y);
2007  //printf("norm_wind : %f, wind_x : %f, wind_y : %f\n", FLOAT_VECT2_NORM(windspeed), windspeed.x, windspeed.y);
2008  //printf("norm_gs : %f, gs_x : %f, gs_y : %f\n", FLOAT_VECT2_NORM(groundspeed), groundspeed.x, groundspeed.y);
2009  //printf("norm_nt : %f, nt_x : %f, nt_y : %f\n", FLOAT_VECT2_NORM(NT_v_NE), NT_v_NE.x, NT_v_NE.y);
2010  //printf("norm_nt_new: %f, nt_new_x: %f, nt_new_y: %f\n", sqrtf(nav_target_new[0]*nav_target_new[0] + nav_target_new[1]*nav_target_new[1]), nav_target_new[0], nav_target_new[1]);
2011 }
2012 
2013 
Main include for ABI (AirBorneInterface).
struct pprz_autopilot autopilot
Global autopilot structure.
Definition: autopilot.c:49
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:295
pprz_t throttle
throttle level as will be displayed in GCS
Definition: autopilot.h:66
uint8_t mode
current autopilot mode
Definition: autopilot.h:63
pprz_t commands[COMMANDS_NB]
Definition: commands.c:30
Hardware independent code for commands handling.
uint8_t last_wp UNUSED
static const float scale[]
float G2_RW[EFF_MAT_COLS_NB]
struct RW_Model RW
float EFF_MAT_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB]
struct wing_model wing
#define ELE_MIN_AS
struct RW_skew skew
#define Min(x, y)
Definition: esc_dshot.c:109
Device independent GPS code (interface)
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
#define FLOAT_ANGLE_NORMALIZE(_a)
static void float_vect_sum(float *o, const float *a, const float *b, const int n)
o = a + b
static void float_vect_zero(float *a, const int n)
a = 0
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 float float_vect_norm(const float *a, const int n)
||a||
#define FLOAT_VECT2_NORM(_v)
euler angles
angular rates
#define VECT2_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:92
#define POS_FLOAT_OF_BFP(_ai)
#define SPEED_FLOAT_OF_BFP(_ai)
#define POS_BFP_OF_REAL(_af)
#define ACCEL_FLOAT_OF_BFP(_ai)
#define SPEED_BFP_OF_REAL(_af)
euler angles
Rotation quaternion.
#define A
static struct NedCoor_f * stateGetAccelNed_f(void)
Get acceleration in NED coordinates (float).
Definition: state.h:1038
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition: state.h:710
static struct FloatRates * stateGetBodyRates_f(void)
Get vehicle body angular rate (float).
Definition: state.h:1200
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition: state.h:908
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]
Integrated Navigation System interface.
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
Second order low pass filter structure.
Hardware independent API for actuators (servos, motor controllers).
#define NAV_HYBRID_MAX_AIRSPEED
float nav_max_speed
float nav_hybrid_max_bank
float nav_hybrid_pos_gain
#define NAV_HYBRID_MAX_DECELERATION
Specific navigation functions for hybrid aircraft.
static float k_e_3_3_f_v2(float omega_n, float zeta, float p1)
Definition: oneloop_andi.c:543
static float w_approx(float p1, float p2, float p3, float rm_k)
Third Order to First Order Dynamics Approximation.
Definition: oneloop_andi.c:923
#define ONELOOP_ANDI_MAX_THETA
Definition: oneloop_andi.c:234
void init_poles(void)
Initialize Position of Poles.
Definition: oneloop_andi.c:937
struct PolePlacement p_pos_e
Definition: oneloop_andi.c:390
static float ang_acc[3]
Definition: oneloop_andi.c:370
static float du_pref_1l[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:363
void chirp_pos(float time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[])
Reference Model Definition for 3rd order system specific to positioning with bounds.
static Butterworth2LowPass accely_filt
Definition: oneloop_andi.c:421
static Butterworth2LowPass model_pred_la_filt[3]
Definition: oneloop_andi.c:417
float act_dynamics[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:173
float ratio_u_un[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:410
void init_filter(void)
Initialize the filters.
struct PolePlacement p_head_rm
Definition: oneloop_andi.c:397
void oneloop_andi_RM(bool half_loop, struct FloatVect3 PSA_des, int rm_order_h, int rm_order_v, bool in_flight_oneloop)
Function to generate the reference signals for the oneloop controller.
void oneloop_andi_enter(bool half_loop_sp, int ctrl_type)
Function that resets important values upon engaging Oneloop ANDI.
static Butterworth2LowPass airspeed_filt
Definition: oneloop_andi.c:422
static float k_e_2_3_f_v2(float omega_n, float zeta, float p1)
Definition: oneloop_andi.c:536
static float k_e_1_2_f_v2(float omega, float zeta)
Error Controller Gain Design.
Definition: oneloop_andi.c:518
float act_max_norm[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:191
struct Gains3rdOrder k_att_rm
Definition: oneloop_andi.c:400
float max_a_nav
Definition: oneloop_andi.c:259
void float_euler_dot_of_rates_vec(float r[3], float e[3], float edot[3])
Attitude Euler to Rates Conversion Function.
Definition: oneloop_andi.c:586
float oneloop_andi_filt_cutoff_v
Definition: oneloop_andi.c:127
static float ang_rate[3]
Definition: oneloop_andi.c:371
struct FloatEulers eulers_zxy_des
Definition: oneloop_andi.c:350
static float du_min_1l[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:361
static float du_max_1l[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:362
float p_ref_0[3]
Definition: oneloop_andi.c:384
struct Int32Eulers stab_att_sp_euler_1l
Definition: oneloop_andi.c:348
struct PolePlacement p_att_rm
Definition: oneloop_andi.c:388
static float ec_3rd(float x_ref, float x_d_ref, float x_2d_ref, float x_3d_ref, float x, float x_d, float x_2d, float k1_e, float k2_e, float k3_e)
Error Controller Definition for 3rd order system.
Definition: oneloop_andi.c:866
static float Wv_wls[ANDI_OUTPUTS]
Definition: oneloop_andi.c:211
static float k_rm_3_3_f(float omega_n, float zeta, float p1)
Definition: oneloop_andi.c:566
int16_t temp_pitch
Definition: oneloop_andi.c:334
float max_as
Definition: oneloop_andi.c:279
struct Gains3rdOrder k_att_e
Definition: oneloop_andi.c:399
float psi_des_rad
Definition: oneloop_andi.c:353
float EFF_MAT_G[ANDI_OUTPUTS][ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:409
static float model_pred[ANDI_OUTPUTS]
Definition: oneloop_andi.c:368
void rm_1st_pos(float dt, float x_2d_ref[], float x_3d_ref[], float x_2d_des[], float k3_rm[], float x_3d_bound, int n)
Reference Model Definition for 3rd order system specific to positioning with bounds.
Definition: oneloop_andi.c:822
void oneloop_andi_propagate_filters(void)
Propagate the filters.
bool ctrl_off
Definition: oneloop_andi.c:358
struct Gains3rdOrder k_pos_e
Definition: oneloop_andi.c:401
float nu[ANDI_OUTPUTS]
Definition: oneloop_andi.c:340
float nu_norm_max
Definition: oneloop_andi.c:203
bool actuator_is_servo[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:166
float oneloop_andi_sideslip(void)
Function to calculate corrections for sideslip.
float num_thrusters_oneloop
Definition: oneloop_andi.c:103
static float act_dynamics_d[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:342
float t_chirp
Definition: oneloop_andi.c:381
float act_min_norm[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:197
#define ONELOOP_ANDI_DEBUG_MODE
Definition: oneloop_andi.c:227
float oneloop_andi_filt_cutoff_q
Definition: oneloop_andi.c:147
float oneloop_andi_filt_cutoff_a
Definition: oneloop_andi.c:121
static float pitch_pref
Definition: oneloop_andi.c:364
static float gamma_wls
Definition: oneloop_andi.c:360
static float g2_ff
Definition: oneloop_andi.c:345
float f0_chirp
Definition: oneloop_andi.c:379
static float chirp_pos_j_ref(float delta_t, float f0, float k, float A)
Function to calculate the jerk reference during the chirp.
#define ONELOOP_ANDI_MAX_PHI
Definition: oneloop_andi.c:232
float max_j_nav
Definition: oneloop_andi.c:265
static Butterworth2LowPass filt_veloc_ned[3]
Definition: oneloop_andi.c:415
void oneloop_from_nav(bool in_flight)
Function that maps navigation inputs to the oneloop controller for the generated autopilot.
struct PolePlacement p_alt_rm
Definition: oneloop_andi.c:394
float max_j_ang
Definition: oneloop_andi.c:271
void ec_3rd_att(float y_4d[3], float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x[3], float x_d[3], float x_2d[3], float k1_e[3], float k2_e[3], float k3_e[3], float max_ang_jerk)
Error Controller Definition for 3rd order system specific to attitude.
Definition: oneloop_andi.c:898
static float positive_non_zero(float input)
Function to make sure that inputs are positive non zero vaues.
Definition: oneloop_andi.c:508
bool chirp_on
Definition: oneloop_andi.c:375
static void send_eff_mat_stab_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
Definition: oneloop_andi.c:428
void rm_3rd(float dt, float *x_ref, float *x_d_ref, float *x_2d_ref, float *x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm)
Reference Model Definition for 3rd order system.
Definition: oneloop_andi.c:720
float andi_u[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:337
static float psi_vec[4]
Definition: oneloop_andi.c:355
void calc_normalization(void)
Calculate Normalization of actuators and discrete actuator dynamics
static float model_pred_ar[3]
Definition: oneloop_andi.c:369
float fwd_sideslip_gain
Definition: oneloop_andi.c:287
struct Gains3rdOrder k_pos_e_indi
Definition: oneloop_andi.c:405
float f1_chirp
Definition: oneloop_andi.c:380
void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des, int rm_order_h, int rm_order_v)
Main function that runs the controller and performs control allocation.
struct PolePlacement p_att_e
Definition: oneloop_andi.c:387
static void send_eff_mat_guid_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
Definition: oneloop_andi.c:439
static void debug_vect(struct transport_tx *trans, struct link_device *dev, char *name, float *data, int datasize)
Definition: oneloop_andi.c:486
struct PolePlacement p_alt_e
Definition: oneloop_andi.c:393
void rm_2nd_pos(float dt, float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_d_des[], float k2_rm[], float k3_rm[], float x_2d_bound, float x_3d_bound, int n)
Reference Model Definition for 3rd order system specific to positioning with bounds.
Definition: oneloop_andi.c:800
float bound_v_from_a(float e_x[], float v_bound, float a_bound, int n)
Calculate velocity limit based on acceleration limit.
Definition: oneloop_andi.c:658
void reshape_wind(void)
static float g
Definition: oneloop_andi.c:332
static float andi_du_n[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:339
void get_act_state_oneloop(void)
Function to reconstruct actuator state using first order dynamics.
float A_chirp
Definition: oneloop_andi.c:382
struct PolePlacement p_head_e
Definition: oneloop_andi.c:396
int8_t chirp_axis
Definition: oneloop_andi.c:383
static float chirp_pos_p_ref(float delta_t, float f0, float k, float A)
Function to calculate the position reference during the chirp.
static int number_iter
Definition: oneloop_andi.c:365
float andi_du[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:338
float max_v_nav_v
Definition: oneloop_andi.c:284
float max_v_nav
Definition: oneloop_andi.c:277
bool heading_manual
Definition: oneloop_andi.c:356
static float chirp_pos_v_ref(float delta_t, float f0, float k, float A)
Function to calculate the velocity reference during the chirp.
float t_0_chirp
Definition: oneloop_andi.c:378
struct Int32Quat stab_att_sp_quat_1l
Definition: oneloop_andi.c:349
float time_elapsed_chirp
Definition: oneloop_andi.c:377
static float nav_target[3]
Definition: oneloop_andi.c:329
void err_nd(float err[], float a[], float b[], float k[], int n)
Calculate Scaled Error between two 3D arrays.
Definition: oneloop_andi.c:601
static Butterworth2LowPass model_pred_ar_filt[3]
Definition: oneloop_andi.c:420
static float k_e_1_3_f_v2(float omega_n, UNUSED float zeta, float p1)
Definition: oneloop_andi.c:530
#define ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD
Definition: oneloop_andi.c:252
void calc_model(void)
Function that calculates the model prediction for the complementary filter.
struct OneloopGeneral oneloop_andi
Definition: oneloop_andi.c:325
struct Gains3rdOrder k_pos_rm
Definition: oneloop_andi.c:402
bool autopilot_in_flight_end_detection(bool motors_on UNUSED)
Quadplanes can still be in-flight with COMMAND_THRUST==0 and can even soar not descending in updrafts...
static float use_increment
Definition: oneloop_andi.c:328
static float Wv[ANDI_OUTPUTS]
Definition: oneloop_andi.c:210
void chirp_call(bool *chirp_on, bool *chirp_first_call, float *t_0_chirp, float *time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[])
void init_controller(void)
Initialize Controller Gains FIXME: Calculate the gains dynamically for transition.
Definition: oneloop_andi.c:984
void G1G2_oneloop(int ctrl_type)
Function that samples and scales the effectiveness matrix FIXME: make this function into a for loop t...
static void send_guidance_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
Definition: oneloop_andi.c:460
float theta_pref_max
Definition: oneloop_andi.c:237
float act_max[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:179
void rm_3rd_head(float dt, float *x_ref, float *x_d_ref, float *x_2d_ref, float *x_3d_ref, float x_des, float k1_rm, float k2_rm, float k3_rm)
Reference Model Definition for 3rd order system specific to the heading angle.
Definition: oneloop_andi.c:742
bool chirp_first_call
Definition: oneloop_andi.c:376
void normalize_nu(void)
Function to normalize the pseudo control vector.
float psi_des_deg
Definition: oneloop_andi.c:354
void rm_3rd_pos(float dt, float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x_des[], float k1_rm[], float k2_rm[], float k3_rm[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n)
Reference Model Definition for 3rd order system specific to positioning with bounds.
Definition: oneloop_andi.c:770
struct FloatEulers eulers_zxy
Definition: oneloop_andi.c:351
void oneloop_andi_init(void)
Init function of Oneloop ANDI controller
static float Wu[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:217
void float_rates_of_euler_dot_vec(float r[3], float e[3], float edot[3])
Attitude Rates to Euler Conversion Function.
Definition: oneloop_andi.c:574
float oneloop_andi_filt_cutoff_p
Definition: oneloop_andi.c:140
static Butterworth2LowPass filt_accel_ned[3]
Definition: oneloop_andi.c:414
static float k_rm_1_3_f(float omega_n, float zeta, float p1)
Reference Model Gain Design.
Definition: oneloop_andi.c:552
static float k_e_2_2_f_v2(float omega, float zeta)
Definition: oneloop_andi.c:524
float oneloop_andi_filt_cutoff_r
Definition: oneloop_andi.c:154
float k_as
Definition: oneloop_andi.c:333
struct PolePlacement p_pos_rm
Definition: oneloop_andi.c:391
float ratio_vn_v[ANDI_OUTPUTS]
Definition: oneloop_andi.c:411
void ec_3rd_pos(float y_4d[], float x_ref[], float x_d_ref[], float x_2d_ref[], float x_3d_ref[], float x[], float x_d[], float x_2d[], float k1_e[], float k2_e[], float k3_e[], float x_d_bound, float x_2d_bound, float x_3d_bound, int n)
Definition: oneloop_andi.c:870
float nu_n[ANDI_OUTPUTS]
Definition: oneloop_andi.c:341
static float chirp_pos_a_ref(float delta_t, float f0, float k, float A)
Function to calculate the acceleration reference during the chirp.
#define ONELOOP_ANDI_MAX_BANK
Definition: oneloop_andi.c:231
bool yaw_stick_in_auto
Definition: oneloop_andi.c:357
void vect_bound_nd(float vect[], float bound, int n)
Scale a 3D array to within a 3D bound.
Definition: oneloop_andi.c:629
void err_sum_nd(float err[], float a[], float b[], float k[], float c[], int n)
Calculate Scaled Error between two 3D arrays.
Definition: oneloop_andi.c:610
void integrate_nd(float dt, float a[], float a_dot[], int n)
Integrate in time 3D array.
Definition: oneloop_andi.c:620
static float dt_1l
Definition: oneloop_andi.c:331
static void send_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
Definition: oneloop_andi.c:446
struct Gains3rdOrder k_att_e_indi
Definition: oneloop_andi.c:404
void rm_3rd_attitude(float dt, float x_ref[3], float x_d_ref[3], float x_2d_ref[3], float x_3d_ref[3], float x_des[3], bool ow_psi, float psi_overwrite[4], float k1_rm[3], float k2_rm[3], float k3_rm[3], float max_ang_jerk)
Reference Model Definition for 3rd order system with attitude conversion functions.
Definition: oneloop_andi.c:679
static void send_oneloop_debug(struct transport_tx *trans, struct link_device *dev)
Definition: oneloop_andi.c:493
float act_min[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:185
float actuator_state_1l[ANDI_NUM_ACT]
Definition: oneloop_andi.c:343
static float a_thrust
Definition: oneloop_andi.c:344
float oneloop_andi_filt_cutoff_pos
Definition: oneloop_andi.c:133
float max_r
Definition: oneloop_andi.c:158
void rm_2nd(float dt, float *x_ref, float *x_d_ref, float *x_2d_ref, float x_des, float k1_rm, float k2_rm)
Reference Model Definition for 2nd order system.
Definition: oneloop_andi.c:843
void acc_body_bound(struct FloatVect2 *vect, float bound)
Scale a 3D array to within a 3D bound.
Definition: oneloop_andi.c:642
float * bwls_1l[ANDI_OUTPUTS]
Definition: oneloop_andi.c:408
static float k_rm_2_3_f(float omega_n, float zeta, float p1)
Definition: oneloop_andi.c:559
static float nav_target_new[3]
Definition: oneloop_andi.c:330
static float lin_acc[3]
Definition: oneloop_andi.c:372
static Butterworth2LowPass rates_filt_bt[3]
Definition: oneloop_andi.c:416
static float u_pref[ANDI_NUM_ACT_TOT]
Definition: oneloop_andi.c:223
static Butterworth2LowPass model_pred_aa_filt[3]
Definition: oneloop_andi.c:419
float oneloop_andi_filt_cutoff
Definition: oneloop_andi.c:115
static Butterworth2LowPass ang_rate_lowpass_filters[3]
Definition: oneloop_andi.c:418
struct OneloopGuidanceState gui_state
Definition: oneloop_andi.h:127
struct OneloopStabilizationState sta_state
Definition: oneloop_andi.h:129
#define CTRL_INDI
Definition: oneloop_andi.h:58
#define ANDI_NUM_ACT
Definition: oneloop_andi.h:35
struct OneloopGuidanceRef gui_ref
Definition: oneloop_andi.h:126
#define CTRL_ANDI
Control types.
Definition: oneloop_andi.h:57
struct OneloopStabilizationRef sta_ref
Definition: oneloop_andi.h:128
#define ANDI_NUM_ACT_TOT
Definition: oneloop_andi.h:48
#define ANDI_OUTPUTS
Definition: oneloop_andi.h:52
#define MAX_PPRZ
Definition: paparazzi.h:8
Paparazzi floating point algebra.
float y
in meters
float x
in meters
float z
in meters
float x
in meters
float y
in meters
vector in North East Down coordinates Units: meters
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
static pprz_t radio_control_get(uint8_t idx)
Get a radio control channel value.
Definition: radio_control.h:94
#define AP_MODE_ATTITUDE_DIRECT
struct RotorcraftNavigation nav
Definition: navigation.c:51
Rotorcraft navigation functions.
struct EnuCoor_f speed
speed setpoint (in m/s)
Definition: navigation.h:128
float climb
climb setpoint (in m/s)
Definition: navigation.h:137
#define NAV_SETPOINT_MODE_SPEED
Definition: navigation.h:101
#define NAV_VERTICAL_MODE_CLIMB
Definition: navigation.h:93
float nav_altitude
current altitude setpoint (in meters): might differ from fp_altitude depending on altitude shift from...
Definition: navigation.h:139
#define NAV_VERTICAL_MODE_ALT
Definition: navigation.h:94
#define NAV_SETPOINT_MODE_POS
Nav setpoint modes these modes correspond to submodes defined by navigation routines to tell which se...
Definition: navigation.h:100
struct EnuCoor_f target
final target position (in meters)
Definition: navigation.h:126
struct RotWingStateSettings rotwing_state_settings
struct Stabilization stabilization
Definition: stabilization.c:41
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:138
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 float P[3][3]
Definition: trilateration.c:31
short int16_t
Typedef defining 16 bit short type.
Definition: vl53l1_types.h:93
signed char int8_t
Typedef defining 8 bit char type.
Definition: vl53l1_types.h:103
float b
Definition: wedgebug.c:202
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