Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
stabilization_andi.c
Go to the documentation of this file.
1/*
2 *
3 * Copyright (C) 2025 Justin Dubois <j.p.g.dubois@student.tudelft.nl>
4 *
5 * This file is part of paparazzi
6 *
7 * paparazzi is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * paparazzi is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with paparazzi; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
20 *
21 */
22
45#include "state.h"
46#include "generated/airframe.h"
49#include "modules/core/abi.h"
50#include "math/wls/wls_alloc.h"
55#include "autopilot.h"
64
65#include <stdio.h>
66#if INS_EXT_POSE
68#endif
69
70#ifdef STABILIZATION_ANDI_SCHEDULE_EFF
72#else
73 const bool SCHEDULE_EFF = false;
74#endif
75
76#ifdef STABILIZATION_ANDI_USE_STATE_DYNAMICS
78#else
79 const bool USE_STATE_DYNAMICS = false;
80#endif
81
82#ifdef STABILIZATION_ANDI_RELAX_OBM
84#else
85 const float ANDI_RELAX_OBM = 1.0f;
86#endif
87
88#ifdef STABILIZATION_ANDI_ACT_IS_SERVO
90#else
92#endif
93
94#ifdef STABILIZATION_ANDI_ACT_DYNAMICS
96#else
97 #error "You must specify the actuator dynamics"
98#endif
99
100#ifdef STABILIZATION_ANDI_ACT_DELAY
102#else
104#endif
105
106#if defined(STABILIZATION_ANDI_ACT_MAX) && defined(STABILIZATION_ANDI_ACT_MIN)
109#else
110 #error "You must specify the actuator limits: STABILIZATION_ANDI_ACT_MAX and STABILIZATION_ANDI_ACT_MIN"
111#endif
112
113#if defined(STABILIZATION_ANDI_ACT_RATE_MAX) && defined(STABILIZATION_ANDI_ACT_RATE_MIN)
116#else
117 #error "You must specify the actuator limits: STABILIZATION_ANDI_ACT_RATE_MAX and STABILIZATION_ANDI_ACT_RATE_MIN"
118#endif
119
120#if defined STABILIZATION_ANDI_ACT_PREF
122#else
123const float ACTUATOR_PREF[ANDI_NUM_ACT] = {0.0f};
124#endif
125
126#if defined STABILIZATION_ANDI_RC_RATE_MAX
128#else
129const float RC_RATE_MAX[ANDI_OUTPUTS] = {[0 ... ANDI_OUTPUTS - 1] = 5.0f};
130#endif
131
132#ifdef STABILIZATION_ANDI_THRUST_MIN
134#else
135 const float THRUST_MIN = 0.0f;
136#endif
137
138#ifdef STABILIZATION_ANDI_THRUST_MAX
140#else
141 #error "You must specify maximum specific thrust: STABILIZATION_ANDI_THRUST_MAX"
142#endif
143
144#ifdef PERIODIC_FREQUENCY
145 const float SAMPLE_TIME = 1.0f / PERIODIC_FREQUENCY;
146#else
147 #error "Periodic frequency is not defined."
148#endif
149
150#if ANDI_NUM_ACT > WLS_N_U_MAX
151 #error Matrix-WLS_N_U_MAX too small or not defined: define WLS_N_U_MAX >= ANDI_NUM_ACT in airframe file
152#endif
153#if ANDI_OUTPUTS > WLS_N_V_MAX
154 #error Matrix-WLS_N_V_MAX too small or not defined: define WLS_N_V_MAX >= ANDI_OUTPUTS in airframe file
155#endif
156
157#ifdef STABILIZATION_ANDI_WLS_WV
159#else
160const float WLS_WV[ANDI_OUTPUTS] = {[0 ... ANDI_OUTPUTS - 1] = 1.0f};
161#endif
162
169#ifdef STABILIZATION_ANDI_WLS_WU
171#else
172float WLS_WU[ANDI_NUM_ACT] = {[0 ... ANDI_NUM_ACT - 1] = 1.0f};
173#endif
174
175#ifdef STABILIZATION_ANDI_CUTOFF_FREQ_OMEGA
176const struct FloatVect3 CUTOFF_FREQ_OMEGA = {
180}; // rad/s
181#else
182#error "You must specify the cutoff frequency for omega: STABILIZATION_ANDI_CUTOFF_FREQ_OMEGA"
183#endif
184
185#ifdef STABILIZATION_ANDI_CUTOFF_FREQ_OMEGA_DOT
186const struct FloatVect3 CUTOFF_FREQ_OMEGA_DOT = {
190}; // rad/s
193#else
194#error "You must specify the cutoff frequency for omega_dot: STABILIZATION_ANDI_CUTOFF_FREQ_OMEGA_DOT"
195#endif
196
197#ifdef STABILIZATION_ANDI_CUTOFF_FREQ_ACCEL
198const struct FloatVect3 CUTOFF_FREQ_ACCEL = {
202};
203#else
204#error "You must specify the cutoff frequency for accel: STABILIZATION_ANDI_CUTOFF_FREQ_ACCEL"
205#endif
206
207#ifdef STABILIZATION_ANDI_CUTOFF_FREQ_VEL
208const struct FloatVect3 CUTOFF_FREQ_VEL = {
212}; // rad/s
213#else
214#error "You must specify the cutoff frequency for vel: STABILIZATION_ANDI_CUTOFF_FREQ_VEL"
215#endif
216
217
218// Function prototypes
226static void generate_reference_rate(float dt, const struct FloatRates *rate_des,
227 const struct GainsOrder2Vect3 *k_rate_rm, const struct AttQuat *bounds,
228 struct AttQuat *att_ref) __attribute__((unused));
229static void generate_reference_attitude(float dt, const struct FloatQuat *att_des,
230 const struct GainsOrder3Vect3 *k_att_rm, const struct AttQuat *bounds, struct AttQuat *att_ref);
231static void generate_reference_thrust(float dt, float thrust_des, const float k_thrust_rm,
232 const struct ThrustRef *bounds_min, const struct ThrustRef *bounds_max, struct ThrustRef *thrust_ref);
233static struct FloatVect3 control_error_rate(const struct AttQuat *att_ref, const struct AttStateQuat *att_state,
234 const struct GainsOrder2Vect3 *k_rate_ec) __attribute__((unused));
235static struct FloatVect3 control_error_attitude(const struct AttQuat *att_ref, const struct AttStateQuat *att_state,
236 const struct GainsOrder3Vect3 *k_att_ec);
237static float control_error_thrust(const struct ThrustRef *thrust_ref, const float thrust_state,
238 const float k_thrust_ec);
239static void compute_wls_upper_bounds(float u_d_max[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT],
240 const float act_max[ANDI_NUM_ACT], const float act_rate_max[ANDI_NUM_ACT],
241 const float actuator_bandwidth[ANDI_NUM_ACT]);
242static void compute_wls_lower_bounds(float u_d_min[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT],
243 const float act_min[ANDI_NUM_ACT], const float act_rate_min[ANDI_NUM_ACT],
244 const float actuator_bandwidth[ANDI_NUM_ACT]);
245static void compute_wls_u_scaler(float u_scaler[ANDI_NUM_ACT], const float act_min[ANDI_NUM_ACT],
246 const float act_max[ANDI_NUM_ACT]);
247static void compute_wls_v_scaler(float v_scaler[ANDI_NUM_ACT], const float v[ANDI_NUM_ACT]) __attribute__((unused));
248
249static inline float ec_k1_order3_f(const float omega_n, const float zeta, const float omega_a) { return (omega_n * omega_n * (omega_a - 2 * zeta * omega_n)); }
250static inline float ec_k2_order3_f(const float omega_n, const float zeta, const float omega_a) { return (omega_n * omega_n + 2.0f * zeta * omega_n * (omega_a - 2 * zeta * omega_n)); }
251static inline float ec_k3_order3_f(const float omega_n __attribute__((unused)),
252 const float zeta __attribute__((unused)), const float omega_a) { return omega_a; }
253static inline float rm_k1_order3_f(const float omega_n, const float zeta, const float omega_a) { return (omega_n * omega_n * omega_a) / (omega_n * omega_n + 2 * zeta * omega_n * omega_a); }
254static inline float rm_k2_order3_f(const float omega_n, const float zeta, const float omega_a) { return (omega_n * omega_n + 2 * zeta * omega_n * omega_a) / (2 * zeta * omega_n + omega_a); }
255static inline float rm_k3_order3_f(const float omega_n, const float zeta, const float omega_a) { return 2 * zeta * omega_n + omega_a; }
256
257static inline float ec_k1_order2_f(const float omega_a, const float zeta) { return omega_a * omega_a / (4 * zeta * zeta); }
258static inline float ec_k2_order2_f(const float omega_a, const float zeta __attribute__((unused))) { return omega_a; }
259static inline float rm_k1_order2_f(const float omega_a, const float zeta) { return ec_k2_order2_f(omega_a, zeta) / ec_k2_order2_f(omega_a, zeta); }
260static inline float rm_k2_order2_f(const float omega_a, const float zeta) { return ec_k2_order2_f(omega_a, zeta); }
261
322
323
324// WLS allocation variables
326 .nu = ANDI_NUM_ACT,
327 .nv = ANDI_OUTPUTS,
328 .gamma_sq = 100000.0,
329 .u_pref = {0.0f},
330 .u_min = {0.0f},
331 .u_max = {0.0f},
332 .PC = 0.0f,
333 .SC = 0.0f,
334 .iter = 0
335};
336
337// Controller gains
344
345// Complementary filter instances for state dependent contribution
349
353
354// Actuator and delay
355struct FirstOrderZOHLowPass actuator_obm_zohlpf[ANDI_NUM_ACT]; // ZOH low pass filter for actuator model
356struct TransportDelay actuator_obm_delay[ANDI_NUM_ACT]; // transport delay for actuator model
357float actuator_state[ANDI_NUM_ACT]; // from feedback or model
358float actuator_state_lpf[ANDI_NUM_ACT]; // delayed actuator state
359
360// T4 Actuator feedback handling
363float actuator_meas[ANDI_NUM_ACT]; // measured actuator feedback
364
365// Raw state measurement variables
367
368// State variables
369struct AttStateQuat attitude_state_cf; // undelayed attitude state for feedforward
370struct LinState linear_state_cf; // undelayed linear state for feedforward
371float thrust_state; // delayed thrust state for feedback
372
373// Reference model variables
376
377// Setpoints
381
382// Bounds
386
387// Controller variables
393
394// Pseudo command variables
395float nu_obj[ANDI_OUTPUTS]; // Total pseudo command allocated to the actuators
396float nu_ec[ANDI_OUTPUTS]; // Pseudo command from the error controller
397float nu_obm[ANDI_OUTPUTS]; // Pseudo command from the on board model state dependent term
398// float nu_reconstructed[ANDI_OUTPUTS]; // Reconstructed angular acceleration from the actuator commands (for model verification)
399
400#if PERIODIC_TELEMETRY
403{
404 char *name = "andi";
406 strlen(name), name,
407 &wls_stab_p.gamma_sq, // Does this need scaling as a function of scaling factor?
410 ANDI_OUTPUTS, (float *)WLS_WV);
411}
412
414{
415 char *name = "andi";
416 float zero_array[ANDI_NUM_ACT] = {0.0f};
418 strlen(name), name,
419 ANDI_NUM_ACT, (float *)WLS_WU,
424}
425
434
436{
438 4, (float *)&attitude_des,
439 4, (float *)&attitude_state_cf.att,
440 4, (float *)&attitude_ref.att,
441 3, (float *)&attitude_state_cf.att_d,
442 3, (float *)&attitude_ref.att_d,
443 3, (float *)&attitude_state_cf.att_2d,
444 3, (float *)&attitude_ref.att_2d,
445 3, (float *)&attitude_ref.att_3d,
447}
448// For debug only
449// static void send_stab_thrust_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
450// {
451// pprz_msg_send_STAB_THRUST(trans, dev, AC_ID,
452// &thrust_des,
453// &thrust_ref.thrust,
454// &thrust_state,
455// &thrust_ref.thrust_d);
456// }
457
458// static void send_on_board_model_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
459// {
460// pprz_msg_send_ON_BOARD_MODEL(trans, dev, AC_ID,
461// 3, (float *)&linear_state_cf.vel,
462// 3, (float *)&linear_state_cf.acc,
463// ANDI_NUM_ACT, (float *)&actuator_meas,
464// ANDI_OUTPUTS, (float *)&nu_obm);
465// }
466
467// static void send_stab_pseudo_command_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
468// {
469// /**
470// * nu_obj: Total pseudo command sent to the actuators
471// * nu_ec: Pseudo command from the error controller
472// * nu_obm: Pseudo command from the on board model state dependent term
473// * nu_reconstructed: Reconstructed angular acceleration from the actuator commands.
474// * This is used to verify the on board model. If the OBM is perfect, then nu_reconstructed should be
475// * equal to the measured state plus any external disturbances.
476// *
477// * nu_obj = nu_ec + nu_obm
478// * nu_reconstructed = Ce * u_meas - nu_obm NOTE: This is wrong equation, fix it.
479// *
480// * FIXME: nu_reconstructed has been repurposed and no longer is the reconstructed value. Update the telemetry message accordingly.
481// */
482// pprz_msg_send_STAB_PSEUDO_COMMAND(trans, dev, AC_ID,
483// ANDI_OUTPUTS, nu_obj, // Total pseudo command
484// ANDI_OUTPUTS, nu_ec, // From error controller
485// ANDI_OUTPUTS, nu_obm, // From on board model state dependent term
486// ANDI_OUTPUTS, nu_reconstructed); // Reconstructed from actuator commands
487// }
488
489#endif // PERIODIC_TELEMETRY
490
493
507{
508 // Copy the entire ActuatorsT4In struct from the pointer to actuator_obs
510}
511
531{
532 actuator_meas[0] = RadOfCentiDeg((float)actuators_t4_in_ptr->servo_1_angle);
533 actuator_meas[1] = -RadOfCentiDeg((float)actuators_t4_in_ptr->servo_6_angle);
534 actuator_meas[2] = (float)actuators_t4_in_ptr->esc_1_rpm * 2 * M_PI / 60; // Convert rpm to rad/s
535 actuator_meas[2] *= actuator_meas[2]; // square motor rpm
536 actuator_meas[3] = (float)actuators_t4_in_ptr->esc_2_rpm * 2 * M_PI / 60;
537 actuator_meas[3] *= actuator_meas[3]; // square motor rpm
538}
539
547{
548 struct GainsOrder3Vect3 gains;
549 gains.k1.x = rm_k1_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
550 gains.k1.y = rm_k1_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
551 gains.k1.z = rm_k1_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
552
553 gains.k2.x = rm_k2_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
554 gains.k2.y = rm_k2_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
555 gains.k2.z = rm_k2_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
556
557 gains.k3.x = rm_k3_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
558 gains.k3.y = rm_k3_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
559 gains.k3.z = rm_k3_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
560 return gains;
561}
562
570{
571 struct GainsOrder2Vect3 gains;
572 gains.k1.x = rm_k1_order2_f(poles->omega_a.x, poles->zeta.x);
573 gains.k1.y = rm_k1_order2_f(poles->omega_a.y, poles->zeta.y);
574 gains.k1.z = rm_k1_order2_f(poles->omega_a.z, poles->zeta.z);
575
576 gains.k2.x = rm_k2_order2_f(poles->omega_a.x, poles->zeta.x);
577 gains.k2.y = rm_k2_order2_f(poles->omega_a.y, poles->zeta.y);
578 gains.k2.z = rm_k2_order2_f(poles->omega_a.z, poles->zeta.z);
579 return gains;
580}
581
589{
590 struct GainsOrder3Vect3 gains;
591 gains.k1.x = ec_k1_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
592 gains.k1.y = ec_k1_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
593 gains.k1.z = ec_k1_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
594
595 gains.k2.x = ec_k2_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
596 gains.k2.y = ec_k2_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
597 gains.k2.z = ec_k2_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
598
599 gains.k3.x = ec_k3_order3_f(poles->omega_n.x, poles->zeta.x, poles->omega_a.x);
600 gains.k3.y = ec_k3_order3_f(poles->omega_n.y, poles->zeta.y, poles->omega_a.y);
601 gains.k3.z = ec_k3_order3_f(poles->omega_n.z, poles->zeta.z, poles->omega_a.z);
602 return gains;
603}
604
612{
613 struct GainsOrder2Vect3 gains;
614 gains.k1.x = ec_k1_order2_f(poles->omega_a.x, poles->zeta.x);
615 gains.k1.y = ec_k1_order2_f(poles->omega_a.y, poles->zeta.y);
616 gains.k1.z = ec_k1_order2_f(poles->omega_a.z, poles->zeta.z);
617
618 gains.k2.x = ec_k2_order2_f(poles->omega_a.x, poles->zeta.x);
619 gains.k2.y = ec_k2_order2_f(poles->omega_a.y, poles->zeta.y);
620 gains.k2.z = ec_k2_order2_f(poles->omega_a.z, poles->zeta.z);
621 return gains;
622}
623
639 float dt,
640 const struct FloatRates *rate_des,
641 const struct GainsOrder2Vect3 *k_rate_rm,
642 const struct AttQuat *bounds,
643 struct AttQuat *att_ref)
644{
645 float p_des = rate_des->p;
646 float q_des = rate_des->q;
647 float r_des = rate_des->r;
648
649 BoundAbs(p_des, bounds->att_d.p);
650 BoundAbs(q_des, bounds->att_d.q);
651 BoundAbs(r_des, bounds->att_d.r);
652
653 float p_d_des = k_rate_rm->k1.x * (p_des - att_ref->att_d.p);
654 float q_d_des = k_rate_rm->k1.y * (q_des - att_ref->att_d.q);
655 float r_d_des = k_rate_rm->k1.z * (r_des - att_ref->att_d.r);
656
657 BoundAbs(p_d_des, bounds->att_2d.x);
658 BoundAbs(q_d_des, bounds->att_2d.y);
659 BoundAbs(r_d_des, bounds->att_2d.z);
660
661 float p_2d_des = k_rate_rm->k2.x * (p_d_des - att_ref->att_2d.x);
662 float q_2d_des = k_rate_rm->k2.y * (q_d_des - att_ref->att_2d.y);
663 float r_2d_des = k_rate_rm->k2.z * (r_d_des - att_ref->att_2d.z);
664
665 BoundAbs(p_2d_des, bounds->att_3d.x);
666 BoundAbs(q_2d_des, bounds->att_3d.y);
667 BoundAbs(r_2d_des, bounds->att_3d.z);
668
669 att_ref->att_3d.x = p_2d_des;
670 att_ref->att_3d.y = q_2d_des;
671 att_ref->att_3d.z = r_2d_des;
672
673 att_ref->att_2d.x += p_2d_des * dt;
674 att_ref->att_2d.y += q_2d_des * dt;
675 att_ref->att_2d.z += r_2d_des * dt;
676
677 att_ref->att_d.p += att_ref->att_2d.x * dt;
678 att_ref->att_d.q += att_ref->att_2d.y * dt;
679 att_ref->att_d.r += att_ref->att_2d.z * dt;
680
682}
683
703 float dt,
704 const struct FloatQuat *att_des,
705 const struct GainsOrder3Vect3 *k_att_rm,
706 const struct AttQuat *bounds,
707 struct AttQuat *att_ref)
708{
709 struct FloatQuat att_err; // rotation from ref to des
711 float p_des = k_att_rm->k1.x * att_err.qx * 2;
712 float q_des = k_att_rm->k1.y * att_err.qy * 2;
713 float r_des = k_att_rm->k1.z * att_err.qz * 2;
714
715 BoundAbs(p_des, bounds->att_d.p);
716 BoundAbs(q_des, bounds->att_d.q);
717 BoundAbs(r_des, bounds->att_d.r);
718
719 float p_d_des = k_att_rm->k2.x * (p_des - att_ref->att_d.p);
720 float q_d_des = k_att_rm->k2.y * (q_des - att_ref->att_d.q);
721 float r_d_des = k_att_rm->k2.z * (r_des - att_ref->att_d.r);
722
723 BoundAbs(p_d_des, bounds->att_2d.x);
724 BoundAbs(q_d_des, bounds->att_2d.y);
725 BoundAbs(r_d_des, bounds->att_2d.z);
726
727 float p_2d_des = k_att_rm->k3.x * (p_d_des - att_ref->att_2d.x);
728 float q_2d_des = k_att_rm->k3.y * (q_d_des - att_ref->att_2d.y);
729 float r_2d_des = k_att_rm->k3.z * (r_d_des - att_ref->att_2d.z);
730
731 BoundAbs(p_2d_des, bounds->att_3d.x);
732 BoundAbs(q_2d_des, bounds->att_3d.y);
733 BoundAbs(r_2d_des, bounds->att_3d.z);
734
735 att_ref->att_3d.x = p_2d_des;
736 att_ref->att_3d.y = q_2d_des;
737 att_ref->att_3d.z = r_2d_des;
738
739 att_ref->att_2d.x += p_2d_des * dt;
740 att_ref->att_2d.y += q_2d_des * dt;
741 att_ref->att_2d.z += r_2d_des * dt;
742
743 att_ref->att_d.p += att_ref->att_2d.x * dt;
744 att_ref->att_d.q += att_ref->att_2d.y * dt;
745 att_ref->att_d.r += att_ref->att_2d.z * dt;
746
747 float_quat_integrate(&att_ref->att, &att_ref->att_d, dt);
749}
750
751
766 float dt,
767 float thrust_des,
768 const float k_thrust_rm,
769 const struct ThrustRef *bounds_min,
770 const struct ThrustRef *bounds_max,
771 struct ThrustRef *thrust_ref)
772{
773 Bound(thrust_des, bounds_min->thrust, bounds_max->thrust);
775
776 Bound(thrust_ref->thrust_d, bounds_min->thrust_d, bounds_max->thrust_d);
778}
779
794 const struct AttQuat *att_ref,
795 const struct AttStateQuat *att_state,
796 const struct GainsOrder2Vect3 *k_rate_ec)
797{
798 struct FloatVect3 nu = att_ref->att_3d;
799
800 nu.x += k_rate_ec->k2.x * (att_ref->att_2d.x - att_state->att_2d.x);
801 nu.y += k_rate_ec->k2.y * (att_ref->att_2d.y - att_state->att_2d.y);
802 nu.z += k_rate_ec->k2.z * (att_ref->att_2d.z - att_state->att_2d.z);
803
804 nu.x += k_rate_ec->k1.x * (att_ref->att_d.p - att_state->att_d.p);
805 nu.y += k_rate_ec->k1.y * (att_ref->att_d.q - att_state->att_d.q);
806 nu.z += k_rate_ec->k1.z * (att_ref->att_d.r - att_state->att_d.r);
807
808 return nu;
809}
810
825 const struct AttQuat *att_ref,
826 const struct AttStateQuat *att_state,
827 const struct GainsOrder3Vect3 *k_att_ec)
828{
829 struct FloatVect3 nu = att_ref->att_3d;
830
831 nu.x += k_att_ec->k3.x * (att_ref->att_2d.x - att_state->att_2d.x);
832 nu.y += k_att_ec->k3.y * (att_ref->att_2d.y - att_state->att_2d.y);
833 nu.z += k_att_ec->k3.z * (att_ref->att_2d.z - att_state->att_2d.z);
834
835 nu.x += k_att_ec->k2.x * (att_ref->att_d.p - att_state->att_d.p);
836 nu.y += k_att_ec->k2.y * (att_ref->att_d.q - att_state->att_d.q);
837 nu.z += k_att_ec->k2.z * (att_ref->att_d.r - att_state->att_d.r);
838
839 struct FloatQuat att_err; // rotation from state to reference
841 // Multiplication by 2 needed to convert quaternion difference to angular rate.
842 nu.x += k_att_ec->k1.x * att_err.qx * 2;
843 nu.y += k_att_ec->k1.y * att_err.qy * 2;
844 nu.z += k_att_ec->k1.z * att_err.qz * 2;
845
846 return nu;
847}
848
865 const struct ThrustRef *thrust_ref,
866 const float thrust_state,
867 const float k_thrust_ec)
868{
869 float nu = thrust_ref->thrust_d;
871 return nu;
872}
873
888static void compute_wls_upper_bounds(float u_d_max[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT],
889 const float act_max[ANDI_NUM_ACT], const float act_rate_max[ANDI_NUM_ACT], const float actuator_bandwidth[ANDI_NUM_ACT])
890{
891 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
892 // Calculate max rate allowed to avoid exceeding actuator max position in one timestep
893 float rate_limit_pos = (act_max[i] - act_state[i]) * actuator_bandwidth[i];
895 Bound(u_d_max[i], 0.0f, INFINITY);
896 }
897}
898
914static void compute_wls_lower_bounds(float u_d_min[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT],
915 const float act_min[ANDI_NUM_ACT], const float act_rate_min[ANDI_NUM_ACT], const float actuator_bandwidth[ANDI_NUM_ACT])
916{
917 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
918 // Calculate min rate allowed to avoid going below actuator min position in one timestep
919 float rate_limit_pos = (act_min[i] - act_state[i]) * actuator_bandwidth[i];
921 Bound(u_d_min[i], -INFINITY, 0.0f);
922 }
923}
924
940 const float act_max[ANDI_NUM_ACT])
941{
942 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
943 float range = fabs(act_max[i] - act_min[i]);
944 if (range <= FLT_EPSILON) {
945 u_scaler[i] = 1.0f;
946 } else {
947 u_scaler[i] = 1.0f / range;
948 }
949 }
950}
951
963static void compute_wls_v_scaler(float v_scaler[ANDI_NUM_ACT], const float v[ANDI_NUM_ACT])
964{
965 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
966 if (fabs(v[i]) <= FLT_EPSILON) {
967 v_scaler[i] = 1.0f;
968 } else {
969 v_scaler[i] = 1.0f / fabs(v[i]);
970 }
971 }
972}
973
975{
976 // Compute gains
983
984 // Initialize state variables
985 rates_prev.p = 0.0f;
986 rates_prev.q = 0.0f;
987 rates_prev.r = 0.0f;
988
996
997 linear_state_cf.vel.x = 0.0f;
998 linear_state_cf.vel.y = 0.0f;
999 linear_state_cf.vel.z = 0.0f;
1000 linear_state_cf.acc.x = 0.0f;
1001 linear_state_cf.acc.y = 0.0f;
1002 linear_state_cf.acc.z = 0.0f;
1003
1004 thrust_state = 0.0f;
1011 // float_vect_zero(nu_reconstructed, ANDI_NUM_ACT);
1012
1013 // Initialize reference variables
1015 attitude_ref.att_d.p = 0.0f;
1016 attitude_ref.att_d.q = 0.0f;
1017 attitude_ref.att_d.r = 0.0f;
1018 attitude_ref.att_2d.x = 0.0f;
1019 attitude_ref.att_2d.y = 0.0f;
1020 attitude_ref.att_2d.z = 0.0f;
1021 attitude_ref.att_3d.x = 0.0f;
1022 attitude_ref.att_3d.y = 0.0f;
1023 attitude_ref.att_3d.z = 0.0f;
1024
1025 thrust_ref.thrust = 0.0f;
1026 thrust_ref.thrust_d = 0.0f;
1027
1028 // FIXME: These bounds should be set via parameters
1029 // Initialize attitude bounds (symmetric bounds on abs values)
1031 attitude_bounds.att_d.p = 100.0f;
1032 attitude_bounds.att_d.q = 100.0f;
1033 attitude_bounds.att_d.r = 25.0f;
1034 attitude_bounds.att_2d.x = 100.0f;
1035 attitude_bounds.att_2d.y = 100.0f;
1036 attitude_bounds.att_2d.z = 20.0f;
1037 attitude_bounds.att_3d.x = 100.0f;
1038 attitude_bounds.att_3d.y = 100.0f;
1039 attitude_bounds.att_3d.z = 100.0f;
1040
1041 // Limit thrust bounds (asymmetric bounds)
1044 thrust_bounds_min.thrust_d = -1000.0f;
1045 thrust_bounds_max.thrust_d = 1000.0f;
1046
1047 // Initial control effectiveness matrix
1049
1050 // Initialize filters
1053 angular_rates_obm.p = 0.0f;
1054 angular_rates_obm.q = 0.0f;
1055 angular_rates_obm.r = 0.0f;
1056
1059 linear_velocity_obm.x = 0.0f;
1060 linear_velocity_obm.y = 0.0f;
1061 linear_velocity_obm.z = 0.0f;
1062
1063 // Bind T4 actuator feedback abi message
1065
1066 // Precompute discrete-time actuator dynamics coefficients
1069
1070// Start telemetry
1071#if PERIODIC_TELEMETRY
1073 // register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_STAB_THRUST, send_stab_thrust_stabilization_andi); // For debug only, dont forget to add your message.
1077 // register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_STAB_PSEUDO_COMMAND, send_stab_pseudo_command_stabilization_andi);
1078 // register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_ON_BOARD_MODEL, send_on_board_model_stabilization_andi);
1079#endif
1080}
1081
1093{
1094 // Reset actuator states to current measurements
1098
1099 // Clear previous rates
1100 rates_prev.p = 0.0f;
1101 rates_prev.q = 0.0f;
1102 rates_prev.r = 0.0f;
1103
1104 // Reset state to current measurements, higher order derivatives are set to zero
1106 linear_state_cf.acc.x = 0.0f;
1107 linear_state_cf.acc.y = 0.0f;
1108 linear_state_cf.acc.z = 0.0f;
1112
1115 attitude_state_cf.att_2d.x = 0.0f;
1116 attitude_state_cf.att_2d.y = 0.0f;
1117 attitude_state_cf.att_2d.z = 0.0f;
1121
1125 attitude_ref.att_3d.x = 0.0f;
1126 attitude_ref.att_3d.y = 0.0f;
1127 attitude_ref.att_3d.z = 0.0f;
1128
1130
1132 thrust_ref.thrust_d = 0.0f;
1133
1134 // Reset controller states
1137
1138 // Initial control effectiveness matrix
1140
1141}
1142
1185{
1186 // Recompute gains
1187 // FIXME: Only recompute when parameters change, use parameter update handler callback.
1194
1195 // Fetch linear measurements
1196 struct LinState lin_meas;
1198 (struct FloatVect3 *)stateGetSpeedNed_f()); // From Kalman filter
1199 lin_meas.acc = *stateGetAccelBody_f(); // From accelerometer
1200
1201 // Fetch attitude measurements
1203 attitude_meas.att = *stateGetNedToBodyQuat_f(); // From Kalman filter
1204 attitude_meas.att_d = *stateGetBodyRates_f(); // From gyroscope
1208 rates_prev = attitude_meas.att_d; // Store previous rates for next acceleration calculation
1209
1210 // Propagate and get on board model actuator state estimates
1216
1217 // Get actuator measurements from T4 feedback
1219
1220 // FIXME: Make configurable which source to use for each actuator.
1221 // Choose actuator feedback for elevon and on board model for esc (because lack of rpm control).
1226
1227 // Evaluate On Board Model with previous filtered state estimates
1232
1233 // FIXME: Integral before filtering can cause numerical issues. Update complementary filter to handle this case.
1234 // FIXME: Numerical differentiation to get accelerations can be noisy. Consider using a filter before differentiation.
1235 // Cascaded complementary filter for linear velocity and accelerations measurements
1241
1242 // Cascaded complementary filter for angular rates and accelerations measurements
1249
1250 // Get thrust measurement from on board model
1252
1253 // Reconstructed nu is repurposed to hold modeled moments and specific thrust from the on board model (for obm validation).
1254 // This can be used to compare the on board model prediction to the actual measured acceleration to validate model accuracy.
1255 // Do not compare this to the complementary filter values since these are influenced by the model, use the raw measurements instead.
1256 // nu_reconstructed[0] = angular_accel_obm.x;
1257 // nu_reconstructed[1] = angular_accel_obm.y;
1258 // nu_reconstructed[2] = angular_accel_obm.z;
1259 // nu_reconstructed[3] = thrust_state;
1260
1261 // Get setpoints
1262 if (use_rate_control) {
1264 if (in_flight)
1266 } else {
1268 if (in_flight)
1270 }
1271
1272 // FIXME: Thrust setpoint cant be of type THRUST_INCR_SP, this is not enforced but will silently fail
1275 &thrust_ref);
1276
1277 // Construct pseudo control
1278 struct FloatVect3 nu_attitude;
1279 if (use_rate_control) {
1281 } else {
1283 }
1285
1286 nu_ec[0] = nu_attitude.x;
1287 nu_ec[1] = nu_attitude.y;
1288 nu_ec[2] = nu_attitude.z;
1289 nu_ec[3] = nu_thrust;
1290
1291 // State feedback from on board model
1295
1296 if (in_flight) {
1297 nu_obj[0] = nu_ec[0] - (nu_obm[0] * ANDI_RELAX_OBM);
1298 nu_obj[1] = nu_ec[1] - (nu_obm[1] * ANDI_RELAX_OBM);
1299 nu_obj[2] = nu_ec[2] - (nu_obm[2] * ANDI_RELAX_OBM);
1300 } else {
1301 nu_obj[0] = 0.0f;
1302 nu_obj[1] = 0.0f;
1303 nu_obj[2] = 0.0f;
1304 }
1305 nu_obj[3] = nu_ec[3] - (nu_obm[3] * ANDI_RELAX_OBM);
1306
1307 // Compute control effectiveness matrix based on current states
1309
1310 // Solve control allocation using weighted least squares
1314 float wls_v_scaler[ANDI_OUTPUTS] = {[0 ... ANDI_OUTPUTS - 1] = 1.0f}; // Disable v scaling
1316 du_max); // FIXME: Compute only once in advance for fixed bounds (important for well defined WLS Wu weights)
1317 // compute_wls_v_scaler(wls_v_scaler, nu_obj);
1318
1320 float *bwls[ANDI_OUTPUTS];
1321 // Scale control effectiveness matrix
1322 for (uint8_t i = 0; i < ANDI_OUTPUTS; i++) {
1323 for (uint8_t j = 0; j < ANDI_NUM_ACT; j++) {
1325 }
1326 bwls[i] = ce_mat_scaled[i];
1327 }
1328
1329 // Scale actuator bounds and weights
1330 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
1331 wls_stab_p.u_min[i] = du_min[i] * wls_u_scaler[i];
1332 wls_stab_p.u_max[i] = du_max[i] * wls_u_scaler[i];
1333 wls_stab_p.u_pref[i] = (wls_stab_p.u_min[i] + wls_stab_p.u_max[i]) / 2.0f; // Use mid-point as preferred command
1334 wls_stab_p.Wu[i] = WLS_WU[i];
1335 }
1336
1337 // Scale pseudo control and weights
1338 for (uint8_t i = 0; i < ANDI_OUTPUTS; i++) {
1339 wls_stab_p.v[i] = nu_obj[i] * wls_v_scaler[i];
1340 wls_stab_p.Wv[i] = WLS_WV[i];
1341 }
1342
1343 wls_alloc(&wls_stab_p, bwls, 0, 0, 10);
1344
1345 // Scale back actuator commands
1346 for (uint8_t i = 0; i < ANDI_NUM_ACT; i++) {
1347 du_cmd[i] = (wls_stab_p.u[i] / wls_u_scaler[i]);
1348 u_cmd[i] = du_cmd[i] / ACTUATOR_DYNAMICS[i] + actuator_state[i];
1350 }
1351
1352 // Commit actuator commands
1353 // Resulting commands are in rad for servo and rad/s for motor
1354 // Paparazzi expects the commands in pprz units (-MAX_PPRZ to MAX_PPRZ for servo, 0 to MAX_PPRZ for motor).
1355 // FIXME: Do not hardcode actuator layout
1356 commands[0] = (pprz_t)(u_cmd[0] / ACTUATOR_MAX[0] * MAX_PPRZ);
1357 commands[1] = (pprz_t)(u_cmd[1] / ACTUATOR_MAX[1] * MAX_PPRZ);
1358 commands[2] = (pprz_t)(sqrt(u_cmd[2] / ACTUATOR_MAX[2]) * MAX_PPRZ);
1359 commands[3] = (pprz_t)(sqrt(u_cmd[3] / ACTUATOR_MAX[3]) * MAX_PPRZ);
1360
1361 // Set Thrust command for compatibility with other modules
1362 // FIXME: Do not hardcode actuator layout
1363 cmd[COMMAND_THRUST] = 0;
1364 cmd[COMMAND_THRUST] += (pprz_t)(sqrt(u_cmd[2] / ACTUATOR_MAX[2]) * MAX_PPRZ);
1365 cmd[COMMAND_THRUST] += (pprz_t)(sqrt(u_cmd[3] / ACTUATOR_MAX[3]) * MAX_PPRZ);
1366 cmd[COMMAND_THRUST] /= 2;
1367}
1368
1369// FIXME: The following functions are to integrate the controller in the existing stabilization framework, find a better way to do this or move.
1371{
1372 ;
1373}
1374
1376{
1377 ;
1378}
1379
1380void stabilization_rate_run(bool in_flight __attribute__((unused)),
1381 struct StabilizationSetpoint *rate_sp __attribute__((unused)), struct ThrustSetpoint *thrust __attribute__((unused)),
1382 int32_t *cmd __attribute__((unused)))
1383{
1384 ;
1385}
1386
1387void stabilization_attitude_run(bool in_flight __attribute__((unused)),
1388 struct StabilizationSetpoint *sp __attribute__((unused)), struct ThrustSetpoint *thrust __attribute__((unused)),
1389 int32_t *cmd __attribute__((unused)))
1390{
1391 ;
1392}
1393
1394// FIXME: This function is duplicated in stabilization_rate.c, find a way to share it
1396{
1397 struct FloatRates rate_sp;
1400 rate_sp.p = rc->values[RC_RATE_P] * RC_RATE_MAX[0] / MAX_PPRZ;
1401 }
1403 rate_sp.q = rc->values[RC_RATE_Q] * RC_RATE_MAX[1] / MAX_PPRZ;
1404 }
1406 rate_sp.r = rc->values[RC_RATE_R] * RC_RATE_MAX[2] / MAX_PPRZ;
1407 }
1409}
1410
1411// FIXME: Autopilot end flight detection is not applicable to tailsitters.
1413{
1414 return false;
1415}
1416
1417// DEBUG FUNCTION
1418// static int counter = 0;
1419// /**
1420// * @brief Debug function for actuators.
1421// *
1422// * Send step inputs to actuators and observe responses.
1423// * useful to estimate actuator dynamics.
1424// */
1425// void actuator_debug(bool do_servo_step, bool do_motor_step, float step_rate)
1426// {
1427// if (counter++ > PERIODIC_FREQUENCY * step_rate) {
1428// counter = 0;
1429// }
1430
1431// if (counter <= (PERIODIC_FREQUENCY * step_rate) / 2) {
1432// commands[0] = (pprz_t)(do_servo_step ? MAX_PPRZ : 0);
1433// commands[1] = (pprz_t)(do_servo_step ? MAX_PPRZ : 0);
1434// commands[2] = (pprz_t)(do_motor_step ? MAX_PPRZ : 0);
1435// commands[3] = (pprz_t)(do_motor_step ? MAX_PPRZ : 0);
1436// } else {
1437// commands[0] = (pprz_t)(do_servo_step ? MIN_PPRZ : 0);
1438// commands[1] = (pprz_t)(do_servo_step ? MIN_PPRZ : 0);
1439// commands[2] = (pprz_t)(do_motor_step ? 0 : 0);
1440// commands[3] = (pprz_t)(do_motor_step ? 0 : 0);
1441// }
1442// }
Main include for ABI (AirBorneInterface).
#define ABI_BROADCAST
Broadcast address.
Definition abi_common.h:59
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
Core autopilot interface common to all firmwares.
Hardware independent code for commands handling.
Implementation of complementary filters (first order, second order, and Butterworth variants)
Definitions and inline functions for 1st order complementary filter vector types.
static struct FloatVect3 update_butterworth_2_complementary_vect3(struct Butterworth2ComplementaryVect3 *filter, const struct FloatVect3 *value_x, const struct FloatVect3 *value_y)
Initialize 3D vector of 2nd order Butterworth complementary filters.
static struct FloatRates update_first_order_complementary_rates(struct FirstOrderComplementaryVect3 *filter, const struct FloatRates *value_x, const struct FloatRates *value_y)
Update 3D vector of 1st order complementary filters for rates.
static void reset_first_order_complementary_rates(struct FirstOrderComplementaryVect3 *filter, const struct FloatRates *value)
Reset 3D vector of 1st order complementary filters for rates to a specific value.
static void reset_first_order_complementary_vect3(struct FirstOrderComplementaryVect3 *filter, const struct FloatVect3 *value)
Reset 3D vector of 1st order complementary filters to a specific value.
static void init_butterworth_2_complementary_vect3(struct Butterworth2ComplementaryVect3 *filter, const struct FloatVect3 *cut_off, float sample_time)
Initialize 3D vector of 2nd order Butterworth complementary filters.
static struct FloatVect3 update_first_order_complementary_vect3(struct FirstOrderComplementaryVect3 *filter, const struct FloatVect3 *value_x, const struct FloatVect3 *value_y)
Update 3D vector of 1st order complementary filters.
static struct FloatRates get_first_order_complementary_rates(const struct FirstOrderComplementaryVect3 *filter)
Get current output rates from 1st order complementary filters.
static void reset_butterworth_2_complementary_vect3(struct Butterworth2ComplementaryVect3 *filter, const struct FloatVect3 *value)
Reset 3D vector of 2nd order Butterworth complementary filters to a specific value.
static struct FloatVect3 get_butterworth_2_complementary_vect3(const struct Butterworth2ComplementaryVect3 *filter)
Get current output 3D vector from 2nd order Butterworth complementary filters.
static void init_first_order_complementary_vect3(struct FirstOrderComplementaryVect3 *filter, const struct FloatVect3 *cut_off, float sample_time)
Initialize 3D vector of 1st order complementary filters.
static struct FloatVect3 get_first_order_complementary_vect3(const struct FirstOrderComplementaryVect3 *filter)
Get current output 3D vector from 1st order complementary filters.
3D vector of 2nd order Butterworth complementary filters.
3D vector of 1st order complementary filters.
static struct uart_periph * dev
float q
in rad/s
float p
in rad/s
float r
in rad/s
static void float_quat_normalize(struct FloatQuat *q)
static void float_quat_identity(struct FloatQuat *q)
initialises a quaternion to identity
static void float_vect_zero(float *a, const int n)
a = 0
void float_vect3_integrate_fi(struct FloatVect3 *vec, const struct FloatVect3 *dv, const float dt)
in place first order integration of a 3D-vector
void float_rates_vect3_integrate_fi(struct FloatRates *r, const struct FloatVect3 *dr, const float dt)
in place first order integration of angular rates
void float_quat_integrate(struct FloatQuat *q, const struct FloatRates *omega, const float dt)
in place quaternion integration with constant rotational velocity
#define FLOAT_RATES_ZERO(_r)
void float_quat_inv_comp_norm_shortest(struct FloatQuat *b2c, const struct FloatQuat *a2b, const struct FloatQuat *a2c)
Composition (multiplication) of two quaternions with normalization.
void float_quat_vmult(struct FloatVect3 *v_out, const struct FloatQuat *q, const struct FloatVect3 *v_in)
rotate 3D vector by quaternion.
Roation quaternion.
angular rates
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1302
static struct FloatVect3 * stateGetAccelBody_f(void)
Definition state.h:1100
static struct FloatRates * stateGetBodyRates_f(void)
Get vehicle body angular rate (float).
Definition state.h:1375
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition state.h:1049
Integrated Navigation System interface.
Simple first order low pass filter with bilinear transform.
Definitions and inline functions for 1st order low-pass filter vector types.
A first order low pass filter using Zero Order Hold (ZOH) discretization.
Zero Order Hold (ZOH) discrete first order low pass filter structure.
static void update_first_order_zoh_low_pass_array(const uint8_t n, struct FirstOrderZOHLowPass filter_array[restrict n], const float input_array[restrict n])
Update an array of first order ZOH low-pass filters.
static void init_first_order_zoh_low_pass_array(const uint8_t n, struct FirstOrderZOHLowPass filter_array[restrict n], const float omega[restrict n], const float sample_time)
Initialize a set of first order ZOH low-pass filters to zero for 3D vector data.
static void get_first_order_zoh_low_pass_array(const uint8_t n, const struct FirstOrderZOHLowPass filter_array[restrict n], float output_array[restrict n])
Retrieve the filtered outputs from an array of first order ZOH low-pass filters.
static void reset_first_order_zoh_low_pass_array(const uint8_t n, struct FirstOrderZOHLowPass filter_array[restrict n], const float value_array[restrict n])
Reset an array of first order ZOH low-pass filters to specific values.
uint16_t foo
Definition main_demo5.c:58
Hardware independent API for actuators (servos, motor controllers).
Specific navigation functions for hybrid aircraft.
float evaluate_obm_thrust_z(const float actuator_state[ANDI_NUM_ACT])
Compute total thrust produced by the current actuator state.
struct FloatVect3 evaluate_obm_forces(const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate total force acting on the vehicle from the OBM.
struct FloatVect3 evaluate_obm_moments(const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate total moments acting on the vehicle from the OBM.
void evaluate_obm_f_stb_u(float fu_mat[ANDI_NUM_ACT *ANDI_OUTPUTS], const struct FloatRates *rates, const struct FloatVect3 *vel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate the state-dependent control effectiveness matrix F_u for stabilization.
void evaluate_obm_f_stb_x(float nu_obm[ANDI_OUTPUTS], const struct FloatRates *rates, const struct FloatVect3 *vel_body, const struct FloatVect3 *ang_accel, const struct FloatVect3 *accel_body, const float actuator_state[ANDI_NUM_ACT])
Evaluate the state-dependent contribution F_x * x_dot for stabilization.
struct Gains3rdOrder k_att_rm
float nu[ANDI_OUTPUTS]
float act_max[ANDI_NUM_ACT_TOT]
float act_min[ANDI_NUM_ACT_TOT]
#define ANDI_NUM_ACT
#define ANDI_OUTPUTS
float gains[MAX_SAMPLES_LEARNING]
int16_t pprz_t
Definition paparazzi.h:6
#define MAX_PPRZ
Definition paparazzi.h:8
Paparazzi floating point algebra.
Generic interface for radio control modules.
Rotorcraft navigation functions.
static const ShellCommand commands[]
Definition shell_arch.c:78
struct FloatRates stab_sp_to_rates_f(struct StabilizationSetpoint *sp)
float th_sp_to_thrust_f(struct ThrustSetpoint *th, int32_t thrust, uint8_t axis)
struct StabilizationSetpoint stab_sp_from_rates_f(struct FloatRates *rates)
struct FloatQuat stab_sp_to_quat_f(struct StabilizationSetpoint *sp)
#define THRUST_AXIS_Z
const float ACTUATOR_PREF[ANDI_NUM_ACT]
struct AttQuat attitude_bounds
static float ec_k3_order3_f(const float omega_n, const float zeta, const float omega_a)
float actuator_state[ANDI_NUM_ACT]
const uint8_t ACTUATOR_DELAY[ANDI_NUM_ACT]
void stabilization_attitude_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
Attitude control run function.
struct FirstOrderComplementaryVect3 attitude_rates_cf
float du_max[ANDI_NUM_ACT]
struct PolesOrder2Vect3 andi_p_rate_rm
static float control_error_thrust(const struct ThrustRef *thrust_ref, const float thrust_state, const float k_thrust_ec)
Computes the thrust control command based on desired and current thrust.
float andi_p_thrust_ec
void stabilization_andi_enter(void)
Initializes the ANDI stabilization controller state upon entering stabilization mode.
float andi_p_thrust_rm
static void generate_reference_attitude(float dt, const struct FloatQuat *att_des, const struct GainsOrder3Vect3 *k_att_rm, const struct AttQuat *bounds, struct AttQuat *att_ref)
Generates a bounded second-order reference signal for quaternion-based attitude control.
static void compute_wls_v_scaler(float v_scaler[ANDI_NUM_ACT], const float v[ANDI_NUM_ACT])
Compute output scaling factors for normalizing weighted least squares outputs.
struct GainsOrder3Vect3 andi_k_att_rm
void stabilization_attitude_enter(void)
Attitude control enter function.
static void compute_wls_lower_bounds(float u_d_min[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT], const float act_min[ANDI_NUM_ACT], const float act_rate_min[ANDI_NUM_ACT], const float actuator_bandwidth[ANDI_NUM_ACT])
Compute lower bounds for actuator rate commands based on actuator state and constraints.
struct FloatRates angular_rates_obm
float andi_k_thrust_ec
static float ec_k1_order3_f(const float omega_n, const float zeta, const float omega_a)
const bool ACTUATOR_IS_SERVO[ANDI_NUM_ACT]
static void fetch_actuators_t4(float actuator_meas[ANDI_NUM_ACT], const struct ActuatorsT4In *actuators_t4_in_ptr)
Extract actuator states from ActuatorsT4In struct.
struct LinState linear_state_cf
void stabilization_andi_run(bool use_rate_control, bool in_flight, struct StabilizationSetpoint *stab_setpoint, struct ThrustSetpoint *thrust_setpoint, int32_t *cmd)
Main ANDI stabilization control loop.
float actuator_state_lpf[ANDI_NUM_ACT]
static struct GainsOrder2Vect3 compute_reference_gains_order_2_vect_3(const struct PolesOrder2Vect3 *poles)
Compute reference-model gains for a 2nd-order 3D system.
void stabilization_rate_enter(void)
struct PolesOrder3Vect3 andi_p_att_ec
static float rm_k1_order2_f(const float omega_a, const float zeta)
struct StabilizationSetpoint stabilization_rate_read_rc(struct RadioControl *rc)
static void generate_reference_thrust(float dt, float thrust_des, const float k_thrust_rm, const struct ThrustRef *bounds_min, const struct ThrustRef *bounds_max, struct ThrustRef *thrust_ref)
Generates a bounded second-order reference signal for thrust control.
static struct GainsOrder3Vect3 compute_error_gains_order_3_vect_3(const struct PolesOrder3Vect3 *poles)
Compute error-compensation gains for a 3rd-order 3D system.
struct PolesOrder2Vect3 andi_p_rate_ec
const float THRUST_MIN
struct FirstOrderComplementaryVect3 linear_vel_cf
struct FloatRates rates_des
struct GainsOrder3Vect3 andi_k_att_ec
struct Butterworth2ComplementaryVect3 linear_accel_cf
float nu_ec[ANDI_OUTPUTS]
static void generate_reference_rate(float dt, const struct FloatRates *rate_des, const struct GainsOrder2Vect3 *k_rate_rm, const struct AttQuat *bounds, struct AttQuat *att_ref)
Generates a bounded second-order reference signal for attitude rate control.
float u_cmd[ANDI_NUM_ACT]
struct WLS_t wls_stab_p
static void send_wls_u_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
void stabilization_rate_run(bool in_flight, struct StabilizationSetpoint *rate_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
void stabilization_andi_init(void)
struct ActuatorsT4In actuators_t4_obs
const float RC_RATE_MAX[ANDI_OUTPUTS]
const bool USE_STATE_DYNAMICS
static struct GainsOrder2Vect3 compute_error_gains_order_2_vect_3(const struct PolesOrder2Vect3 *poles)
Compute error-compensation gains for a 2nd-order 3D system.
struct Butterworth2ComplementaryVect3 attitude_accel_cf
static struct FloatVect3 control_error_attitude(const struct AttQuat *att_ref, const struct AttStateQuat *att_state, const struct GainsOrder3Vect3 *k_att_ec)
Computes the attitude rate error control command.
const float WLS_WV[ANDI_OUTPUTS]
struct ThrustRef thrust_ref
static void send_eff_mat_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
static float rm_k2_order3_f(const float omega_n, const float zeta, const float omega_a)
float nu_obm[ANDI_OUTPUTS]
static float rm_k1_order3_f(const float omega_n, const float zeta, const float omega_a)
static void actuators_t4_in_callback(uint8_t sender_id, struct ActuatorsT4In *actuators_t4_in_ptr, float *actuators_t4_extra_data_in_ptr)
Callback function to handle incoming actuator telemetry data.
static struct FloatVect3 control_error_rate(const struct AttQuat *att_ref, const struct AttStateQuat *att_state, const struct GainsOrder2Vect3 *k_rate_ec)
Computes the control error command for attitude rate regulation.
struct ThrustRef thrust_bounds_max
float nu_obj[ANDI_OUTPUTS]
struct FloatRates rates_prev
static void send_stab_attitude_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
struct AttStateQuat attitude_state_cf
struct FloatVect3 linear_velocity_obm
float actuator_meas[ANDI_NUM_ACT]
struct PolesOrder3Vect3 andi_p_att_rm
struct TransportDelay actuator_obm_delay[ANDI_NUM_ACT]
struct FirstOrderZOHLowPass actuator_obm_zohlpf[ANDI_NUM_ACT]
struct AttQuat attitude_ref
float andi_k_thrust_rm
float WLS_WU[ANDI_NUM_ACT]
Normalized actuator cost for WLS allocation.
static float rm_k2_order2_f(const float omega_a, const float zeta)
static float ec_k1_order2_f(const float omega_a, const float zeta)
abi_event actuators_t4_in_event
static void send_wls_v_stabilization_andi(struct transport_tx *trans, struct link_device *dev)
float thrust_des
static float ec_k2_order3_f(const float omega_n, const float zeta, const float omega_a)
const bool SCHEDULE_EFF
bool autopilot_in_flight_end_detection(bool motors_on)
float du_min[ANDI_NUM_ACT]
struct ThrustRef thrust_bounds_min
static void compute_wls_u_scaler(float u_scaler[ANDI_NUM_ACT], const float act_min[ANDI_NUM_ACT], const float act_max[ANDI_NUM_ACT])
Compute input scaling factors for normalizing weighted least squares.
static float ec_k2_order2_f(const float omega_a, const float zeta)
const float ANDI_RELAX_OBM
float du_cmd[ANDI_NUM_ACT]
struct FloatQuat attitude_des
struct GainsOrder2Vect3 andi_k_rate_ec
static void compute_wls_upper_bounds(float u_d_max[ANDI_NUM_ACT], const float act_state[ANDI_NUM_ACT], const float act_max[ANDI_NUM_ACT], const float act_rate_max[ANDI_NUM_ACT], const float actuator_bandwidth[ANDI_NUM_ACT])
Compute upper bounds for actuator rate commands based on actuator state and constraints.
float ce_mat[ANDI_NUM_ACT *ANDI_OUTPUTS]
static struct GainsOrder3Vect3 compute_reference_gains_order_3_vect_3(const struct PolesOrder3Vect3 *poles)
Compute reference-model gains for a 3rd-order 3D system.
struct GainsOrder2Vect3 andi_k_rate_rm
static float rm_k3_order3_f(const float omega_n, const float zeta, const float omega_a)
float thrust_state
ANDI stabilization controller for tiltbody rotorcraft.
struct FloatRates att_d
struct FloatVect3 k1
struct FloatVect3 vel
struct FloatQuat att
struct FloatVect3 acc
struct FloatVect3 att_2d
struct FloatQuat att
struct FloatRates att_d
struct FloatVect3 omega_a
struct FloatVect3 omega_n
struct FloatVect3 att_3d
struct FloatVect3 att_2d
struct FloatVect3 k1
Structure representing attitude in quaternion form along with its first three derivatives,...
Structure representing attitude in quaternion form along with its first two derivatives,...
Structure defining second-order gain parameters for vectorized 3D quantities.
Structure defining third-order gain parameters for vectorized 3D quantities.
Structure representing linear state with velocity and acceleration vectors.
Structure defining second-order pole parameters for vectorized 3D quantities.
Structure defining third-order pole parameters for vectorized 3D quantities.
Structure representing (specific) thrust reference and its derivative.
Read an attitude setpoint from the RC.
static struct FloatRates att_state
#define RC_RATE_R
#define RC_RATE_Q
#define YAW_RATE_DEADBAND_EXCEEDED(_rc)
#define RC_RATE_P
#define ROLL_RATE_DEADBAND_EXCEEDED(_rc)
#define PITCH_RATE_DEADBAND_EXCEEDED(_rc)
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...
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
Transport delay filter implementation.
Transport delay filter type definitions and array operations.
static void reset_transport_delay_array(const uint8_t n, struct TransportDelay td_array[restrict n], const float initial_value[restrict n])
Reset an array of TransportDelay structures to specific initial values.
static void update_transport_delay_array(uint8_t n, struct TransportDelay td_array[restrict n], const float input_array[restrict n])
Update an array of TransportDelay structures with input values.
static void get_transport_delay_array(const uint8_t n, const struct TransportDelay td_array[restrict n], float output_array[restrict n])
Get output values from an array of TransportDelay structures.
static void init_transport_delay_array(uint8_t n, struct TransportDelay td_array[restrict n], const uint8_t delay_samples[restrict n], float initial_value[restrict n])
Initialize an array of TransportDelay structures.
int int32_t
Typedef defining 32 bit int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
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
float gamma_sq
Definition wls_alloc.h:69
float u[WLS_N_U_MAX]
Definition wls_alloc.h:71
int iter
Definition wls_alloc.h:79
float u_min[WLS_N_U_MAX]
Definition wls_alloc.h:75
float Wu[WLS_N_U_MAX]
Definition wls_alloc.h:73
float u_max[WLS_N_U_MAX]
Definition wls_alloc.h:76
float u_pref[WLS_N_U_MAX]
Definition wls_alloc.h:74
float Wv[WLS_N_V_MAX]
Definition wls_alloc.h:72
float v[WLS_N_V_MAX]
Definition wls_alloc.h:70
int nu
Definition wls_alloc.h:67