Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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"
40#include "modules/core/abi.h"
42
43
44// The acceleration reference is calculated with these gains. If you use GPS,
45// they are probably limited by the update rate of your GPS. The default
46// values are tuned for 4 Hz GPS updates. If you have high speed position updates, the
47// gains can be higher, depending on the speed of the inner loop.
48#ifndef GUIDANCE_INDI_SPEED_GAIN
49#define GUIDANCE_INDI_SPEED_GAIN 1.8
50#define GUIDANCE_INDI_SPEED_GAINZ 1.8
51#endif
52
53#ifndef GUIDANCE_INDI_POS_GAIN
54#define GUIDANCE_INDI_POS_GAIN 0.5
55#define GUIDANCE_INDI_POS_GAINZ 0.5
56#endif
57
58#ifndef GUIDANCE_INDI_LIFTD_ASQ
59#define GUIDANCE_INDI_LIFTD_ASQ 0.20
60#endif
61
62#ifndef GUIDANCE_INDI_MAX_PUSHER_INCREMENT
63#define GUIDANCE_INDI_MAX_PUSHER_INCREMENT MAX_PPRZ
64#endif
65
66/* If lift effectiveness at low airspeed not defined,
67 * just make one interpolation segment that connects to
68 * the quadratic part from 12 m/s onward
69 */
70#ifndef GUIDANCE_INDI_LIFTD_P50
71#define GUIDANCE_INDI_LIFTD_P80 (GUIDANCE_INDI_LIFTD_ASQ*12*12)
72#define GUIDANCE_INDI_LIFTD_P50 (GUIDANCE_INDI_LIFTD_P80/2)
73#endif
74
75#ifndef GUIDANCE_INDI_MAX_AIRSPEED
76#error "You must have an airspeed sensor to use this guidance"
77#endif
78
79#ifndef GUIDANCE_INDI_MIN_AIRSPEED
80#define GUIDANCE_INDI_MIN_AIRSPEED -10.f
81#endif
82
86#ifndef GUIDANCE_INDI_FWD_CLIMB_SPEED
87#define GUIDANCE_INDI_FWD_CLIMB_SPEED 4.0
88#endif
89
93#ifndef GUIDANCE_INDI_FWD_DESCEND_SPEED
94#define GUIDANCE_INDI_FWD_DESCEND_SPEED -4.0
95#endif
96
100#ifndef GUIDANCE_INDI_QUAD_CLIMB_SPEED
101#define GUIDANCE_INDI_QUAD_CLIMB_SPEED 2.0
102#endif
103
107#ifndef GUIDANCE_INDI_QUAD_DESCEND_SPEED
108#define GUIDANCE_INDI_QUAD_DESCEND_SPEED -2.0
109#endif
110
113 .pos_gainz = GUIDANCE_INDI_POS_GAINZ,
114
115 .speed_gain = GUIDANCE_INDI_SPEED_GAIN,
116 .speed_gainz = GUIDANCE_INDI_SPEED_GAINZ,
117
118 .heading_bank_gain = GUIDANCE_INDI_HEADING_BANK_GAIN,
119 .liftd_asq = GUIDANCE_INDI_LIFTD_ASQ, // coefficient of airspeed squared
120 .liftd_p80 = GUIDANCE_INDI_LIFTD_P80,
121 .liftd_p50 = GUIDANCE_INDI_LIFTD_P50,
122 .min_airspeed = GUIDANCE_INDI_MIN_AIRSPEED,
123 .max_airspeed = GUIDANCE_INDI_MAX_AIRSPEED,
124 .stall_protect_gain = 1.5, // m/s^2 downward acceleration per m/s airspeed loss
125 .climb_vspeed_fwd = GUIDANCE_INDI_FWD_CLIMB_SPEED,
126 .descend_vspeed_fwd = GUIDANCE_INDI_FWD_DESCEND_SPEED,
127 .climb_vspeed_quad = GUIDANCE_INDI_QUAD_CLIMB_SPEED,
128 .descend_vspeed_quad = GUIDANCE_INDI_QUAD_DESCEND_SPEED,
129};
130
131// Quadplanes can hover at various pref pitch
133
134
135// If using WLS, check that the matrix size is sufficient
136#if GUIDANCE_INDI_HYBRID_USE_WLS
137#if GUIDANCE_INDI_HYBRID_U > WLS_N_U_MAX
138#error Matrix-WLS_N_U_MAX too small: increase WLS_N_U_MAX in airframe file
139#endif
140
141#if GUIDANCE_INDI_HYBRID_V > WLS_N_V_MAX
142#error Matrix-WLS_N_V_MAX too small: increase WLS_N_V_MAX in airframe file
143#endif
144#endif
145
146
147// Tell the guidance that the airspeed needs to be zeroed.
148// Recomended to also put GUIDANCE_INDI_NAV_SPEED_MARGIN low in this case.
149#ifndef GUIDANCE_INDI_ZERO_AIRSPEED
150#define GUIDANCE_INDI_ZERO_AIRSPEED FALSE
151#endif
152
153/*Airspeed threshold where making a turn is "worth it"*/
154#ifndef TURN_AIRSPEED_TH
155#define TURN_AIRSPEED_TH 13.0
156#endif
157
158/*Boolean to force the heading to a static value (only use for specific experiments)*/
160
161bool force_forward = false;
162
164
165
166struct FloatVect3 sp_accel = {0.0,0.0,0.0};
167#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
169static void guidance_indi_filter_thrust(void);
170
171#ifdef GUIDANCE_INDI_THRUST_DYNAMICS
172#warning GUIDANCE_INDI_THRUST_DYNAMICS is deprecated, use GUIDANCE_INDI_THRUST_DYNAMICS_FREQ instead.
173#warning "The thrust dynamics are now specified in continuous time with the corner frequency of the first order model!"
174#warning "define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ in rad/s"
175#warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old value."
176#endif
177
178#ifndef GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
179#ifndef STABILIZATION_INDI_ACT_FREQ_P
180#error "You need to define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ to be able to use indi vertical control"
181#else // assume that the same actuators are used for thrust as for roll (e.g. quadrotor)
182#define GUIDANCE_INDI_THRUST_DYNAMICS_FREQ STABILIZATION_INDI_ACT_FREQ_P
183#endif
184#endif //GUIDANCE_INDI_THRUST_DYNAMICS_FREQ
185
186#endif //GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
187
188#ifndef GUIDANCE_INDI_FILTER_CUTOFF
189#ifdef STABILIZATION_INDI_FILT_CUTOFF
190#define GUIDANCE_INDI_FILTER_CUTOFF STABILIZATION_INDI_FILT_CUTOFF
191#else
192#define GUIDANCE_INDI_FILTER_CUTOFF 3.0
193#endif
194#endif
195
196#ifndef GUIDANCE_INDI_AIRSPEED_FILT_CUTOFF
197#define GUIDANCE_INDI_AIRSPEED_FILT_CUTOFF 0.5
198#endif
199
200#ifndef GUIDANCE_INDI_MAX_LAT_ACCEL
201#define GUIDANCE_INDI_MAX_LAT_ACCEL 9.81
202#endif
203
204#ifndef GUIDANCE_INDI_COORDINATED_TURN_MIN_AIRSPEED
205#define GUIDANCE_INDI_COORDINATED_TURN_MIN_AIRSPEED 10.0
206#endif
207
208#ifndef GUIDANCE_INDI_COORDINATED_TURN_MAX_AIRSPEED
209#define GUIDANCE_INDI_COORDINATED_TURN_MAX_AIRSPEED 30.0
210#endif
211
212#ifndef GUIDANCE_INDI_COORDINATED_TURN_AIRSPEED_MARGIN
213#define GUIDANCE_INDI_COORDINATED_TURN_AIRSPEED_MARGIN 0.0
214#endif
215
216float inv_eff[4];
217
218// Max bank angle in radians
221
222#if defined(ROTWING_STATE_FW_MAX_AIRSPEED) && defined(ROTWING_STATE_QUAD_MAX_AIRSPEED)
225#else
228#endif
229
231
234
235float thrust_dyn = 0.f;
236float thrust_act = 0.f;
242
245
248
249float 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"
254struct WLS_t wls_guid_p = {
257 .gamma_sq = 100000.0,
258 .v = {0.0},
259#ifdef 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
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
278float v_gih[3];
279
280// Filters
283
288
289struct 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
295static void vel_sp_cb(uint8_t sender_id, struct FloatVect3 *vel_sp);
296struct FloatVect3 indi_vel_sp = {0.0, 0.0, 0.0};
297float time_of_vel_sp = 0.0;
298
300
301#if PERIODIC_TELEMETRY
310static void send_guidance_indi_hybrid(struct transport_tx *trans, struct link_device *dev)
311{
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
328static 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}
332static 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);*/
347
348#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
349#ifdef GUIDANCE_INDI_THRUST_DYNAMICS
351#else
353#endif
354#endif
355
356 float tau = 1.0/(2.0*M_PI*filter_cutoff);
358 for(int8_t i=0; i<3; i++) {
360 }
361 struct FloatQuat q0;
366
369
370#if GUIDANCE_INDI_HYBRID_USE_WLS
371 for (int8_t i = 0; i < GUIDANCE_INDI_HYBRID_V; i++) {
372 Bwls_gih[i] = Ga[i];
373 }
374#endif
375
376#if PERIODIC_TELEMETRY
379#if GUIDANCE_INDI_HYBRID_USE_WLS
382#endif
383#endif
384}
385
413
414void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed) {
415 gih_params.min_airspeed = min_airspeed;
417}
418
422
427
432
441{
442 // set global accel sp variable FIXME clean this
444
445 /* Obtain eulers with zxy rotation order */
449
450 /* Calculate the transition ratio so that the ctrl_effecitveness scheduling works */
453
454 // filter accel to get rid of noise and filter attitude to synchronize with accel
456
457#if GUIDANCE_INDI_RC_DEBUG
458#warning "GUIDANCE_INDI_RC_DEBUG lets you control the accelerations via RC, but disables autonomous flight!"
459 // for rc control horizontal, rotate from body axes to NED
460 float psi = eulers_zxy.psi;
461 float rc_x = -(radio_control.values[RADIO_PITCH]/9600.0)*8.0;
462 float rc_y = (radio_control.values[RADIO_ROLL]/9600.0)*8.0;
463 sp_accel.x = cosf(psi) * rc_x - sinf(psi) * rc_y;
464 sp_accel.y = sinf(psi) * rc_x + cosf(psi) * rc_y;
465
466 // for rc vertical control
467 sp_accel.z = -(radio_control.values[RADIO_THROTTLE]-4500)*8.0/9600.0;
468#endif
469
470 struct FloatVect3 accel_filt;
471 accel_filt.x = filt_accel_ned[0].o[0];
472 accel_filt.y = filt_accel_ned[1].o[0];
473 accel_filt.z = filt_accel_ned[2].o[0];
474
475 struct FloatVect3 a_diff;
476 VECT3_DIFF(a_diff, sp_accel, accel_filt);
477
478 // Bound the acceleration error so that the linearization still holds
479 Bound(a_diff.x, -6.0, 6.0);
480 Bound(a_diff.y, -6.0, 6.0);
481 Bound(a_diff.z, -9.0, 9.0);
482
483 // If the thrust to specific force ratio has been defined, include vertical control
484 // else ignore the vertical acceleration error
485#ifndef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
486#ifndef STABILIZATION_ATTITUDE_INDI_FULL
487 a_diff.z = 0.0;
488#endif
489#endif
490
491 // Calculate matrix of partial derivatives and control objective
493
494#if GUIDANCE_INDI_HYBRID_USE_WLS
495
496 // Calculate the maximum deflections
498
499 float du_gih[GUIDANCE_INDI_HYBRID_U]; // = {0.0f, 0.0f, 0.0f};
500
501 for (int i = 0; i < GUIDANCE_INDI_HYBRID_V; i++) {
502 wls_guid_p.v[i] = v_gih[i];
503 }
504 wls_alloc(&wls_guid_p, Bwls_gih, 0, 0, 10);
505 for (int i = 0; i < GUIDANCE_INDI_HYBRID_U; i++) {
506 du_gih[i] = wls_guid_p.u[i];
507 }
508 euler_cmd.x = du_gih[0];
509 euler_cmd.y = du_gih[1];
510 euler_cmd.z = du_gih[2];
511
512#else
513 // compute inverse matrix of Ga
514 float Ga_inv[3][3] = {};
516 // Calculate roll,pitch and thrust command
518#endif
519
520 // Coordinated turn
521 // feedforward estimate angular rotation omega = g*tan(phi)/v
522 float omega;
523 const float max_phi = RadOfDeg(60.0f);
524#if GUIDANCE_INDI_ZERO_AIRSPEED
525 float airspeed_turn = 0.f;
526#else
528#endif
529 // We are dividing by the airspeed, so a lower bound is important
531
534
535 //Bound euler angles to prevent flipping
538
539 // Use the current roll angle to determine the corresponding heading rate of change.
541
542 // When tilting backwards (e.g. waypoint behind the drone), we have to yaw around to face the direction
543 // of flight even when the drone is not rolling much (yet). Determine the shortest direction in which to yaw by
544 // looking at the roll angle.
545 if( (eulers_zxy.theta > 0.0f) && ( fabs(eulers_zxy.phi) < eulers_zxy.theta)) {
546 if (eulers_zxy.phi > 0.0f) {
548 } else {
550 }
551 }
552
554 omega = 9.81f / airspeed_turn * tanf(coordinated_turn_roll);
555 } else { //max 60 degrees roll
556 omega = 9.81f / airspeed_turn * 1.72305f * ((coordinated_turn_roll > 0.0f) - (coordinated_turn_roll < 0.0f));
557 }
558
559#ifdef FWD_SIDESLIP_GAIN
560 // Add sideslip correction
561 omega -= accely_filt.o[0]*FWD_SIDESLIP_GAIN;
562#endif
563
564 // We can pre-compute the required rates to achieve this turn rate:
565 // NOTE: there *should* not be any problems possible with Euler singularities here
567
568 struct FloatRates ff_rates;
569
570 ff_rates.p = -sinf(euler_zyx->theta) * omega;
571 ff_rates.q = cosf(euler_zyx->theta) * sinf(euler_zyx->phi) * omega;
572 ff_rates.r = cosf(euler_zyx->theta) * cosf(euler_zyx->phi) * omega;
573
574 // For a hybrid it is important to reduce the sideslip, which is done by changing the heading.
575 // For experiments, it is possible to fix the heading to a different value.
577 // heading is fixed by nav
578 guidance_euler_cmd.psi = heading_sp;
579 }
580 else {
581 // heading is free and controlled by guidance
584 // limit heading setpoint to be within bounds of current heading
585#ifdef STABILIZATION_ATTITUDE_SP_PSI_DELTA_LIMIT
590 if (delta_psi > delta_limit) {
592 } else if (delta_psi < -delta_limit) {
594 }
596#endif
598 }
599
600 // compute required thrust setpoint
601#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
603 // Add the increment in specific force * specific_force_to_thrust_gain to the filtered thrust
606#if GUIDANCE_INDI_RC_DEBUG
608 thrust_in = 0;
609 }
610#endif
611 // return required thrust
613
614#else
615 float thrust_vect[3];
616#if GUIDANCE_INDI_HYBRID_U > 3
617 thrust_vect[0] = du_gih[3];
620 }
621#else
622 thrust_vect[0] = 0;
623#endif
624 thrust_vect[1] = 0;
626 // specific force not defined, return required increment
628#endif
629
630 // Set the quaternion setpoint from eulers_zxy
631 struct FloatQuat sp_quat;
634
636}
637
638// compute accel setpoint from speed setpoint (use global variables ! FIXME)
640{
641 struct FloatVect3 accel_sp = { 0.f, 0.f, 0.f };
642
644
645 //for rc control horizontal, rotate from body axes to NED
646 float psi = eulers_zxy.psi;
647 float cpsi = cosf(psi);
648 float spsi = sinf(psi);
649 float speed_sp_b_x = cpsi * gi_speed_sp.x + spsi * gi_speed_sp.y;
650 float speed_sp_b_y = -spsi * gi_speed_sp.x + cpsi * gi_speed_sp.y;
651
652 // Get airspeed or zero it
653#if GUIDANCE_INDI_ZERO_AIRSPEED
654 float airspeed = 0.f;
655#else
656 float airspeed = stateGetAirspeed_f();
657 Bound(airspeed, 0.0f, 100.0f);
659 airspeed = guidance_indi_airspeed_filt.o[0];
660 }
661#endif
663 struct FloatVect2 airspeed_v = { cpsi * airspeed, spsi * airspeed };
664 struct FloatVect2 windspeed;
666
667 VECT2_DIFF(desired_airspeed, gi_speed_sp, windspeed); // Use 2d part of gi_speed_sp
669
671
672 // Check if some minimum airspeed is desired (e.g. to prevent stall)
675 }
676
678
679 // Make turn instead of straight line, control airspeed
680 if ((airspeed > TURN_AIRSPEED_TH) && (norm_des_as > (TURN_AIRSPEED_TH+2.0f))) {
681
682 // Give the wind cancellation priority.
684 float groundspeed_factor = 0.0f;
685
686 // if the wind is faster than we can fly, just fly in the wind direction
689 float bv = -2.f * (windspeed.x * gi_speed_sp.x + windspeed.y * gi_speed_sp.y);
691
692 float dv = bv * bv - 4.0f * av * cv;
693
694 // dv can only be positive, but just in case
695 if (dv < 0.0f) {
696 dv = fabsf(dv);
697 }
698 float d_sqrt = sqrtf(dv);
699
700 groundspeed_factor = (-bv + d_sqrt) / (2.0f * av);
701 }
702
705
707 }
708
709 if (force_forward) {
711 }
712
713 // Calculate accel sp in body axes, because we need to regulate airspeed
714 struct FloatVect2 sp_accel_b;
715 // In turn acceleration proportional to heading diff
719
721
722 // Control the airspeed
724
725 accel_sp.x = cpsi * sp_accel_b.x - spsi * sp_accel_b.y;
726 accel_sp.y = spsi * sp_accel_b.x + cpsi * sp_accel_b.y;
728 }
729 else { // Go somewhere in the shortest way
730
731 if (airspeed > 10.f) {
732 // Groundspeed vector in body frame
733 float groundspeed_x = cpsi * stateGetSpeedNed_f()->x + spsi * stateGetSpeedNed_f()->y;
735
736 // limit groundspeed setpoint to max_airspeed + (diff gs and airspeed)
737 if ((speed_increment + airspeed) > gih_params.max_airspeed) {
739 }
740 }
741
742 gi_speed_sp.x = cpsi * speed_sp_b_x - spsi * speed_sp_b_y;
743 gi_speed_sp.y = spsi * speed_sp_b_x + cpsi * speed_sp_b_y;
744
748 }
749
750 // Bound the acceleration setpoint
751 float accelbound = 3.0f + airspeed / gih_params.max_airspeed * 5.0f; // FIXME remove hard coded values
753 BoundAbs(accel_sp.z, 3.0);
754
755#ifdef ROTWING_FW_MIN_AIRSPEED
758 BoundAbs(accel_sp.z, 5.0);
759 }
760#endif
761
762 return accel_sp;
763}
764
765static float bound_vz_sp(float vz_sp)
766{
767 // Bound vertical speed setpoint
770 } else {
772 }
773 return vz_sp;
774}
775
777{
778 struct FloatVect3 pos_err = { 0 };
779 struct FloatVect3 accel_sp = { 0 };
780
781 // First check for velocity setpoint from module // FIXME should be called like this
782 float dt = get_sys_time_float() - time_of_vel_sp;
783 // If the input command is not updated after a timeout, switch back to flight plan control
784 if (dt < 0.5) {
788 accel_sp = compute_accel_from_speed_sp(); // compute accel sp
789 return guidance_indi_run(&accel_sp, gh->sp.heading);
790 }
791
793 //Linear controller to find the acceleration setpoint from position and velocity
801 } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
803 } else {
804 gi_speed_sp.z = 0.f;
805 }
806 accel_sp = compute_accel_from_speed_sp(); // compute accel sp
808 accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
809 }
810 return guidance_indi_run(&accel_sp, gh->sp.heading);
811 }
813 gi_speed_sp.x = SPEED_FLOAT_OF_BFP(gh->ref.speed.x);
814 gi_speed_sp.y = SPEED_FLOAT_OF_BFP(gh->ref.speed.y);
818 } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
820 } else {
821 gi_speed_sp.z = 0.f;
822 }
823 accel_sp = compute_accel_from_speed_sp(); // compute accel sp
825 accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
826 }
827 return guidance_indi_run(&accel_sp, gh->sp.heading);
828 }
829 else { // H_ACCEL
830 gi_speed_sp.x = 0.f;
831 gi_speed_sp.y = 0.f;
835 } else if (v_mode == GUIDANCE_INDI_HYBRID_V_SPEED) {
837 } else {
838 gi_speed_sp.z = 0.f;
839 }
840 accel_sp = compute_accel_from_speed_sp(); // compute accel sp in case z control is required
841 // overwrite accel X and Y
845 accel_sp.z = (gi_speed_sp.z - stateGetSpeedNed_f()->z) * gih_params.speed_gainz + ACCEL_FLOAT_OF_BFP(gv->zdd_ref); // overwrite accel
846 }
847 return guidance_indi_run(&accel_sp, gh->sp.heading);
848 }
849}
850
851#ifdef GUIDANCE_INDI_SPECIFIC_FORCE_GAIN
856{
857 // Actuator dynamics
859
860 // same filter as for the acceleration
862}
863
864#endif
865
872{
873 struct NedCoor_f *accel = stateGetAccelNed_f();
877
879
880 // Propagate filter for sideslip correction
883
884 float airspeed = stateGetAirspeed_f();
885 Bound(airspeed, 0.0f, 100.0f);
887}
888
889
897float WEAK guidance_indi_get_liftd(float airspeed, float theta) {
898 float liftd = 0.0f;
899
900 if (airspeed < 12.f) {
901 /* Assume the airspeed is too low to be measured accurately
902 * Use scheduling based on pitch angle instead.
903 * You can define two interpolation segments
904 */
905 float pitch_interp = DegOfRad(theta);
906 const float min_pitch = -80.0f;
907 const float middle_pitch = -50.0f;
908 const float max_pitch = -20.0f;
909
912 float ratio = (pitch_interp - max_pitch)/(middle_pitch - max_pitch);
913 liftd = -gih_params.liftd_p50*ratio;
914 } else {
915 float ratio = (pitch_interp - middle_pitch)/(min_pitch - middle_pitch);
917 }
918 } else {
919 liftd = -gih_params.liftd_asq*airspeed*airspeed;
920 }
921
922 //TODO: bound liftd
923 return liftd;
924}
925
930{
931 indi_vel_sp.x = vel_sp->x;
932 indi_vel_sp.y = vel_sp->y;
933 indi_vel_sp.z = vel_sp->z;
935}
936
937
938#if GUIDANCE_INDI_HYBRID_USE_AS_DEFAULT
939// guidance indi control function is implementing the default functions of guidance
940
941void guidance_h_run_enter(void)
942{
944}
945
946void guidance_v_run_enter(void)
947{
948 // nothing to do
949}
950
951static struct VerticalGuidance *_gv = &guidance_v;
953
955{
957}
958
960{
962}
963
965{
967}
968
970{
971 _gv = gv;
973 return thrust_sp;
974}
975
977{
978 _gv = gv;
980 return thrust_sp;
981}
982
984{
985 _gv = gv;
987 return thrust_sp;
988}
989
990#endif
991
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
Core autopilot interface common to all firmwares.
#define UNUSED(x)
static struct uart_periph * dev
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)
static void float_quat_identity(struct FloatQuat *q)
initialises a quaternion to identity
void float_eulers_of_quat_zxy(struct FloatEulers *e, const struct FloatQuat *q)
euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
void float_mat3_mult(struct FloatVect3 *vect_out, const float mat[3][3], const struct FloatVect3 vect_in)
Multiply 3D matrix with vector.
bool float_mat_inv_3d(float inv_out[3][3], const float mat_in[3][3])
3x3 matrix inverse
void float_quat_of_eulers_zxy(struct FloatQuat *q, const struct FloatEulers *e)
quat from euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
void float_vect3_bound_in_2d(struct FloatVect3 *vect3, const float bound)
#define FLOAT_VECT2_NORM(_v)
euler angles
Roation quaternion.
angular rates
#define VECT2_DIFF(_c, _a, _b)
#define VECT3_DIFF(_c, _a, _b)
#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:1203
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1314
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1302
static struct NedCoor_f * stateGetPositionNed_f(void)
Get position in local NED coordinates (float).
Definition state.h:839
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition state.h:1049
static struct Int32Vect3 * stateGetAccelBody_i(void)
Get acceleration in Body coordinates (int).
Definition state.h:1094
static float stateGetAirspeed_f(void)
Get airspeed (float).
Definition state.h:1598
int32_t max_airspeed
struct FloatMat33 Ga_inv
float thrust_vect[3]
float guidance_indi_specific_force_gain
struct FloatVect3 indi_vel_sp
bool force_forward
forward flight for hybrid nav
QuatButterworthLowPass quat_filt
#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
#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)
void guidance_set_max_bank_angle(float max_bank)
float inv_eff[4]
#define GUIDANCE_INDI_FWD_DESCEND_SPEED
Descend speed when navigation is making turns instead of direct lines.
void guidance_set_max_climb_speed(float max_climb_speed_quad, float max_climb_speed_fwd)
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
#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
void guidance_set_max_descend_speed(float max_descend_speed_quad, float max_descend_speed_fwd)
#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, const float tau, const float sample_time, const float value)
Init a second order Butterworth filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, const float value)
Update second order Butterworth low pass filter state with a new value.
Second order low pass filter structure.
uint16_t foo
Definition main_demo5.c:58
float z
in meters
float x
in meters
float y
in meters
vector in North East Down coordinates Units: meters
Quaternion second order filter.
static struct FloatQuat update_quat_butterworth_low_pass(QuatButterworthLowPass *filter, const struct FloatQuat quat)
Update second order quaternion Butterworth low pass filter state with a new value.
static void init_quat_butterworth_low_pass(QuatButterworthLowPass *filter, const float omega, const float sample_time, const struct FloatQuat q0)
Init a second order quaternion Butterworth filter.
Quaternion second order filter model (float)
struct RadioControl radio_control
Generic interface for radio control modules.
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
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
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
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.
Stabilization setpoint.
Thrust setpoint // TODO to a setpoint header Structure to store the desired thrust vector with differ...
Architecture independent timing functions.
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:168
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_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.
signed char int8_t
Typedef defining 8 bit char type.
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
int nu
Definition wls_alloc.h:67