Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
stabilization_indi.c
Go to the documentation of this file.
1/*
2 * Copyright (C) Ewoud Smeur <ewoud_smeur@msn.com>
3 * MAVLab Delft University of Technology
4 *
5 * This file is part of paparazzi.
6 *
7 * paparazzi is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * paparazzi is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with paparazzi; see the file COPYING. If not, write to
19 * the Free Software Foundation, 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
36
38#include "state.h"
39#include "generated/airframe.h"
42#include "modules/core/abi.h"
44#include "math/wls/wls_alloc.h"
45#include <stdio.h>
46
47// Factor that the estimated G matrix is allowed to deviate from initial one
48#define INDI_ALLOWED_G_FACTOR 2.0
49
50#ifdef STABILIZATION_INDI_FILT_CUTOFF_P
51#define STABILIZATION_INDI_FILTER_ROLL_RATE TRUE
52#else
53#define STABILIZATION_INDI_FILT_CUTOFF_P 20.0
54#endif
55
56#ifdef STABILIZATION_INDI_FILT_CUTOFF_Q
57#define STABILIZATION_INDI_FILTER_PITCH_RATE TRUE
58#else
59#define STABILIZATION_INDI_FILT_CUTOFF_Q 20.0
60#endif
61
62#ifdef STABILIZATION_INDI_FILT_CUTOFF_R
63#define STABILIZATION_INDI_FILTER_YAW_RATE TRUE
64#else
65#define STABILIZATION_INDI_FILT_CUTOFF_R 20.0
66#endif
67
68// Default is WLS
69#ifndef STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
70#define STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE FALSE
71#endif
72
73#ifndef STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
74#define STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER FALSE
75#endif
76
77// Airspeed [m/s] at which the forward flight throttle limit is used instead of
78// the hover throttle limit.
79#ifndef STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
80#define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD 8.0
81#endif
82
83#if INDI_OUTPUTS > 4
84#ifndef STABILIZATION_INDI_G1_THRUST_X
85#error "You must define STABILIZATION_INDI_G1_THRUST_X for your number of INDI_OUTPUTS"
86#endif
87#endif
88
89#ifdef SetCommandsFromRC
90#warning SetCommandsFromRC not used: STAB_INDI writes actuators directly
91#endif
92
93#ifdef SetAutoCommandsFromRC
94#warning SetAutoCommandsFromRC not used: STAB_INDI writes actuators directly
95#endif
96
97
98#if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
99#if INDI_NUM_ACT > WLS_N_U_MAX
100#error Matrix-WLS_N_U_MAX too small or not defined: define WLS_N_U_MAX >= INDI_NUM_ACT in airframe file
101#endif
102#if INDI_OUTPUTS > WLS_N_V_MAX
103#error Matrix-WLS_N_V_MAX too small or not defined: define WLS_N_V_MAX >= INDI_OUTPUTS in airframe file
104#endif
106 .nu = INDI_NUM_ACT,
107 .nv = INDI_OUTPUTS,
108 .gamma_sq = 10000.0,
109 .v = {0.0},
110#ifdef STABILIZATION_INDI_WLS_PRIORITIES
112#else //State prioritization {W Roll, W pitch, W yaw, TOTAL THRUST}
113#if INDI_OUTPUTS == 5
114 .Wv = {1000, 1000, 1, 100, 100},
115#else
116 .Wv = {1000, 1000, 1, 100},
117#endif
118#endif
119#ifdef STABILIZATION_INDI_WLS_WU //Weighting of different actuators in the cost function
121#else
122 .Wu = {[0 ... INDI_NUM_ACT - 1] = 1.0},
123#endif
124 .u_pref = {0.0},
125 .u_min = {0.0},
126 .u_max = {0.0},
127 .PC = 0.0,
128 .SC = 0.0,
129 .iter = 0
130};
131#endif
134
135static void lms_estimation(void);
136static void get_actuator_state(void);
137static void calc_g1_element(float dx_error, int8_t i, int8_t j, float mu_extra);
138static void calc_g2_element(float dx_error, int8_t j, float mu_extra);
139#if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
140static void calc_g1g2_pseudo_inv(void);
141#endif
142static void bound_g_mat(void);
143
157
158#if STABILIZATION_INDI_USE_ADAPTIVE
159bool indi_use_adaptive = true;
160#else
161bool indi_use_adaptive = false;
162#endif
163
164#ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
166#endif
167
168#ifdef STABILIZATION_INDI_ACT_IS_SERVO
170#else
172#endif
173
174#ifdef STABILIZATION_INDI_ACT_IS_THRUSTER_X
176#else
178#endif
179
181
182#ifdef STABILIZATION_INDI_ACT_PREF
183// Preferred (neutral, least energy) actuator value
185#else
186// Assume 0 is neutral
187float act_pref[INDI_NUM_ACT] = {0.0};
188#endif
189
190#ifdef STABILIZATION_INDI_ACT_DYN
191#warning STABILIZATION_INDI_ACT_DYN is deprecated, use STABILIZATION_INDI_ACT_FREQ instead.
192#warning You now have to define the continuous time corner frequency in rad/s of the actuators.
193#warning "Use -ln(1 - old_number) * PERIODIC_FREQUENCY to compute it from the old values."
195#else
197float act_dyn_discrete[INDI_NUM_ACT]; // will be computed from freq at init
198#endif
199
203#ifdef STABILIZATION_INDI_YAW_DISTURBANCE_LIMIT
205#else // Put a rediculously high limit
207#endif
208
209// variables needed for control
211struct FloatRates angular_accel_ref = {0., 0., 0.};
212struct FloatRates angular_rate_ref = {0., 0., 0.};
213float angular_acceleration[3] = {0., 0., 0.};
216
217float q_filt = 0.0;
218float r_filt = 0.0;
219
220float stabilization_indi_filter_freq = 20.0; //Hz, for setting handler
221
222// variables needed for estimation
231
232// The learning rate per axis (roll, pitch, yaw, thrust)
233float mu1[INDI_OUTPUTS] = {0.00001, 0.00001, 0.000003, 0.000002};
234// The learning rate for the propeller inertia (scaled by 512 wrt mu1)
235float mu2 = 0.002;
236
237// other variables
239
240// Number of actuators used to provide thrust
243
246
247// Register actuator feedback if we rely on RPM information
248#if STABILIZATION_INDI_RPM_FEEDBACK
249#ifndef STABILIZATION_INDI_ACT_FEEDBACK_ID
250#define STABILIZATION_INDI_ACT_FEEDBACK_ID ABI_BROADCAST
251#endif
253
255static void act_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback, uint8_t num_act);
256PRINT_CONFIG_MSG("STABILIZATION_INDI_RPM_FEEDBACK")
257#endif
258
260float g2[INDI_NUM_ACT] = STABILIZATION_INDI_G2; //scaled by INDI_G_SCALING
261#ifdef STABILIZATION_INDI_G1
263#else // old defines TODO remove
264#if INDI_OUTPUTS == 5
268 };
269#else
273#endif
274#endif
275
281
288#if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
290#else
292#endif
294
295void init_filters(void);
296void sum_g1_g2(void);
297
298#if PERIODIC_TELEMETRY
300#if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
301static void send_wls_v_stab(struct transport_tx *trans, struct link_device *dev)
302{
303 send_wls_v("stab", &wls_stab_p, trans, dev);
304}
305static void send_wls_u_stab(struct transport_tx *trans, struct link_device *dev)
306{
307 send_wls_u("stab", &wls_stab_p, trans, dev);
308}
309#endif
310static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
311{
313 INDI_NUM_ACT, g1g2[0],
314 INDI_NUM_ACT, g1g2[1],
315 INDI_NUM_ACT, g1g2[2],
316 INDI_NUM_ACT, g1g2[3],
318}
319
320static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
321{
322 struct Int32Quat *quat = stateGetNedToBodyQuat_i();
328 &(quat->qi),
329 &(quat->qx),
330 &(quat->qy),
331 &(quat->qz));
332}
333
334static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
335{
336 float zero = 0.0;
338 struct FloatEulers att, att_sp;
339#if GUIDANCE_INDI_HYBRID
344#else
347#endif
348 float temp_att[3] = {att.phi, att.theta, att.psi};
349 float temp_att_ref[3] = {att_sp.phi, att_sp.theta, att_sp.psi};
350 float temp_rate[3] = {body_rates->p, body_rates->q, body_rates->r};
354 1, &zero, // att des
355 3, temp_att, // att
356 3, temp_att_ref, // att ref
357 3, temp_rate, // rate
358 3, temp_rate_ref, // rate ref
359 3, angular_acceleration, // ang.acc = rate.diff
360 3, temp_ang_acc_ref, // ang.acc.ref
361 1, &zero, // jerk ref
362 1, &zero); // u
363}
364#endif
365
370{
371 // Initialize filters
372 init_filters();
373
374 int8_t i;
375// If the deprecated STABILIZATION_INDI_ACT_DYN is used, convert it to the new FREQUENCY format
376#ifdef STABILIZATION_INDI_ACT_FREQ
377 // Initialize the array of pointers to the rows of g1g2
378 for (i = 0; i < INDI_NUM_ACT; i++) {
380 }
381#endif
382
383#if STABILIZATION_INDI_RPM_FEEDBACK
385#endif
386
392
393 //Calculate G1G2
394 sum_g1_g2();
395
396 // Do not compute if not needed
397#if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
398 //Calculate G1G2_PSEUDO_INVERSE
400#endif
401
402 // Initialize the array of pointers to the rows of g1g2
403 for (i = 0; i < INDI_OUTPUTS; i++) {
404 Bwls[i] = g1g2[i];
405 }
406
407 // Initialize the estimator matrices
410 // Remember the initial matrices
413
414 // Assume all non-servos are delivering thrust
416 num_thrusters_x = 0;
417 for (i = 0; i < INDI_NUM_ACT; i++) {
420
422
424 }
425
426#if PERIODIC_TELEMETRY
430 #if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
433 #endif
434#endif
435}
436
450
466
470void init_filters(void)
471{
472 // tau = 1/(2*pi*Fc)
473 float tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF);
475 float sample_time = 1.0 / PERIODIC_FREQUENCY;
476 // Filtering of the gyroscope
477 int8_t i;
478 for (i = 0; i < 3; i++) {
481 }
482
483 // Filtering of the actuators
484 for (i = 0; i < INDI_NUM_ACT; i++) {
487 }
488
489 // Filtering the bodyx acceleration with same cutoff as gyroscope
491
492 // Filtering of the accel body z
494
495#if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
496 tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P);
498 tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q);
500 tau = 1.0 / (2.0 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R);
502#else
503 // Init rate filter for feedback
505
509#endif
510}
511
520void stabilization_indi_rate_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
521{
522
523 // Propagate actuator filters
526 for (int i = 0; i < INDI_NUM_ACT; i++) {
531
532 // calculate derivatives for estimation
537 }
538
539 // Use the last actuator state for this computation
541
542 // Predict angular acceleration u*B
546
547 /* Propagate the filter on the gyroscopes */
549 float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
550
551 // Get the acceleration in body axes
552 struct Int32Vect3 *body_accel_i;
553 body_accel_i = stateGetAccelBody_i();
554 ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
555
556 int8_t i;
557 for (i = 0; i < 3; i++) {
560
562
563 //Calculate the angular acceleration via finite difference
566
567 // Calculate derivatives for estimation
572 }
573
574 // subtract u*B from angular acceleration
577
578 if (in_flight) {
579 // Limit the estimated disturbance in yaw for drones that are stable in sideslip
581 } else {
582 // Not in flight, so don't estimate disturbance
584 }
585
586 //The rates used for feedback are by default the measured rates.
587 //If there is a lot of noise on the gyroscope, it might be good to use the filtered value for feedback.
588 //Note that due to the delay, the PD controller may need relaxed gains.
589 struct FloatRates rates_filt;
590#if STABILIZATION_INDI_FILTER_ROLL_RATE
591#if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
593#else
595#endif
596#else
597 rates_filt.p = body_rates->p;
598#endif
599#if STABILIZATION_INDI_FILTER_PITCH_RATE
600#if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
602#else
604#endif
605#else
606 rates_filt.q = body_rates->q;
607#endif
608#if STABILIZATION_INDI_FILTER_YAW_RATE
609#if STABILIZATION_INDI_FILTER_RATES_SECOND_ORDER
611#else
613#endif
614#else
615 rates_filt.r = body_rates->r;
616#endif
617
618 // calculate the virtual control (reference acceleration) based on a PD controller
623
624 // compute virtual thrust
625 struct FloatVect3 v_thrust = { 0.f, 0.f, 0.f };
626 if (thrust->type == THRUST_INCR_SP) {
628 v_thrust.y = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Y);
629 v_thrust.z = th_sp_to_incr_f(thrust, 0, THRUST_AXIS_Z);
630
631 // Compute estimated thrust
632 struct FloatVect3 thrust_filt = { 0.f, 0.f, 0.f };
633 for (i = 0; i < INDI_NUM_ACT; i++) {
635#if INDI_OUTPUTS == 5
637#endif
638 }
639 // Add the current estimated thrust to the increment
641 } else {
642 // build incremental thrust
643 float th_cmd_z = (float)th_sp_to_thrust_i(thrust, 0, THRUST_AXIS_Z);
644 for (i = 0; i < INDI_NUM_ACT; i++) {
645 v_thrust.z += th_cmd_z * Bwls[3][i];
646#if INDI_OUTPUTS == 5
647 // TODO set X thrust from RC in the thrust input setpoint
649 v_thrust.x += cmd[COMMAND_THRUST_X] * Bwls[4][i];
650#endif
651 }
652 v_thrust.y = 0.f;
653 }
654
655 // This term compensates for the spinup torque in the yaw axis
657
658 if (in_flight) {
659 // Limit the estimated disturbance in yaw for drones that are stable in sideslip
661 } else {
662 // Not in flight, so don't estimate disturbance
664 }
665
666 // The control objective in array format
670 indi_v[3] = v_thrust.z;
671#if INDI_OUTPUTS == 5
672 indi_v[4] = v_thrust.x;
673#endif
674
675#if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
676 // Calculate the increment for each actuator
677 for (i = 0; i < INDI_NUM_ACT; i++) {
678 indi_u[i] = (g1g2_pseudo_inv[i][0] * indi_v[0])
679 + (g1g2_pseudo_inv[i][1] * indi_v[1])
680 + (g1g2_pseudo_inv[i][2] * indi_v[2])
681 + (g1g2_pseudo_inv[i][3] * indi_v[3]);
682 }
683#else
685
686 // WLS Control Allocator
687 for (i = 0; i < INDI_OUTPUTS; i++) {
688 wls_stab_p.v[i] = indi_v[i];
689 }
690 wls_alloc(&wls_stab_p, Bwls, 0, 0, 10);
691 for (i = 0; i < INDI_NUM_ACT; i++) {
692 indi_u [i] = wls_stab_p.u[i];
693 }
694#endif
695
696 // Bound the inputs to the actuators
697 for (i = 0; i < INDI_NUM_ACT; i++) {
698 if (act_is_servo[i]) {
700 } else {
702 Bound(indi_u[i], 0, MAX_PPRZ);
703 } else {
704 indi_u[i] = -MAX_PPRZ;
705 }
706 }
707 }
708
709 // Use online effectiveness estimation only when flying
710 if (in_flight && indi_use_adaptive) {
712 }
713
714 /*Commit the actuator command*/
715 for (i = 0; i < INDI_NUM_ACT; i++) {
716 actuators_pprz[i] = (int16_t) indi_u[i];
717 }
718
719 //update thrust command such that the current is correctly estimated
720 cmd[COMMAND_THRUST] = 0;
721 for (i = 0; i < INDI_NUM_ACT; i++) {
723 }
725
726}
727
731#if !STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
733{
734 // Calculate the min and max increments
735 for (uint8_t i = 0; i < INDI_NUM_ACT; i++) {
738 wls_stab_p.u_pref[i] = act_pref[i];
739
740#ifdef GUIDANCE_INDI_MIN_THROTTLE
741 float airspeed = stateGetAirspeed_f();
742 //limit minimum thrust ap can give
743 if (!act_is_servo[i]) {
747 } else {
749 }
750 }
751 }
752#endif
753 }
754}
755#endif
756
765void stabilization_indi_attitude_run(bool in_flight, struct StabilizationSetpoint *att_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
766{
767 stab_att_sp_euler = stab_sp_to_eulers_i(att_sp); // stab_att_sp_euler.psi still used in ref..
768 stab_att_sp_quat = stab_sp_to_quat_i(att_sp); // quat attitude setpoint
769
770 /* attitude error in float */
771 struct FloatQuat att_err;
774
776
777 struct FloatVect3 att_fb;
778#if TILT_TWIST_CTRL
779 struct FloatQuat tilt;
780 struct FloatQuat twist;
782 att_fb.x = tilt.qx;
783 att_fb.y = tilt.qy;
784 att_fb.z = twist.qz;
785#else
786 att_fb.x = att_err.qx;
787 att_fb.y = att_err.qy;
788 att_fb.z = att_err.qz;
789#endif
790
791 // local variable to compute rate setpoints based on attitude error
792 struct FloatRates rate_sp;
793 // calculate the virtual control (reference acceleration) based on a PD controller
797
798 // Add feed-forward rates to the attitude feedback part
801
802 // Store for telemetry
806
807 // Possibly we can use some bounding here
808 /*BoundAbs(rate_sp.r, 5.0);*/
809
810 /* compute the INDI command */
812 stabilization_indi_rate_run(in_flight, &sp, thrust, cmd);
813}
814
822{
823#if STABILIZATION_INDI_RPM_FEEDBACK
825#else
826 //actuator dynamics
827 int8_t i;
829 for (i = 0; i < INDI_NUM_ACT; i++) {
831
833 + act_dyn_discrete[i] * (indi_u[i] - actuator_state[i]);
834
835#ifdef STABILIZATION_INDI_ACT_RATE_LIMIT
838 } else if ((actuator_state[i] - prev_actuator_state) < -act_rate_limit[i]) {
840 }
841#endif
842 }
843
844#endif
845}
846
858{
859 g1_est[i][j] = g1_est[i][j] - du_estimation[j] * mu * ddx_error;
860}
861
872{
874}
875
882{
883
884 // Get the acceleration in body axes
885 struct Int32Vect3 *body_accel_i;
886 body_accel_i = stateGetAccelBody_i();
887 ACCELS_FLOAT_OF_BFP(body_accel_f, *body_accel_i);
888
889 // Filter the acceleration in z axis
891
892 // Calculate the derivative of the acceleration via finite difference
895
896 // Use xml setting for adaptive mu for lms
897 // Set default value if not defined
898#ifndef STABILIZATION_INDI_ADAPTIVE_MU
899 float adaptive_mu_lr = 0.001;
900#else
902#endif
903
904 // scale the inputs to avoid numerical errors
907
909
910 //Estimation of G
911 // TODO: only estimate when du_norm2 is large enough (enough input)
912 /*float du_norm2 = du_estimation[0]*du_estimation[0] + du_estimation[1]*du_estimation[1] +du_estimation[2]*du_estimation[2] + du_estimation[3]*du_estimation[3];*/
913 int8_t i;
914 for (i = 0; i < INDI_OUTPUTS; i++) {
915 // Calculate the error between prediction and measurement
916 float ddx_error = - ddx_estimation[i];
917 int8_t j;
918 for (j = 0; j < INDI_NUM_ACT; j++) {
919 ddx_error += g1_est[i][j] * du_estimation[j];
920 if (i == 2) {
921 // Changing the momentum of the rotors gives a counter torque
923 }
924 }
925
926 // when doing the yaw axis, also use G2
927 if (i == 2) {
928 for (j = 0; j < INDI_NUM_ACT; j++) {
930 }
931 } else if (i == 3) {
932 // If the acceleration change is very large (rough landing), don't adapt
933 if (fabs(indi_accel_d) > 60.0) {
934 ddx_error = 0.0;
935 }
936 }
937
938 // Calculate the row of the G1 matrix corresponding to this axis
939 for (j = 0; j < INDI_NUM_ACT; j++) {
941 }
942 }
943
944 bound_g_mat();
945
946 // Save the calculated matrix to G1 and G2
947 // until thrust is included, first part of the array
950
951 // Calculate sum of G1 and G2 for Bwls
952 sum_g1_g2();
953
954#if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
955 // Calculate the inverse of (G1+G2)
957#endif
958}
959
964void sum_g1_g2(void)
965{
966 int8_t i;
967 int8_t j;
968 for (i = 0; i < INDI_OUTPUTS; i++) {
969 for (j = 0; j < INDI_NUM_ACT; j++) {
970 if (i != 2) {
971 g1g2[i][j] = g1[i][j] / INDI_G_SCALING;
972 } else {
973 g1g2[i][j] = (g1[i][j] + g2[j]) / INDI_G_SCALING;
974 }
975 }
976 }
977}
978
979#if STABILIZATION_INDI_ALLOCATION_PSEUDO_INVERSE
984void calc_g1g2_pseudo_inv(void)
985{
986 //G1G2*transpose(G1G2)
987 //calculate matrix multiplication of its transpose INDI_OUTPUTSxnum_act x num_actxINDI_OUTPUTS
988 float element = 0;
989 int8_t row;
990 int8_t col;
991 int8_t i;
992 for (row = 0; row < INDI_OUTPUTS; row++) {
993 for (col = 0; col < INDI_OUTPUTS; col++) {
994 element = 0;
995 for (i = 0; i < INDI_NUM_ACT; i++) {
996 element = element + g1g2[row][i] * g1g2[col][i];
997 }
998 g1g2_trans_mult[row][col] = element;
999 }
1000 }
1001
1002 //there are numerical errors if the scaling is not right.
1004
1005 //inverse of 4x4 matrix
1007
1008 //scale back
1010
1011 //G1G2'*G1G2inv
1012 //calculate matrix multiplication INDI_NUM_ACTxINDI_OUTPUTS x INDI_OUTPUTSxINDI_OUTPUTS
1013 for (row = 0; row < INDI_NUM_ACT; row++) {
1014 for (col = 0; col < INDI_OUTPUTS; col++) {
1015 element = 0;
1016 for (i = 0; i < INDI_OUTPUTS; i++) {
1017 element = element + g1g2[i][row] * g1g2inv[col][i];
1018 }
1019 g1g2_pseudo_inv[row][col] = element;
1020 }
1021 }
1022}
1023#endif
1024
1025#if STABILIZATION_INDI_RPM_FEEDBACK
1027{
1028 int8_t i;
1029 for (i = 0; i < num_act; i++) {
1030 // Sanity check that index is valid
1031 if (feedback[i].idx < INDI_NUM_ACT && feedback[i].set.rpm) {
1032 int8_t idx = feedback[i].idx;
1033 act_obs[idx] = (feedback[i].rpm - get_servo_min(idx));
1035 Bound(act_obs[idx], 0, MAX_PPRZ);
1036 }
1037 }
1038}
1039#endif
1040
1041static void bound_g_mat(void)
1042{
1043 int8_t i;
1044 int8_t j;
1045 for (j = 0; j < INDI_NUM_ACT; j++) {
1046 float max_limit;
1047 float min_limit;
1048
1049 // Limit the values of the estimated G1 matrix
1050 for (i = 0; i < INDI_OUTPUTS; i++) {
1051 if (g1_init[i][j] > 0.0) {
1054 } else {
1057 }
1058
1059 if (g1_est[i][j] > max_limit) {
1060 g1_est[i][j] = max_limit;
1061 }
1062 if (g1_est[i][j] < min_limit) {
1063 g1_est[i][j] = min_limit;
1064 }
1065 }
1066
1067 // Do the same for the G2 matrix
1068 if (g2_init[j] > 0.0) {
1071 } else {
1074 }
1075
1076 if (g2_est[j] > max_limit) {
1077 g2_est[j] = max_limit;
1078 }
1079 if (g2_est[j] < min_limit) {
1080 g2_est[j] = min_limit;
1081 }
1082 }
1083}
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:67
bool autopilot_get_motors_on(void)
get motors status
Definition autopilot.c:295
#define UNUSED(x)
float q
in rad/s
float phi
in radians
float p
in rad/s
float r
in rad/s
float theta
in radians
float psi
in radians
static void float_vect_zero(float *a, const int n)
a = 0
void float_quat_inv_comp_norm_shortest(struct FloatQuat *b2c, struct FloatQuat *a2b, struct FloatQuat *a2c)
Composition (multiplication) of two quaternions with normalization.
static void float_vect_smul(float *o, const float *a, const float s, const int n)
o = a * s
static void float_mat_vect_mul(float *o, float **a, float *b, int m, int n)
o = a * b
static void float_vect_scale(float *a, const float s, const int n)
a *= s
static float float_vect_dot_product(const float *a, const float *b, const int n)
a.b
static void float_vect_copy(float *a, const float *b, const int n)
a = b
void float_eulers_of_quat_zxy(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'ZXY' This rotation order is useful if you need 90 deg pitch
static void float_vect_diff(float *o, const float *a, const float *b, const int n)
o = a - b
void float_quat_tilt_twist(struct FloatQuat *tilt, struct FloatQuat *twist, struct FloatQuat *quat)
Tilt twist decomposition of a quaternion (z axis)
bool float_mat_inv_4d(float invOut[4][4], float mat_in[4][4])
4x4 Matrix inverse
euler angles
Roation quaternion.
angular rates
#define RATES_ADD(_a, _b)
#define QUAT_FLOAT_OF_BFP(_qf, _qi)
#define VECT3_ADD(_a, _b)
#define EULERS_FLOAT_OF_BFP(_ef, _ei)
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
euler angles
Rotation quaternion.
static struct Int32Quat * stateGetNedToBodyQuat_i(void)
Get vehicle body attitude quaternion (int).
Definition state.h:1276
static struct FloatEulers * stateGetNedToBodyEulers_f(void)
Get vehicle body attitude euler angles (float).
Definition state.h:1306
static struct FloatQuat * stateGetNedToBodyQuat_f(void)
Get vehicle body attitude quaternion (float).
Definition state.h:1294
static struct FloatRates * stateGetBodyRates_f(void)
Get vehicle body angular rate (float).
Definition state.h:1367
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:1590
Butterworth2LowPass thrust_filt
static float p[2][2]
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
Simple first order low pass filter with bilinear transform.
float o[2]
output history
static float update_first_order_low_pass(struct FirstOrderLowPass *filter, float value)
Update first order low pass filter state with a new value.
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
static void init_first_order_low_pass(struct FirstOrderLowPass *filter, float tau, float sample_time, float value)
Init first order low pass filter.
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
First order low pass filter structure.
Second order low pass filter structure.
uint16_t foo
Definition main_demo5.c:58
Hardware independent API for actuators (servos, motor controllers).
int32_t rpm
RPM.
Definition actuators.h:51
uint8_t idx
General index of the actuators (generated in airframe.h)
Definition actuators.h:45
static float mu
Physical model parameters.
static uint32_t idx
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
#define MAX_PPRZ
Definition paparazzi.h:8
static abi_event act_feedback_ev
Paparazzi floating point algebra.
struct RadioControl radio_control
Generic interface for radio control modules.
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
struct HorizontalGuidance guidance_h
Definition guidance_h.c:45
#define GUIDANCE_H_MODE_NAV
Definition guidance_h.h:58
#define GUIDANCE_H_MODE_HOVER
Definition guidance_h.h:57
struct FloatRates stab_sp_to_rates_f(struct StabilizationSetpoint *sp)
float th_sp_to_incr_f(struct ThrustSetpoint *th, int32_t thrust, uint8_t axis)
struct Int32Quat stab_sp_to_quat_i(struct StabilizationSetpoint *sp)
struct Int32Eulers stab_sp_to_eulers_i(struct StabilizationSetpoint *sp)
struct StabilizationSetpoint stab_sp_from_rates_f(struct FloatRates *rates)
struct FloatQuat stab_sp_to_quat_f(struct StabilizationSetpoint *sp)
int32_t th_sp_to_thrust_i(struct ThrustSetpoint *th, int32_t thrust, uint8_t axis)
#define THRUST_AXIS_X
#define THRUST_AXIS_Z
#define THRUST_AXIS_Y
Quaternion transformation functions.
Read an attitude setpoint from the RC.
static void calc_g1_element(float dx_error, int8_t i, int8_t j, float mu_extra)
Butterworth2LowPass acceleration_lowpass_filter
static void send_eff_mat_g_indi(struct transport_tx *trans, struct link_device *dev)
static void send_ahrs_ref_quat(struct transport_tx *trans, struct link_device *dev)
void stabilization_indi_enter(void)
Function that resets important values upon engaging INDI.
Butterworth2LowPass acceleration_body_x_filter
float act_pref[INDI_NUM_ACT]
float * Bwls[INDI_OUTPUTS]
int32_t stabilization_att_indi_cmd[COMMANDS_NB]
struct Indi_gains indi_gains
void WEAK stabilization_indi_set_wls_settings(void)
Function that sets the u_min, u_max and u_pref if function not elsewhere defined.
#define STABILIZATION_INDI_THROTTLE_LIMIT_AIRSPEED_FWD
bool act_is_thruster_x[INDI_NUM_ACT]
bool act_is_servo[INDI_NUM_ACT]
static struct FirstOrderLowPass rates_filt_fo[3]
float angular_acceleration[3]
static void send_wls_v_stab(struct transport_tx *trans, struct link_device *dev)
int32_t num_thrusters
float actuator_state_filt_vectd[INDI_NUM_ACT]
float r_filt
#define STABILIZATION_INDI_FILT_CUTOFF_P
static void bound_g_mat(void)
float mu1[INDI_OUTPUTS]
#define STABILIZATION_INDI_FILT_CUTOFF_Q
struct WLS_t wls_stab_p
float g1g2[INDI_OUTPUTS][INDI_NUM_ACT]
static void calc_g2_element(float dx_error, int8_t j, float mu_extra)
float q_filt
static struct Int32Eulers stab_att_sp_euler
static void send_wls_u_stab(struct transport_tx *trans, struct link_device *dev)
float estimation_rate_d[INDI_NUM_ACT]
float du_estimation[INDI_NUM_ACT]
float actuator_state_filt_vectdd[INDI_NUM_ACT]
Butterworth2LowPass measurement_lowpass_filters[3]
void stabilization_indi_update_filt_freq(float freq)
bool act_is_thruster_z[INDI_NUM_ACT]
float g2[INDI_NUM_ACT]
struct FloatVect3 body_accel_f
float ddu_estimation[INDI_NUM_ACT]
float estimation_rate_dd[INDI_NUM_ACT]
float mu2
float act_obs[INDI_NUM_ACT]
int32_t num_thrusters_x
float g1[INDI_OUTPUTS][INDI_NUM_ACT]
void stabilization_indi_init(void)
Function that initializes important values upon engaging INDI.
struct FloatRates angular_rate_ref
float stablization_indi_yaw_dist_limit
Limit the maximum specific moment that can be compensated (units rad/s^2)
float g1g2inv[INDI_OUTPUTS][INDI_OUTPUTS]
void stabilization_indi_attitude_run(bool in_flight, struct StabilizationSetpoint *att_sp, struct ThrustSetpoint *thrust, int32_t *cmd)
float actuator_state_filt_vect[INDI_NUM_ACT]
void stabilization_indi_rate_run(bool in_flight, struct StabilizationSetpoint *sp, struct ThrustSetpoint *thrust, int32_t *cmd)
float act_first_order_cutoff[INDI_NUM_ACT]
float act_dyn_discrete[INDI_NUM_ACT]
struct FloatRates angular_accel_ref
float g1g2_trans_mult[INDI_OUTPUTS][INDI_OUTPUTS]
#define STABILIZATION_INDI_FILT_CUTOFF_R
bool indi_use_adaptive
float g2_init[INDI_NUM_ACT]
Butterworth2LowPass estimation_input_lowpass_filters[INDI_NUM_ACT]
void sum_g1_g2(void)
Function that sums g1 and g2 to obtain the g1g2 matrix It also undoes the scaling that was done to ma...
float g1g2_pseudo_inv[INDI_NUM_ACT][INDI_OUTPUTS]
float g2_est[INDI_NUM_ACT]
float g1_init[INDI_OUTPUTS][INDI_NUM_ACT]
static struct Int32Quat stab_att_sp_quat
float actuator_state[INDI_NUM_ACT]
static void lms_estimation(void)
Function that estimates the control effectiveness of each actuator online.
static void send_att_full_indi(struct transport_tx *trans, struct link_device *dev)
#define INDI_ALLOWED_G_FACTOR
float g1_est[INDI_OUTPUTS][INDI_NUM_ACT]
float indi_v[INDI_OUTPUTS]
float stabilization_indi_filter_freq
float indi_u[INDI_NUM_ACT]
static void get_actuator_state(void)
Function that tries to get actuator feedback.
Butterworth2LowPass actuator_lowpass_filters[INDI_NUM_ACT]
void init_filters(void)
Function that resets the filters to zeros.
Butterworth2LowPass estimation_output_lowpass_filters[3]
#define INDI_G_SCALING
#define STABILIZATION_INDI_ESTIMATION_FILT_CUTOFF
#define STABILIZATION_INDI_FILT_CUTOFF
struct FloatRates rate
struct FloatRates att
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition usb_ser_hw.c:74
Stabilization setpoint.
union StabilizationSetpoint::@278 sp
Thrust setpoint // TODO to a setpoint header Structure to store the desired thrust vector with differ...
enum ThrustSetpoint::@282 type
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
static void act_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback, uint8_t num_act)
RPM callback for RPM based control throttle curves.
int int32_t
Typedef defining 32 bit int type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
signed char int8_t
Typedef defining 8 bit char type.
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 u_min[WLS_N_U_MAX]
Definition wls_alloc.h:75
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 v[WLS_N_V_MAX]
Definition wls_alloc.h:70
int nu
Definition wls_alloc.h:67