Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
guidance_indi_hybrid.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Ewoud Smeur <ewoud.smeur@gmail.com>
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, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
30 #include "generated/airframe.h"
34 #include "state.h"
35 #include "mcu_periph/sys_time.h"
36 #include "autopilot.h"
37 #include "stdio.h"
39 #include "modules/core/abi.h"
41 
42 
43 // The acceleration reference is calculated with these gains. If you use GPS,
44 // they are probably limited by the update rate of your GPS. The default
45 // values are tuned for 4 Hz GPS updates. If you have high speed position updates, the
46 // gains can be higher, depending on the speed of the inner loop.
47 #ifndef GUIDANCE_INDI_SPEED_GAIN
48 #define GUIDANCE_INDI_SPEED_GAIN 1.8
49 #define GUIDANCE_INDI_SPEED_GAINZ 1.8
50 #endif
51 
52 #ifndef GUIDANCE_INDI_POS_GAIN
53 #define GUIDANCE_INDI_POS_GAIN 0.5
54 #define GUIDANCE_INDI_POS_GAINZ 0.5
55 #endif
56 
57 #ifndef GUIDANCE_INDI_LIFTD_ASQ
58 #define GUIDANCE_INDI_LIFTD_ASQ 0.20
59 #endif
60 
61 #ifndef GUIDANCE_INDI_MAX_PUSHER_INCREMENT
62 #define GUIDANCE_INDI_MAX_PUSHER_INCREMENT MAX_PPRZ
63 #endif
64 
65 /* If lift effectiveness at low airspeed not defined,
66  * just make one interpolation segment that connects to
67  * the quadratic part from 12 m/s onward
68  */
69 #ifndef GUIDANCE_INDI_LIFTD_P50
70 #define GUIDANCE_INDI_LIFTD_P80 (GUIDANCE_INDI_LIFTD_ASQ*12*12)
71 #define GUIDANCE_INDI_LIFTD_P50 (GUIDANCE_INDI_LIFTD_P80/2)
72 #endif
73 
74 #ifndef GUIDANCE_INDI_MAX_AIRSPEED
75 #error "You must have an airspeed sensor to use this guidance"
76 #endif
77 
78 #ifndef GUIDANCE_INDI_MIN_AIRSPEED
79 #define GUIDANCE_INDI_MIN_AIRSPEED -10.f
80 #endif
81 
85 #ifndef GUIDANCE_INDI_FWD_CLIMB_SPEED
86 #define GUIDANCE_INDI_FWD_CLIMB_SPEED 4.0
87 #endif
88 
92 #ifndef GUIDANCE_INDI_FWD_DESCEND_SPEED
93 #define GUIDANCE_INDI_FWD_DESCEND_SPEED -4.0
94 #endif
95 
99 #ifndef GUIDANCE_INDI_QUAD_CLIMB_SPEED
100 #define GUIDANCE_INDI_QUAD_CLIMB_SPEED 2.0
101 #endif
102 
106 #ifndef GUIDANCE_INDI_QUAD_DESCEND_SPEED
107 #define GUIDANCE_INDI_QUAD_DESCEND_SPEED -2.0
108 #endif
109 
112  .pos_gainz = GUIDANCE_INDI_POS_GAINZ,
113 
114  .speed_gain = GUIDANCE_INDI_SPEED_GAIN,
115  .speed_gainz = GUIDANCE_INDI_SPEED_GAINZ,
116 
117  .heading_bank_gain = GUIDANCE_INDI_HEADING_BANK_GAIN,
118  .liftd_asq = GUIDANCE_INDI_LIFTD_ASQ, // coefficient of airspeed squared
119  .liftd_p80 = GUIDANCE_INDI_LIFTD_P80,
120  .liftd_p50 = GUIDANCE_INDI_LIFTD_P50,
121  .min_airspeed = GUIDANCE_INDI_MIN_AIRSPEED,
122  .max_airspeed = GUIDANCE_INDI_MAX_AIRSPEED,
123  .stall_protect_gain = 1.5, // m/s^2 downward acceleration per m/s airspeed loss
124  .climb_vspeed_fwd = GUIDANCE_INDI_FWD_CLIMB_SPEED,
125  .descend_vspeed_fwd = GUIDANCE_INDI_FWD_DESCEND_SPEED,
126  .climb_vspeed_quad = GUIDANCE_INDI_QUAD_CLIMB_SPEED,
127  .descend_vspeed_quad = GUIDANCE_INDI_QUAD_DESCEND_SPEED,
128 };
129 
130 // Quadplanes can hover at various pref pitch
132 
133 
134 // If using WLS, check that the matrix size is sufficient
135 #if GUIDANCE_INDI_HYBRID_USE_WLS
136 #if GUIDANCE_INDI_HYBRID_U > WLS_N_U_MAX
137 #error Matrix-WLS_N_U_MAX too small: increase WLS_N_U_MAX in airframe file
138 #endif
139 
140 #if GUIDANCE_INDI_HYBRID_V > WLS_N_V_MAX
141 #error Matrix-WLS_N_V_MAX too small: increase WLS_N_V_MAX in airframe file
142 #endif
143 #endif
144 
145 
146 // Tell the guidance that the airspeed needs to be zeroed.
147 // Recomended to also put GUIDANCE_INDI_NAV_SPEED_MARGIN low in this case.
148 #ifndef GUIDANCE_INDI_ZERO_AIRSPEED
149 #define GUIDANCE_INDI_ZERO_AIRSPEED FALSE
150 #endif
151 
152 /*Airspeed threshold where making a turn is "worth it"*/
153 #ifndef TURN_AIRSPEED_TH
154 #define TURN_AIRSPEED_TH 13.0
155 #endif
156 
157 /*Boolean to force the heading to a static value (only use for specific experiments)*/
158 bool take_heading_control = false;
159 
160 bool force_forward = false;
161 
163 
164 
165 struct FloatVect3 sp_accel = {0.0,0.0,0.0};
166 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
167 float guidance_indi_specific_force_gain = GUIDANCE_INDI_SPECIFIC_FORCE_GAIN;
168 static void guidance_indi_filter_thrust(void);
169 
170 #ifdef GUIDANCE_INDI_THRUST_DYNAMICS
171 #warning GUIDANCE_INDI_THRUST_DYNAMICS is deprecated, use GUIDANCE_INDI_THRUST_DYNAMICS_FREQ instead.
172 #warning "The thrust dynamics are now specified in continuous time with the corner frequency of the first order model!"
173 #warning "define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ in rad/s"
174 #warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old value."
175 #endif
176 
177 #ifndef GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
178 #ifndef STABILIZATION_INDI_ACT_FREQ_P
179 #error "You need to define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ to be able to use indi vertical control"
180 #else // assume that the same actuators are used for thrust as for roll (e.g. quadrotor)
181 #define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ STABILIZATION_INDI_ACT_FREQ_P
182 #endif
183 #endif //GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
184 
185 #endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
186 
187 #ifndef GUIDANCE_INDI_FILTER_CUTOFF
188 #ifdef STABILIZATION_INDI_FILT_CUTOFF
189 #define GUIDANCE_INDI_FILTER_CUTOFF STABILIZATION_INDI_FILT_CUTOFF
190 #else
191 #define GUIDANCE_INDI_FILTER_CUTOFF 3.0
192 #endif
193 #endif
194 
195 #ifndef GUIDANCE_INDI_AIRSPEED_FILT_CUTOFF
196 #define GUIDANCE_INDI_AIRSPEED_FILT_CUTOFF 0.5
197 #endif
198 
199 #ifndef GUIDANCE_INDI_MAX_LAT_ACCEL
200 #define GUIDANCE_INDI_MAX_LAT_ACCEL 9.81
201 #endif
202 
203 #ifndef GUIDANCE_INDI_COORDINATED_TURN_MIN_AIRSPEED
204 #define GUIDANCE_INDI_COORDINATED_TURN_MIN_AIRSPEED 10.0
205 #endif
206 
207 #ifndef GUIDANCE_INDI_COORDINATED_TURN_MAX_AIRSPEED
208 #define GUIDANCE_INDI_COORDINATED_TURN_MAX_AIRSPEED 30.0
209 #endif
210 
211 #ifndef GUIDANCE_INDI_COORDINATED_TURN_AIRSPEED_MARGIN
212 #define GUIDANCE_INDI_COORDINATED_TURN_AIRSPEED_MARGIN 0.0
213 #endif
214 
215 float inv_eff[4];
216 
217 // Max bank angle in radians
220 
221 #if defined(ROTWING_STATE_FW_MAX_AIRSPEED) && defined(ROTWING_STATE_QUAD_MAX_AIRSPEED)
222  float gih_coordinated_turn_min_airspeed = ROTWING_STATE_QUAD_MAX_AIRSPEED;
224 #else
227 #endif
228 
230 
232 struct FloatEulers eulers_zxy;
233 
234 float thrust_dyn = 0.f;
235 float thrust_act = 0.f;
242 
245 
246 float Ga[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U];
247 struct FloatVect3 euler_cmd;
248 
249 float du_gih[GUIDANCE_INDI_HYBRID_U]; // = {0.0f, 0.0f, 0.0f};
250 
251 #if GUIDANCE_INDI_HYBRID_USE_WLS
252 #include "math/wls/wls_alloc.h"
253 float *Bwls_gih[GUIDANCE_INDI_HYBRID_V];
254 struct WLS_t wls_guid_p = {
255  .nu = GUIDANCE_INDI_HYBRID_U,
256  .nv = GUIDANCE_INDI_HYBRID_V,
257  .gamma_sq = 100000.0,
258  .v = {0.0},
259 #ifdef GUIDANCE_INDI_WLS_PRIORITIES
260  .Wv = GUIDANCE_INDI_WLS_PRIORITIES,
261 #else // X,Y accel, Z accel
262  .Wv = { 100.f, 100.f, 1.f },
263 #endif
264 #ifdef GUIDANCE_INDI_WLS_WU
265  .Wu = GUIDANCE_INDI_WLS_WU,
266 #else
267  .Wu = {[0 ... GUIDANCE_INDI_HYBRID_U - 1] = 1.0},
268 #endif
269  .u_pref = {0.0},
270  .u_min = {0.0},
271  .u_max = {0.0},
272  .PC = 0.0,
273  .SC = 0.0,
274  .iter = 0
275 };
276 #endif
277 // The control objective
278 float v_gih[3];
279 
280 // Filters
283 
287 float thrust_in;
288 
289 struct FloatVect3 gi_speed_sp = {0.0, 0.0, 0.0};
290 
291 #ifndef GUIDANCE_INDI_VEL_SP_ID
292 #define GUIDANCE_INDI_VEL_SP_ID ABI_BROADCAST
293 #endif
295 static void vel_sp_cb(uint8_t sender_id, struct FloatVect3 *vel_sp);
296 struct FloatVect3 indi_vel_sp = {0.0, 0.0, 0.0};
297 float time_of_vel_sp = 0.0;
298 
300 
301 #if PERIODIC_TELEMETRY
303 static void send_eff_mat_guid_indi_hybrid(struct transport_tx *trans, struct link_device *dev)
304 {
305  pprz_msg_send_EFF_MAT_GUID(trans, dev, AC_ID,
306  GUIDANCE_INDI_HYBRID_U, Ga[0],
307  GUIDANCE_INDI_HYBRID_U, Ga[1],
308  GUIDANCE_INDI_HYBRID_U, Ga[2]);
309 }
310 static void send_guidance_indi_hybrid(struct transport_tx *trans, struct link_device *dev)
311 {
312  pprz_msg_send_GUIDANCE_INDI_HYBRID(trans, dev, AC_ID,
313  &sp_accel.x,
314  &sp_accel.y,
315  &sp_accel.z,
316  &euler_cmd.x,
317  &euler_cmd.y,
318  &euler_cmd.z,
319  &filt_accel_ned[0].o[0],
320  &filt_accel_ned[1].o[0],
321  &filt_accel_ned[2].o[0],
322  &gi_speed_sp.x,
323  &gi_speed_sp.y,
324  &gi_speed_sp.z);
325 }
326 
327 #if GUIDANCE_INDI_HYBRID_USE_WLS
328 static void send_wls_v_guid(struct transport_tx *trans, struct link_device *dev)
329 {
330  send_wls_v("guid", &wls_guid_p, trans, dev);
331 }
332 static void send_wls_u_guid(struct transport_tx *trans, struct link_device *dev)
333 {
334  send_wls_u("guid", &wls_guid_p, trans, dev);
335 }
336 #endif // GUIDANCE_INDI_HYBRID_USE_WLS
337 
338 #endif // PERIODIC_TELEMETRY
339 
344 {
345  /*AbiBindMsgACCEL_SP(GUIDANCE_INDI_ACCEL_SP_ID, &accel_sp_ev, accel_sp_cb);*/
346  AbiBindMsgVEL_SP(GUIDANCE_INDI_VEL_SP_ID, &vel_sp_ev, vel_sp_cb);
347 
348 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
349 #ifdef GUIDANCE_INDI_THRUST_DYNAMICS
350  thrust_dyn = GUIDANCE_INDI_THRUST_DYNAMICS;
351 #else
352  thrust_dyn = 1-exp(-GUIDANCE_INDI_THRUST_DYNAMICS_FREQ/PERIODIC_FREQUENCY);
353 #endif
354 #endif
355 
356  float tau = 1.0/(2.0*M_PI*filter_cutoff);
357  float sample_time = 1.0/PERIODIC_FREQUENCY;
358  for(int8_t i=0; i<3; i++) {
359  init_butterworth_2_low_pass(&filt_accel_ned[i], tau, sample_time, 0.0);
360  }
361  init_butterworth_2_low_pass(&roll_filt, tau, sample_time, 0.0);
362  init_butterworth_2_low_pass(&pitch_filt, tau, sample_time, 0.0);
363  init_butterworth_2_low_pass(&thrust_filt, tau, sample_time, 0.0);
364  init_butterworth_2_low_pass(&accely_filt, tau, sample_time, 0.0);
365 
366  float tau_guidance_indi_airspeed = 1.0/(2.0*M_PI*guidance_indi_airspeed_filt_cutoff);
367  init_butterworth_2_low_pass(&guidance_indi_airspeed_filt, tau_guidance_indi_airspeed, sample_time, 0.0);
368 
369 #if GUIDANCE_INDI_HYBRID_USE_WLS
370  for (int8_t i = 0; i < GUIDANCE_INDI_HYBRID_V; i++) {
371  Bwls_gih[i] = Ga[i];
372  }
373 #endif
374 
375 #if PERIODIC_TELEMETRY
376  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_GUIDANCE_INDI_HYBRID, send_guidance_indi_hybrid);
378 #if GUIDANCE_INDI_HYBRID_USE_WLS
379  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_WLS_V, send_wls_v_guid);
380  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_WLS_U, send_wls_u_guid);
381 #endif
382 #endif
383 }
384 
390 {
391  /*Obtain eulers with zxy rotation order*/
394 
395  thrust_in = stabilization.cmd[COMMAND_THRUST];
398 
399  float tau = 1.0 / (2.0 * M_PI * filter_cutoff);
400  float sample_time = 1.0 / PERIODIC_FREQUENCY;
401  for (int8_t i = 0; i < 3; i++) {
402  init_butterworth_2_low_pass(&filt_accel_ned[i], tau, sample_time, 0.0);
403  }
404 
408  init_butterworth_2_low_pass(&accely_filt, tau, sample_time, 0.0);
409 
410  float tau_guidance_indi_airspeed = 1.0/(2.0*M_PI*guidance_indi_airspeed_filt_cutoff);
411  init_butterworth_2_low_pass(&guidance_indi_airspeed_filt, tau_guidance_indi_airspeed, sample_time, 0.0);
412 }
413 
414 void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed) {
415  gih_params.min_airspeed = min_airspeed;
417 }
418 
426 struct StabilizationSetpoint guidance_indi_run(struct FloatVect3 *accel_sp, float heading_sp)
427 {
428  // set global accel sp variable FIXME clean this
429  sp_accel = *accel_sp;
430 
431  /* Obtain eulers with zxy rotation order */
433 
434  /* Calculate the transition ratio so that the ctrl_effecitveness scheduling works */
435  stabilization.transition_ratio = eulers_zxy.theta / RadOfDeg(-75.0f);
436  Bound(stabilization.transition_ratio, 0.f, 1.f);
437 
438  // filter accel to get rid of noise and filter attitude to synchronize with accel
440 
441 #if GUIDANCE_INDI_RC_DEBUG
442 #warning "GUIDANCE_INDI_RC_DEBUG lets you control the accelerations via RC, but disables autonomous flight!"
443  // for rc control horizontal, rotate from body axes to NED
444  float psi = eulers_zxy.psi;
445  float rc_x = -(radio_control.values[RADIO_PITCH]/9600.0)*8.0;
446  float rc_y = (radio_control.values[RADIO_ROLL]/9600.0)*8.0;
447  sp_accel.x = cosf(psi) * rc_x - sinf(psi) * rc_y;
448  sp_accel.y = sinf(psi) * rc_x + cosf(psi) * rc_y;
449 
450  // for rc vertical control
451  sp_accel.z = -(radio_control.values[RADIO_THROTTLE]-4500)*8.0/9600.0;
452 #endif
453 
454  struct FloatVect3 accel_filt;
455  accel_filt.x = filt_accel_ned[0].o[0];
456  accel_filt.y = filt_accel_ned[1].o[0];
457  accel_filt.z = filt_accel_ned[2].o[0];
458 
459  struct FloatVect3 a_diff;
460  VECT3_DIFF(a_diff, sp_accel, accel_filt);
461 
462  // Bound the acceleration error so that the linearization still holds
463  Bound(a_diff.x, -6.0, 6.0);
464  Bound(a_diff.y, -6.0, 6.0);
465  Bound(a_diff.z, -9.0, 9.0);
466 
467  // If the thrust to specific force ratio has been defined, include vertical control
468  // else ignore the vertical acceleration error
469 #ifndef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
470 #ifndef STABILIZATION_ATTITUDE_INDI_FULL
471  a_diff.z = 0.0;
472 #endif
473 #endif
474 
475  // Calculate matrix of partial derivatives and control objective
477 
478 #if GUIDANCE_INDI_HYBRID_USE_WLS
479 
480  // Calculate the maximum deflections
482 
483  float du_gih[GUIDANCE_INDI_HYBRID_U]; // = {0.0f, 0.0f, 0.0f};
484 
485  for (int i = 0; i < GUIDANCE_INDI_HYBRID_V; i++) {
486  wls_guid_p.v[i] = v_gih[i];
487  }
488  wls_alloc(&wls_guid_p, Bwls_gih, 0, 0, 10);
489  for (int i = 0; i < GUIDANCE_INDI_HYBRID_U; i++) {
490  du_gih[i] = wls_guid_p.u[i];
491  }
492  euler_cmd.x = du_gih[0];
493  euler_cmd.y = du_gih[1];
494  euler_cmd.z = du_gih[2];
495 
496 #else
497  // compute inverse matrix of Ga
498  float Ga_inv[3][3] = {};
500  // Calculate roll,pitch and thrust command
501  float_mat3_mult(&euler_cmd, Ga_inv, a_diff);
502 #endif
503 
504  // Coordinated turn
505  // feedforward estimate angular rotation omega = g*tan(phi)/v
506  float omega;
507  const float max_phi = RadOfDeg(60.0f);
508 #if GUIDANCE_INDI_ZERO_AIRSPEED
509  float airspeed_turn = 0.f;
510 #else
511  float airspeed_turn = stateGetAirspeed_f();
512 #endif
513  // We are dividing by the airspeed, so a lower bound is important
515 
518 
519  //Bound euler angles to prevent flipping
522 
523  // Use the current roll angle to determine the corresponding heading rate of change.
524  float coordinated_turn_roll = eulers_zxy.phi;
525 
526  // When tilting backwards (e.g. waypoint behind the drone), we have to yaw around to face the direction
527  // of flight even when the drone is not rolling much (yet). Determine the shortest direction in which to yaw by
528  // looking at the roll angle.
529  if( (eulers_zxy.theta > 0.0f) && ( fabs(eulers_zxy.phi) < eulers_zxy.theta)) {
530  if (eulers_zxy.phi > 0.0f) {
531  coordinated_turn_roll = eulers_zxy.theta;
532  } else {
533  coordinated_turn_roll = -eulers_zxy.theta;
534  }
535  }
536 
537  if (fabsf(coordinated_turn_roll) < max_phi) {
538  omega = 9.81f / airspeed_turn * tanf(coordinated_turn_roll);
539  } else { //max 60 degrees roll
540  omega = 9.81f / airspeed_turn * 1.72305f * ((coordinated_turn_roll > 0.0f) - (coordinated_turn_roll < 0.0f));
541  }
542 
543 #ifdef FWD_SIDESLIP_GAIN
544  // Add sideslip correction
545  omega -= accely_filt.o[0]*FWD_SIDESLIP_GAIN;
546 #endif
547 
548  // We can pre-compute the required rates to achieve this turn rate:
549  // NOTE: there *should* not be any problems possible with Euler singularities here
550  struct FloatEulers *euler_zyx = stateGetNedToBodyEulers_f();
551 
552  struct FloatRates ff_rates;
553 
554  ff_rates.p = -sinf(euler_zyx->theta) * omega;
555  ff_rates.q = cosf(euler_zyx->theta) * sinf(euler_zyx->phi) * omega;
556  ff_rates.r = cosf(euler_zyx->theta) * cosf(euler_zyx->phi) * omega;
557 
558  // For a hybrid it is important to reduce the sideslip, which is done by changing the heading.
559  // For experiments, it is possible to fix the heading to a different value.
560  if (take_heading_control) {
561  // heading is fixed by nav
562  guidance_euler_cmd.psi = heading_sp;
563  }
564  else {
565  // heading is free and controlled by guidance
566  guidance_indi_hybrid_heading_sp += omega / PERIODIC_FREQUENCY;
568  // limit heading setpoint to be within bounds of current heading
569 #ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
570  float delta_limit = STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT;
572  float delta_psi = guidance_indi_hybrid_heading_sp - heading;
573  FLOAT_ANGLE_NORMALIZE(delta_psi);
574  if (delta_psi > delta_limit) {
576  } else if (delta_psi < -delta_limit) {
578  }
580 #endif
582  }
583 
584  // compute required thrust setpoint
585 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
586  guidance_indi_filter_thrust();
587  // Add the increment in specific force * specific_force_to_thrust_gain to the filtered thrust
589  Bound(thrust_in, GUIDANCE_INDI_MIN_THROTTLE, 9600);
590 #if GUIDANCE_INDI_RC_DEBUG
591  if (radio_control.values[RADIO_THROTTLE] < 300) {
592  thrust_in = 0;
593  }
594 #endif
595  // return required thrust
597 
598 #else
599  float thrust_vect[3];
600 #if GUIDANCE_INDI_HYBRID_U > 3
601  thrust_vect[0] = du_gih[3];
602  if (thrust_vect[0] > GUIDANCE_INDI_MAX_PUSHER_INCREMENT*g1g2[4][GUIDANCE_INDI_PUSHER_INDEX]) {
603  thrust_vect[0] = GUIDANCE_INDI_MAX_PUSHER_INCREMENT*g1g2[4][GUIDANCE_INDI_PUSHER_INDEX];
604  }
605 #else
606  thrust_vect[0] = 0;
607 #endif
608  thrust_vect[1] = 0;
609  thrust_vect[2] = euler_cmd.z;
610  // specific force not defined, return required increment
611  thrust_sp = th_sp_from_incr_vect_f(thrust_vect);
612 #endif
613 
614  // Set the quaternion setpoint from eulers_zxy
615  struct FloatQuat sp_quat;
617  float_quat_normalize(&sp_quat);
618 
619  return stab_sp_from_quat_ff_rates_f(&sp_quat, &ff_rates);
620 }
621 
622 // compute accel setpoint from speed setpoint (use global variables ! FIXME)
623 static struct FloatVect3 compute_accel_from_speed_sp(void)
624 {
625  struct FloatVect3 accel_sp = { 0.f, 0.f, 0.f };
626 
628 
629  //for rc control horizontal, rotate from body axes to NED
630  float psi = eulers_zxy.psi;
631  float cpsi = cosf(psi);
632  float spsi = sinf(psi);
633  float speed_sp_b_x = cpsi * gi_speed_sp.x + spsi * gi_speed_sp.y;
634  float speed_sp_b_y = -spsi * gi_speed_sp.x + cpsi * gi_speed_sp.y;
635 
636  // Get airspeed or zero it
637 #if GUIDANCE_INDI_ZERO_AIRSPEED
638  float airspeed = 0.f;
639 #else
640  float airspeed = stateGetAirspeed_f();
641  Bound(airspeed, 0.0f, 100.0f);
643  airspeed = guidance_indi_airspeed_filt.o[0];
644  }
645 #endif
646  struct NedCoor_f *groundspeed = stateGetSpeedNed_f();
647  struct FloatVect2 airspeed_v = { cpsi * airspeed, spsi * airspeed };
648  struct FloatVect2 windspeed;
649  VECT2_DIFF(windspeed, *groundspeed, airspeed_v);
650 
651  VECT2_DIFF(desired_airspeed, gi_speed_sp, windspeed); // Use 2d part of gi_speed_sp
652  float norm_des_as = FLOAT_VECT2_NORM(desired_airspeed);
653 
654  gi_unbounded_airspeed_sp = norm_des_as;
655 
656  // Check if some minimum airspeed is desired (e.g. to prevent stall)
657  if (norm_des_as < gih_params.min_airspeed) {
658  norm_des_as = gih_params.min_airspeed;
659  }
660 
661  float gi_airspeed_sp = norm_des_as;
662 
663  // Make turn instead of straight line, control airspeed
664  if ((airspeed > TURN_AIRSPEED_TH) && (norm_des_as > (TURN_AIRSPEED_TH+2.0f))) {
665 
666  // Give the wind cancellation priority.
667  if (norm_des_as > gih_params.max_airspeed) {
668  float groundspeed_factor = 0.0f;
669 
670  // if the wind is faster than we can fly, just fly in the wind direction
671  if (FLOAT_VECT2_NORM(windspeed) < gih_params.max_airspeed) {
672  float av = gi_speed_sp.x * gi_speed_sp.x + gi_speed_sp.y * gi_speed_sp.y;
673  float bv = -2.f * (windspeed.x * gi_speed_sp.x + windspeed.y * gi_speed_sp.y);
674  float cv = windspeed.x * windspeed.x + windspeed.y * windspeed.y - gih_params.max_airspeed * gih_params.max_airspeed;
675 
676  float dv = bv * bv - 4.0f * av * cv;
677 
678  // dv can only be positive, but just in case
679  if (dv < 0.0f) {
680  dv = fabsf(dv);
681  }
682  float d_sqrt = sqrtf(dv);
683 
684  groundspeed_factor = (-bv + d_sqrt) / (2.0f * av);
685  }
686 
687  desired_airspeed.x = groundspeed_factor * gi_speed_sp.x - windspeed.x;
688  desired_airspeed.y = groundspeed_factor * gi_speed_sp.y - windspeed.y;
689 
690  gi_airspeed_sp = gih_params.max_airspeed;
691  }
692 
693  if (force_forward) {
694  gi_airspeed_sp = gih_params.max_airspeed;
695  }
696 
697  // Calculate accel sp in body axes, because we need to regulate airspeed
698  struct FloatVect2 sp_accel_b;
699  // In turn acceleration proportional to heading diff
700  sp_accel_b.y = atan2f(desired_airspeed.y, desired_airspeed.x) - psi;
701  FLOAT_ANGLE_NORMALIZE(sp_accel_b.y);
702  sp_accel_b.y *= gih_params.heading_bank_gain;
703 
704  BoundAbs(sp_accel_b.y, GUIDANCE_INDI_MAX_LAT_ACCEL);
705 
706  // Control the airspeed
707  sp_accel_b.x = (gi_airspeed_sp - airspeed) * gih_params.speed_gain;
708 
709  accel_sp.x = cpsi * sp_accel_b.x - spsi * sp_accel_b.y;
710  accel_sp.y = spsi * sp_accel_b.x + cpsi * sp_accel_b.y;
712  }
713  else { // Go somewhere in the shortest way
714 
715  if (airspeed > 10.f) {
716  // Groundspeed vector in body frame
717  float groundspeed_x = cpsi * stateGetSpeedNed_f()->x + spsi * stateGetSpeedNed_f()->y;
718  float speed_increment = speed_sp_b_x - groundspeed_x;
719 
720  // limit groundspeed setpoint to max_airspeed + (diff gs and airspeed)
721  if ((speed_increment + airspeed) > gih_params.max_airspeed) {
722  speed_sp_b_x = gih_params.max_airspeed + groundspeed_x - airspeed;
723  }
724  }
725 
726  gi_speed_sp.x = cpsi * speed_sp_b_x - spsi * speed_sp_b_y;
727  gi_speed_sp.y = spsi * speed_sp_b_x + cpsi * speed_sp_b_y;
728 
732  }
733 
734  // Bound the acceleration setpoint
735  float accelbound = 3.0f + airspeed / gih_params.max_airspeed * 5.0f; // FIXME remove hard coded values
736  float_vect3_bound_in_2d(&accel_sp, accelbound);
737  BoundAbs(accel_sp.z, 3.0);
738 
739 #ifdef ROTWING_FW_MIN_AIRSPEED
741  accel_sp.z = gih_params.stall_protect_gain * (gi_airspeed_sp - airspeed);
742  BoundAbs(accel_sp.z, 5.0);
743  }
744 #endif
745 
746  return accel_sp;
747 }
748 
749 static float bound_vz_sp(float vz_sp)
750 {
751  // Bound vertical speed setpoint
754  } else {
756  }
757  return vz_sp;
758 }
759 
761 {
762  struct FloatVect3 pos_err = { 0 };
763  struct FloatVect3 accel_sp = { 0 };
764 
765  // First check for velocity setpoint from module // FIXME should be called like this
766  float dt = get_sys_time_float() - time_of_vel_sp;
767  // If the input command is not updated after a timeout, switch back to flight plan control
768  if (dt < 0.5) {
772  accel_sp = compute_accel_from_speed_sp(); // compute accel sp
773  return guidance_indi_run(&accel_sp, gh->sp.heading);
774  }
775 
776  if (h_mode == GUIDANCE_INDI_HYBRID_H_POS) {
777  //Linear controller to find the acceleration setpoint from position and velocity
778  pos_err.x = POS_FLOAT_OF_BFP(gh->ref.pos.x) - stateGetPositionNed_f()->x;
779  pos_err.y = POS_FLOAT_OF_BFP(gh->ref.pos.y) - stateGetPositionNed_f()->y;
780  gi_speed_sp.x = pos_err.x * gih_params.pos_gain + SPEED_FLOAT_OF_BFP(gh->ref.speed.x);
781  gi_speed_sp.y = pos_err.y * gih_params.pos_gain + SPEED_FLOAT_OF_BFP(gh->ref.speed.y);
782  if (v_mode == GUIDANCE_INDI_HYBRID_V_POS) {
783  pos_err.z = POS_FLOAT_OF_BFP(gv->z_ref) - stateGetPositionNed_f()->z;
785  } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
787  } else {
788  gi_speed_sp.z = 0.f;
789  }
790  accel_sp = compute_accel_from_speed_sp(); // compute accel sp
791  if (v_mode == GUIDANCE_INDI_HYBRID_V_ACCEL) {
792  accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
793  }
794  return guidance_indi_run(&accel_sp, gh->sp.heading);
795  }
796  else if (h_mode == GUIDANCE_INDI_HYBRID_H_SPEED) {
797  gi_speed_sp.x = SPEED_FLOAT_OF_BFP(gh->ref.speed.x);
798  gi_speed_sp.y = SPEED_FLOAT_OF_BFP(gh->ref.speed.y);
799  if (v_mode == GUIDANCE_INDI_HYBRID_V_POS) {
800  pos_err.z = POS_FLOAT_OF_BFP(gv->z_ref) - stateGetPositionNed_f()->z;
802  } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
804  } else {
805  gi_speed_sp.z = 0.f;
806  }
807  accel_sp = compute_accel_from_speed_sp(); // compute accel sp
808  if (v_mode == GUIDANCE_INDI_HYBRID_V_ACCEL) {
809  accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
810  }
811  return guidance_indi_run(&accel_sp, gh->sp.heading);
812  }
813  else { // H_ACCEL
814  gi_speed_sp.x = 0.f;
815  gi_speed_sp.y = 0.f;
816  if (v_mode == GUIDANCE_INDI_HYBRID_V_POS) {
817  pos_err.z = POS_FLOAT_OF_BFP(gv->z_ref) - stateGetPositionNed_f()->z;
819  } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
821  } else {
822  gi_speed_sp.z = 0.f;
823  }
824  accel_sp = compute_accel_from_speed_sp(); // compute accel sp in case z control is required
825  // overwrite accel X and Y
826  accel_sp.x = (gi_speed_sp.x - stateGetSpeedNed_f()->x) * gih_params.speed_gain + ACCEL_FLOAT_OF_BFP(gh->ref.accel.x);
827  accel_sp.y = (gi_speed_sp.y - stateGetSpeedNed_f()->y) * gih_params.speed_gain + ACCEL_FLOAT_OF_BFP(gh->ref.accel.y);
828  if (v_mode == GUIDANCE_INDI_HYBRID_V_ACCEL) {
829  accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
830  }
831  return guidance_indi_run(&accel_sp, gh->sp.heading);
832  }
833 }
834 
835 #ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
839 void guidance_indi_filter_thrust(void)
840 {
841  // Actuator dynamics
843 
844  // same filter as for the acceleration
846 }
847 
848 #endif
849 
857 {
858  struct NedCoor_f *accel = stateGetAccelNed_f();
862 
865 
866  // Propagate filter for sideslip correction
867  float accely = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->y);
869 
870  float airspeed = stateGetAirspeed_f();
871  Bound(airspeed, 0.0f, 100.0f);
873 }
874 
875 
883 float WEAK guidance_indi_get_liftd(float airspeed, float theta) {
884  float liftd = 0.0f;
885 
886  if (airspeed < 12.f) {
887  /* Assume the airspeed is too low to be measured accurately
888  * Use scheduling based on pitch angle instead.
889  * You can define two interpolation segments
890  */
891  float pitch_interp = DegOfRad(theta);
892  const float min_pitch = -80.0f;
893  const float middle_pitch = -50.0f;
894  const float max_pitch = -20.0f;
895 
896  Bound(pitch_interp, min_pitch, max_pitch);
897  if (pitch_interp > middle_pitch) {
898  float ratio = (pitch_interp - max_pitch)/(middle_pitch - max_pitch);
899  liftd = -gih_params.liftd_p50*ratio;
900  } else {
901  float ratio = (pitch_interp - middle_pitch)/(min_pitch - middle_pitch);
903  }
904  } else {
905  liftd = -gih_params.liftd_asq*airspeed*airspeed;
906  }
907 
908  //TODO: bound liftd
909  return liftd;
910 }
911 
915 static void vel_sp_cb(uint8_t sender_id __attribute__((unused)), struct FloatVect3 *vel_sp)
916 {
917  indi_vel_sp.x = vel_sp->x;
918  indi_vel_sp.y = vel_sp->y;
919  indi_vel_sp.z = vel_sp->z;
921 }
922 
923 
924 #if GUIDANCE_INDI_HYBRID_USE_AS_DEFAULT
925 // guidance indi control function is implementing the default functions of guidance
926 
927 void guidance_h_run_enter(void)
928 {
930 }
931 
932 void guidance_v_run_enter(void)
933 {
934  // nothing to do
935 }
936 
937 static struct VerticalGuidance *_gv = &guidance_v;
939 
940 struct StabilizationSetpoint guidance_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
941 {
943 }
944 
945 struct StabilizationSetpoint guidance_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
946 {
948 }
949 
950 struct StabilizationSetpoint guidance_h_run_accel(bool in_flight, struct HorizontalGuidance *gh)
951 {
953 }
954 
955 struct ThrustSetpoint guidance_v_run_pos(bool in_flight UNUSED, struct VerticalGuidance *gv)
956 {
957  _gv = gv;
959  return thrust_sp;
960 }
961 
962 struct ThrustSetpoint guidance_v_run_speed(bool in_flight UNUSED, struct VerticalGuidance *gv)
963 {
964  _gv = gv;
966  return thrust_sp;
967 }
968 
969 struct ThrustSetpoint guidance_v_run_accel(bool in_flight UNUSED, struct VerticalGuidance *gv)
970 {
971  _gv = gv;
973  return thrust_sp;
974 }
975 
976 #endif
977 
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
Core autopilot interface common to all firmwares.
uint8_t last_wp UNUSED
float phi
in radians
float p
in rad/s
float theta
in radians
float psi
in radians
static void float_quat_normalize(struct FloatQuat *q)
#define FLOAT_ANGLE_NORMALIZE(_a)
void float_mat3_mult(struct FloatVect3 *vect_out, float mat[3][3], struct FloatVect3 vect_in)
Multiply 3D matrix with vector.
void float_vect3_bound_in_2d(struct FloatVect3 *vect3, float bound)
void float_quat_of_eulers_zxy(struct FloatQuat *q, struct FloatEulers *e)
quat from euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
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
bool float_mat_inv_3d(float inv_out[3][3], float mat_in[3][3])
3x3 matrix inverse
#define FLOAT_VECT2_NORM(_v)
euler angles
Roation quaternion.
angular rates
#define VECT2_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:92
#define VECT3_DIFF(_c, _a, _b)
Definition: pprz_algebra.h:182
#define POS_FLOAT_OF_BFP(_ai)
#define SPEED_FLOAT_OF_BFP(_ai)
#define ACCEL_FLOAT_OF_BFP(_ai)
static struct NedCoor_f * stateGetAccelNed_f(void)
Get acceleration in NED coordinates (float).
Definition: state.h:1038
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition: state.h:1143
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition: state.h:1131
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition: state.h:710
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
int32_t max_airspeed
struct FloatMat33 Ga_inv
float guidance_indi_specific_force_gain
struct FloatVect3 indi_vel_sp
bool force_forward
forward flight for hybrid nav
#define GUIDANCE_INDI_COORDINATED_TURN_AIRSPEED_MARGIN
Butterworth2LowPass accely_filt
static void vel_sp_cb(uint8_t sender_id, struct FloatVect3 *vel_sp)
ABI callback that obtains the velocity setpoint from a module.
float time_of_vel_sp
Butterworth2LowPass roll_filt
#define GUIDANCE_INDI_QUAD_DESCEND_SPEED
Descend speed when navigation is doing direct lines.
#define GUIDANCE_INDI_SPEED_GAINZ
#define GUIDANCE_INDI_COORDINATED_TURN_MIN_AIRSPEED
struct guidance_indi_hybrid_params gih_params
float thrust_in
#define GUIDANCE_INDI_MAX_LAT_ACCEL
struct FloatVect3 gi_speed_sp
float guidance_indi_min_pitch
float guidance_indi_max_bank
#define GUIDANCE_INDI_MIN_AIRSPEED
float gih_coordinated_turn_min_airspeed
struct StabilizationSetpoint guidance_indi_run_mode(bool in_flight UNUSED, struct HorizontalGuidance *gh, struct VerticalGuidance *gv, enum GuidanceIndiHybrid_HMode h_mode, enum GuidanceIndiHybrid_VMode v_mode)
float inv_eff[4]
#define GUIDANCE_INDI_FWD_DESCEND_SPEED
Descend speed when navigation is making turns instead of direct lines.
float gih_coordinated_turn_max_airspeed
struct FloatVect3 sp_accel
struct FloatEulers guidance_euler_cmd
float guidance_indi_pitch_pref_deg
#define GUIDANCE_INDI_LIFTD_ASQ
#define GUIDANCE_INDI_QUAD_CLIMB_SPEED
Climb speed when navigation is doing direct lines.
float guidance_indi_airspeed_filt_cutoff
float thrust_act
void guidance_indi_enter(void)
Call upon entering indi guidance.
Butterworth2LowPass guidance_indi_airspeed_filt
Butterworth2LowPass pitch_filt
#define GUIDANCE_INDI_POS_GAIN
#define GUIDANCE_INDI_COORDINATED_TURN_MAX_AIRSPEED
#define GUIDANCE_INDI_FWD_CLIMB_SPEED
Climb speed when navigation is making turns instead of direct lines.
bool take_heading_control
void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed)
float guidance_indi_hybrid_heading_sp
float WEAK guidance_indi_get_liftd(float airspeed, float theta)
Get the derivative of lift w.r.t.
struct ThrustSetpoint thrust_sp
#define GUIDANCE_INDI_LIFTD_P50
static void send_guidance_indi_hybrid(struct transport_tx *trans, struct link_device *dev)
void guidance_indi_init(void)
Init function.
float filter_cutoff
#define GUIDANCE_INDI_FILTER_CUTOFF
#define GUIDANCE_INDI_MAX_PUSHER_INCREMENT
float Ga[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U]
struct FloatVect3 euler_cmd
static float bound_vz_sp(float vz_sp)
struct FloatEulers eulers_zxy
state eulers in zxy order
Butterworth2LowPass filt_accel_ned[3]
float gi_unbounded_airspeed_sp
#define GUIDANCE_INDI_AIRSPEED_FILT_CUTOFF
#define GUIDANCE_INDI_POS_GAINZ
#define TURN_AIRSPEED_TH
float thrust_dyn
static void send_eff_mat_guid_indi_hybrid(struct transport_tx *trans, struct link_device *dev)
static struct FloatVect3 compute_accel_from_speed_sp(void)
#define GUIDANCE_INDI_VEL_SP_ID
struct StabilizationSetpoint guidance_indi_run(struct FloatVect3 *accel_sp, float heading_sp)
bool coordinated_turn_use_accel
float v_gih[3]
void guidance_indi_propagate_filters(void)
Low pass the accelerometer measurements to remove noise from vibrations.
bool guidance_indi_airspeed_filtering
#define GUIDANCE_INDI_LIFTD_P80
abi_event vel_sp_ev
Butterworth2LowPass thrust_filt
#define GUIDANCE_INDI_SPEED_GAIN
float du_gih[GUIDANCE_INDI_HYBRID_U]
struct FloatVect2 desired_airspeed
A guidance mode based on Incremental Nonlinear Dynamic Inversion Come to ICRA2016 to learn more!
void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float v_body[GUIDANCE_INDI_HYBRID_V])
Perform WLS.
GuidanceIndiHybrid_VMode
@ GUIDANCE_INDI_HYBRID_V_POS
@ GUIDANCE_INDI_HYBRID_V_SPEED
@ GUIDANCE_INDI_HYBRID_V_ACCEL
GuidanceIndiHybrid_HMode
@ GUIDANCE_INDI_HYBRID_H_SPEED
@ GUIDANCE_INDI_HYBRID_H_ACCEL
@ GUIDANCE_INDI_HYBRID_H_POS
void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
#define GUIDANCE_INDI_MAX_PITCH
#define GUIDANCE_INDI_MIN_PITCH
static enum GuidanceOneloop_VMode _v_mode
void guidance_v_run_enter(void)
static struct VerticalGuidance * _gv
struct ThrustSetpoint guidance_v_run_pos(bool in_flight UNUSED, struct VerticalGuidance *gv)
struct ThrustSetpoint guidance_v_run_speed(bool in_flight UNUSED, struct VerticalGuidance *gv)
struct ThrustSetpoint guidance_v_run_accel(bool in_flight UNUSED, struct VerticalGuidance *gv)
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.
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
Some helper functions to check RC sticks.
void guidance_h_run_enter(void)
struct StabilizationSetpoint guidance_h_run_pos(bool in_flight, struct HorizontalGuidance *gh)
struct StabilizationSetpoint guidance_h_run_speed(bool in_flight, struct HorizontalGuidance *gh)
struct StabilizationSetpoint guidance_h_run_accel(bool in_flight, struct HorizontalGuidance *gh)
#define GUIDANCE_H_MAX_BANK
Max bank controlled by guidance.
Definition: guidance_h.h:64
struct VerticalGuidance guidance_v
Definition: guidance_v.c:60
int32_t z_ref
altitude reference in meters.
Definition: guidance_v.h:62
int32_t zd_ref
vertical speed reference in meter/s.
Definition: guidance_v.h:68
int32_t zdd_ref
vertical acceleration reference in meter/s^2.
Definition: guidance_v.h:74
struct RotorcraftNavigation nav
Definition: navigation.c:51
Rotorcraft navigation functions.
float heading
heading setpoint (in radians)
Definition: navigation.h:133
bool rotwing_state_pusher_motor_running(void)
bool rotwing_state_hover_motors_running(void)
struct Stabilization stabilization
Definition: stabilization.c:41
struct ThrustSetpoint th_sp_from_incr_vect_f(float th_increment[3])
struct StabilizationSetpoint stab_sp_from_quat_ff_rates_f(struct FloatQuat *quat, struct FloatRates *rates)
struct ThrustSetpoint th_sp_from_thrust_i(int32_t thrust, uint8_t axis)
#define THRUST_AXIS_Z
float transition_ratio
transition percentage for hybrids (0.: hover; 1.: forward)
int32_t cmd[COMMANDS_NB]
output command vector, range from [-MAX_PPRZ:MAX_PPRZ] (store for messages)
float stabilization_attitude_get_heading_f(void)
Get attitude heading as float (avoiding jumps)
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
Stabilization setpoint.
Definition: stabilization.h:53
union StabilizationSetpoint::@278 sp
Thrust setpoint // TODO to a setpoint header Structure to store the desired thrust vector with differ...
Definition: stabilization.h:82
Architecture independent timing functions.
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
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
void send_wls_v(char *name, struct WLS_t *WLS_p, struct transport_tx *trans, struct link_device *dev)
Definition: wls_alloc.c:61
void wls_alloc(struct WLS_t *WLS_p, float **B, float *u_guess, float *W_init, int imax)
active set algorithm for control allocation
Definition: wls_alloc.c:119
void send_wls_u(char *name, struct WLS_t *WLS_p, struct transport_tx *trans, struct link_device *dev)
Definition: wls_alloc.c:71
float u[WLS_N_U_MAX]
Definition: wls_alloc.h:71
float v[WLS_N_V_MAX]
Definition: wls_alloc.h:70
int nu
Definition: wls_alloc.h:67