diff --git a/conf/airframes/AG/rot_wing_v3c_oneloop_optitrack_ext_pose_AG.xml b/conf/airframes/AG/rot_wing_v3c_oneloop_optitrack_ext_pose_AG.xml
index 60bc43d668..86f3f1699a 100644
--- a/conf/airframes/AG/rot_wing_v3c_oneloop_optitrack_ext_pose_AG.xml
+++ b/conf/airframes/AG/rot_wing_v3c_oneloop_optitrack_ext_pose_AG.xml
@@ -219,7 +219,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -280,8 +297,8 @@
-
-
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
index 1cf9ae7201..5004266791 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
@@ -221,7 +221,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -286,8 +303,8 @@
-
-
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
index 38044f59e2..4a77196bb0 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
@@ -49,7 +49,6 @@
-
@@ -223,7 +222,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -291,8 +309,8 @@
-
-
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml
index c084012f24..47d8628160 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml
@@ -44,6 +44,7 @@
+
@@ -252,7 +253,6 @@
-
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
index 19b1a6a441..70bbd141c3 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
@@ -256,8 +256,8 @@
-
-
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3g_oneloop.xml b/conf/airframes/tudelft/rotwing_v3g_oneloop.xml
new file mode 100644
index 0000000000..1ba5906812
--- /dev/null
+++ b/conf/airframes/tudelft/rotwing_v3g_oneloop.xml
@@ -0,0 +1,390 @@
+
+
+
+ RotatingWingV3G for outdoor flight with INS EKF2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Enter the PIC
+ - Enter the PAC
+ - Enter the GCS op
+ - Goal of the flight
+ - Location, airspace and weather
+ - Check the RC battery
+ - Check tail connection
+ - Check wings taped and secured
+ - Inspect airframe condition
+ - Check attitude and heading
+ - Airspeed sensor calibration
+ - Put UAV on take-off location
+ - Check flight plan
+ - Switch to correct flight block
+ - Switch on drone tag
+ - Switch on camera
+ - Announce flight to other airspace users
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack.xml b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack.xml
new file mode 100644
index 0000000000..4cc3f48ccd
--- /dev/null
+++ b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack.xml
@@ -0,0 +1,394 @@
+
+
+
+ RotatingWingV3G with optitrack and INS EKF2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Enter the PIC
+ - Enter the PAC
+ - Enter the GCS op
+ - Goal of the flight
+ - Location, airspace and weather
+ - Check the RC battery
+ - Check tail connection
+ - Check wings taped and secured
+ - Inspect airframe condition
+ - Check attitude and heading
+ - Airspeed sensor calibration
+ - Put UAV on take-off location
+ - Check flight plan
+ - Switch to correct flight block
+ - Switch on drone tag
+ - Switch on camera
+ - Announce flight to other airspace users
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml
index 57d4538da2..e75070c353 100644
--- a/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml
+++ b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml
@@ -36,12 +36,12 @@
-
+
@@ -194,25 +194,25 @@
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
@@ -308,6 +307,8 @@
+
+
@@ -322,10 +323,10 @@
-
+
-
-
+
+
diff --git a/conf/flight_plans/tudelft/oneloop_valkenburg.xml b/conf/flight_plans/tudelft/oneloop_valkenburg.xml
index 7879814cd1..938b158f55 100644
--- a/conf/flight_plans/tudelft/oneloop_valkenburg.xml
+++ b/conf/flight_plans/tudelft/oneloop_valkenburg.xml
@@ -72,11 +72,11 @@
-
- = IndexOfBlock('land here')) @AND
(autopilot_in_flight() == true) )" deroute="Landed"/>
diff --git a/conf/modules/eff_scheduling_rotwing_V2.xml b/conf/modules/eff_scheduling_rotwing_V2.xml
index b54e7c3786..7e6abcbb74 100644
--- a/conf/modules/eff_scheduling_rotwing_V2.xml
+++ b/conf/modules/eff_scheduling_rotwing_V2.xml
@@ -22,6 +22,8 @@
+
+
diff --git a/conf/modules/oneloop_andi.xml b/conf/modules/oneloop_andi.xml
index 5ba8d08d38..4909adfb0f 100644
--- a/conf/modules/oneloop_andi.xml
+++ b/conf/modules/oneloop_andi.xml
@@ -6,38 +6,47 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/telemetry/oneloop_telemetry.xml b/conf/telemetry/oneloop_telemetry.xml
index 69add177da..4ec6d3422d 100644
--- a/conf/telemetry/oneloop_telemetry.xml
+++ b/conf/telemetry/oneloop_telemetry.xml
@@ -63,7 +63,8 @@
-
+
+
@@ -124,7 +125,8 @@
-
+
+
@@ -330,7 +332,8 @@
-
+
+
diff --git a/conf/userconf/tudelft/RW_control_panel.xml b/conf/userconf/tudelft/RW_control_panel.xml
index 5d8c7db428..620212c705 100644
--- a/conf/userconf/tudelft/RW_control_panel.xml
+++ b/conf/userconf/tudelft/RW_control_panel.xml
@@ -1124,6 +1124,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -1448,7 +1458,8 @@
-
+
+
@@ -1456,7 +1467,8 @@
-
+
+
@@ -1466,7 +1478,8 @@
-
+
+
@@ -1497,8 +1510,8 @@
-
-
+
+
@@ -1506,15 +1519,5 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/userconf/tudelft/conf.xml b/conf/userconf/tudelft/conf.xml
index 3f6f68c3b0..b35742abab 100644
--- a/conf/userconf/tudelft/conf.xml
+++ b/conf/userconf/tudelft/conf.xml
@@ -585,12 +585,12 @@
@@ -126,7 +127,7 @@ float oneloop_andi_filt_cutoff_v = ONELOOP_ANDI_FILT_CUTOFF_VEL;
#else
float oneloop_andi_filt_cutoff_v = 2.0;
#endif
-
+PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF_VEL)
#ifdef ONELOOP_ANDI_FILT_CUTOFF_POS
float oneloop_andi_filt_cutoff_pos = ONELOOP_ANDI_FILT_CUTOFF_POS;
#else
@@ -154,6 +155,10 @@ float oneloop_andi_filt_cutoff_r = ONELOOP_ANDI_FILT_CUTOFF_R;
float oneloop_andi_filt_cutoff_r = 20.0;
#endif
+PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF);
+PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF_Q);
+PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF_P);
+PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF_R);
#ifndef MAX_R
float max_r = RadOfDeg(120.0);
#else
@@ -238,10 +243,6 @@ float theta_pref_max = RadOfDeg(ONELOOP_THETA_PREF_MAX);
#define ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD 10.0
#endif
-#ifndef ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD
-#define ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD 10.0
-#endif
-
/* Declaration of Navigation Variables*/
#ifdef NAV_HYBRID_MAX_DECELERATION
float max_a_nav = NAV_HYBRID_MAX_DECELERATION;
@@ -267,20 +268,31 @@ float max_v_nav = NAV_HYBRID_MAX_AIRSPEED; // Consider implications of differenc
float max_v_nav = 5.0;
#endif
float max_as = 19.0f;
+float min_as = 0.0f;
#ifdef NAV_HYBRID_MAX_SPEED_V
float max_v_nav_v = NAV_HYBRID_MAX_SPEED_V;
#else
float max_v_nav_v = 1.5;
#endif
+
#ifndef FWD_SIDESLIP_GAIN
float fwd_sideslip_gain = 0.2;
#else
float fwd_sideslip_gain = FWD_SIDESLIP_GAIN;
#endif
+#ifndef ONELOOP_ANDI_WU_QUAD_MOTORS_FWD
+float Wu_quad_motors_fwd = 6.0;
+#else
+float Wu_quad_motors_fwd = ONELOOP_ANDI_WU_QUAD_MOTORS_FWD;
+#endif
+
+
/* Define Section of the functions used in this module*/
void init_poles(void);
+void init_poles_att(void);
+void init_poles_pos(void);
void calc_normalization(void);
void normalize_nu(void);
void G1G2_oneloop(int ctrl_type);
@@ -310,6 +322,12 @@ float oneloop_andi_sideslip(void);
void reshape_wind(void);
void chirp_pos(float time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]);
void chirp_call(bool* chirp_on, bool* chirp_first_call, float* t_0_chirp, float* time_elapsed, float f0, float f1, float t_chirp, float A, int8_t n, float psi, float p_ref[], float v_ref[], float a_ref[], float j_ref[], float p_ref_0[]);
+void init_cf2(struct CF2_t *cf, float fc);
+void init_cf4(struct CF4_t *cf, float fc);
+void init_all_cf(void);
+void reinit_cf2(struct CF2_t *cf, bool reinit);
+void reinit_cf4(struct CF4_t *cf, bool reinit);
+void reinit_all_cf(bool reinit);
/*Define general struct of the Oneloop ANDI controller*/
struct OneloopGeneral oneloop_andi;
@@ -322,6 +340,7 @@ static float dt_1l = 1./PERIODIC_FREQUENCY;
static float g = 9.81; // [m/s^2] Gravitational Acceleration
float k_as = 2.0;
int16_t temp_pitch = 0;
+float gi_unbounded_airspeed_sp = 0.0;
/* Oneloop Control Variables*/
float andi_u[ANDI_NUM_ACT_TOT];
@@ -386,12 +405,16 @@ static float Wv_backup[ANDI_OUTPUTS] = ONELOOP_ANDI_WV;
#else
static float Wv_backup[ANDI_OUTPUTS] = {1.0};
#endif
+
+#ifdef ONELOOP_ANDI_WU // {mF,mR,mB,mL,mP,de,dr,da,df,phi,theta}
+static float Wu_backup[ANDI_NUM_ACT_TOT] = ONELOOP_ANDI_WU;
+#else
+static float Wu_backup[ANDI_NUM_ACT_TOT] = {1.0};
+#endif
+
/*Complementary Filter Variables*/
-static float model_pred[ANDI_OUTPUTS];
-static float model_pred_ar[3];
-static float ang_acc[3];
-static float ang_rate[3];
-static float lin_acc[3];
+struct Oneloop_CF_t cf;
+static struct Oneloop_notch_t oneloop_notch;
/*Chirp test Variables*/
bool chirp_on = false;
@@ -433,19 +456,34 @@ float ratio_u_un[ANDI_NUM_ACT_TOT];
float ratio_vn_v[ANDI_OUTPUTS];
/*Filters Initialization*/
-static Butterworth2LowPass filt_accel_ned[3]; // Low pass filter for acceleration NED (1) - oneloop_andi_filt_cutoff_a (tau_a)
-static Butterworth2LowPass filt_veloc_ned[3]; // Low pass filter for velocity NED - oneloop_andi_filt_cutoff_a (tau_a)
-static Butterworth2LowPass rates_filt_bt[3]; // Low pass filter for angular rates - ONELOOP_ANDI_FILT_CUTOFF_P/Q/R
-static Butterworth2LowPass model_pred_la_filt[3]; // Low pass filter for model prediction linear acceleration (1) - oneloop_andi_filt_cutoff_a (tau_a)
-static Butterworth2LowPass ang_rate_lowpass_filters[3]; // Low pass filter for attitude derivative measurements - oneloop_andi_filt_cutoff (tau)
-static Butterworth2LowPass model_pred_aa_filt[3]; // Low pass filter for model prediction angular acceleration - oneloop_andi_filt_cutoff (tau)
-static Butterworth2LowPass model_pred_ar_filt[3]; // Low pass filter for model prediction angular rates - ONELOOP_ANDI_FILT_CUTOFF_P/Q/R
+static Butterworth2LowPass filt_veloc_N; // Low pass filter for velocity NED - oneloop_andi_filt_cutoff_a (tau_a)
+static Butterworth2LowPass filt_veloc_E;
+static Butterworth2LowPass filt_veloc_D;
static Butterworth2LowPass accely_filt; // Low pass filter for acceleration in y direction - oneloop_andi_filt_cutoff (tau)
-static Butterworth2LowPass airspeed_filt; // Low pass filter for airspeed - oneloop_andi_filt_cutoff (tau)
-
+static Butterworth2LowPass airspeed_filt; // Low pass filter for airspeed - oneloop_andi_filt_cutoff (tau)
/* Define messages of the module*/
#if PERIODIC_TELEMETRY
#include "modules/datalink/telemetry.h"
+// static void send_cf_oneloop(struct transport_tx *trans, struct link_device *dev)
+// {
+// float temp_cf_p[5] = {cf.p.model,cf.p.model_filt.o[0],cf.p.feedback,cf.p.feedback_filt.o[0],cf.p.out};
+// float temp_cf_q[5] = {cf.q.model,cf.q.model_filt.o[0],cf.q.feedback,cf.q.feedback_filt.o[0],cf.q.out};
+// float temp_cf_r[5] = {cf.r.model,cf.r.model_filt.o[0],cf.r.feedback,cf.r.feedback_filt.o[0],cf.r.out};
+// float temp_cf_p_dot[5] = {cf.p_dot.model,cf.p_dot.model_filt.lp2.o[0],cf.p_dot.feedback,cf.p_dot.feedback_filt.lp2.o[0],cf.p_dot.out};
+// float temp_cf_q_dot[5] = {cf.q_dot.model,cf.q_dot.model_filt.lp2.o[0],cf.q_dot.feedback,cf.q_dot.feedback_filt.lp2.o[0],cf.q_dot.out};
+// float temp_cf_r_dot[5] = {cf.r_dot.model,cf.r_dot.model_filt.o[0],cf.r_dot.feedback,cf.r_dot.feedback_filt.o[0],cf.r_dot.out};
+// //float temp_cf_ax[5] = {cf.ax.model,cf.ax.model_filt.o[0],cf.ax.feedback,cf.ax.feedback_filt.o[0],cf.ax.out};
+// //float temp_cf_ay[5] = {cf.ay.model,cf.ay.model_filt.o[0],cf.ay.feedback,cf.ay.feedback_filt.o[0],cf.ay.out};
+// float temp_cf_az[5] = {cf.az.model,cf.az.model_filt.o[0],cf.az.feedback,cf.az.feedback_filt.o[0],cf.az.out};
+// pprz_msg_send_COMPLEMENTARY_FILTER(trans, dev, AC_ID,
+// 5, temp_cf_p,
+// 5, temp_cf_q,
+// 5, temp_cf_r,
+// 5, temp_cf_p_dot,
+// 5, temp_cf_q_dot,
+// 5, temp_cf_r_dot,
+// 5, temp_cf_az);
+// }
static void send_wls_v_oneloop(struct transport_tx *trans, struct link_device *dev)
{
send_wls_v("one", &WLS_one_p, trans, dev);
@@ -458,9 +496,9 @@ static void send_eff_mat_stab_oneloop_andi(struct transport_tx *trans, struct li
{
float zero = 0.0;
pprz_msg_send_EFF_MAT_STAB(trans, dev, AC_ID,
- ANDI_NUM_ACT, EFF_MAT_G[3],
- ANDI_NUM_ACT, EFF_MAT_G[4],
- ANDI_NUM_ACT, EFF_MAT_G[5],
+ ANDI_NUM_ACT, EFF_MAT_RW[3],
+ ANDI_NUM_ACT, EFF_MAT_RW[4],
+ ANDI_NUM_ACT, EFF_MAT_RW[5],
1, &zero,
1, &zero);
}
@@ -468,9 +506,9 @@ static void send_eff_mat_stab_oneloop_andi(struct transport_tx *trans, struct li
static void send_eff_mat_guid_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
{
pprz_msg_send_EFF_MAT_GUID(trans, dev, AC_ID,
- ANDI_NUM_ACT_TOT, EFF_MAT_G[0],
- ANDI_NUM_ACT_TOT, EFF_MAT_G[1],
- ANDI_NUM_ACT_TOT, EFF_MAT_G[2]);
+ ANDI_NUM_ACT_TOT, EFF_MAT_RW[0],
+ ANDI_NUM_ACT_TOT, EFF_MAT_RW[1],
+ ANDI_NUM_ACT_TOT, EFF_MAT_RW[2]);
}
static void send_oneloop_andi(struct transport_tx *trans, struct link_device *dev)
{
@@ -527,15 +565,17 @@ static void debug_vect(struct transport_tx *trans, struct link_device *dev, char
static void send_oneloop_debug(struct transport_tx *trans, struct link_device *dev)
{
- float temp_debug_vect[7];
- temp_debug_vect[0] = model_pred[0];
- temp_debug_vect[1] = model_pred[1];
- temp_debug_vect[2] = model_pred[2];
- temp_debug_vect[3] = model_pred[3];
- temp_debug_vect[4] = model_pred[4];
- temp_debug_vect[5] = model_pred[5];
- temp_debug_vect[6] = RW.as;
- debug_vect(trans, dev, "model_pred_as", temp_debug_vect, 7);
+ float temp_debug_vect[9];
+ temp_debug_vect[0] = cf.ax.model;
+ temp_debug_vect[1] = cf.ay.model;
+ temp_debug_vect[2] = cf.az.model;
+ temp_debug_vect[3] = cf.p_dot.model;
+ temp_debug_vect[4] = cf.q_dot.model;
+ temp_debug_vect[5] = cf.r_dot.model;
+ temp_debug_vect[6] = cf.p.model;
+ temp_debug_vect[7] = cf.q.model;
+ temp_debug_vect[8] = cf.r.model;
+ debug_vect(trans, dev, "model_cf", temp_debug_vect, 9);
}
#endif
@@ -677,7 +717,11 @@ void vect_bound_nd(float vect[], float bound, int n) {
void acc_body_bound(struct FloatVect2* vect, float bound) {
int n = 2;
float v[2] = {vect->x, vect->y};
+ float sign_v0 = (v[0] > 0.f) ? 1.f : (v[0] < 0.f) ? -1.f : 0.f;
+ float sign_v1 = (v[1] > 0.f) ? 1.f : (v[1] < 0.f) ? -1.f : 0.f;
float norm = float_vect_norm(v,n);
+ v[0] = fabsf(v[0]);
+ v[1] = fabsf(v[1]);
norm = positive_non_zero(norm);
if((norm-bound) > FLT_EPSILON) {
v[0] = Min(v[0], bound);
@@ -685,8 +729,8 @@ void acc_body_bound(struct FloatVect2* vect, float bound) {
acc_b_y_2 = positive_non_zero(acc_b_y_2);
v[1] = sqrtf(acc_b_y_2);
}
- vect->x = v[0];
- vect->y = v[1];
+ vect->x = sign_v0*v[0];
+ vect->y = sign_v1*v[1];
}
/** @brief Calculate velocity limit based on acceleration limit */
@@ -965,6 +1009,38 @@ static float w_approx(float p1, float p2, float p3, float rm_k){
return 1.0/tao;
}
+/**
+ * @brief Calculate EC poles given RM poles
+ * @param p_rm Reference Model Pole (3 coincident poles)
+ * @param slow_pole Pole of the slowest dynamics
+ * @param k EC / RM ratio
+ * @param omega_n Natural Frequency
+ */
+static float ec_poles(float p_rm, float slow_pole, float k){
+ p_rm = positive_non_zero(p_rm);
+ slow_pole = positive_non_zero(slow_pole);
+ k = positive_non_zero(k);
+ float omega_n = (2*p_rm*slow_pole*k)/(3*slow_pole-p_rm);
+ return omega_n;
+}
+
+/**
+ * @brief Initialize Position of Poles
+ *
+ */
+void init_poles_att(void){
+ float slow_pole = 22.0; // Pole of the slowest dynamics used in the attitude controller
+ p_att_e.omega_n = ec_poles(p_att_rm.omega_n, slow_pole, 1.28);
+ p_head_e.omega_n = ec_poles(p_head_rm.omega_n, slow_pole, 1.28);
+}
+void init_poles_pos(void){
+ act_dynamics[COMMAND_ROLL] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
+ act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
+ float slow_pole = act_dynamics[COMMAND_ROLL]; // Pole of the slowest dynamics used in the position controller
+ p_pos_e.omega_n = ec_poles(p_pos_rm.omega_n,slow_pole,1.28);//1.0;
+ p_alt_e.omega_n = ec_poles(p_alt_rm.omega_n,slow_pole,1.28);//1.0;// 3.0;
+}
+
/**
* @brief Initialize Position of Poles
*
@@ -972,46 +1048,53 @@ static float w_approx(float p1, float p2, float p3, float rm_k){
void init_poles(void){
// Attitude Controller Poles----------------------------------------------------------
- float slow_pole = 15.1; // Pole of the slowest dynamics used in the attitude controller
+ float slow_pole = 22.0; // Pole of the slowest dynamics used in the attitude controller
- p_att_e.omega_n = 4.50;
- p_att_e.zeta = 1.0;
- p_att_e.p3 = slow_pole;
-
- p_att_rm.omega_n = 4.71;
+ p_att_rm.omega_n = 10.0; // 10.0 4.71
p_att_rm.zeta = 1.0;
p_att_rm.p3 = p_att_rm.omega_n * p_att_rm.zeta;
- p_head_e.omega_n = 1.80;
- p_head_e.zeta = 1.0;
- p_head_e.p3 = slow_pole;
+ p_att_e.omega_n = ec_poles(p_att_rm.omega_n, slow_pole, 1.28); //4.50;
+ p_att_e.zeta = 1.0;
+ p_att_e.p3 = slow_pole;
- p_head_rm.omega_n = 2.56;
+ p_head_rm.omega_n = 7.0; // 7.0 2.56
p_head_rm.zeta = 1.0;
p_head_rm.p3 = p_head_rm.omega_n * p_head_rm.zeta;
+ p_head_e.omega_n = ec_poles(p_head_rm.omega_n, slow_pole, 1.28); //1.80;
+ p_head_e.zeta = 1.0;
+ p_head_e.p3 = slow_pole;
+
act_dynamics[COMMAND_ROLL] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
// Position Controller Poles----------------------------------------------------------
slow_pole = act_dynamics[COMMAND_ROLL]; // Pole of the slowest dynamics used in the position controller
-
- p_pos_e.omega_n = 1.0;
- p_pos_e.zeta = 1.0;
- p_pos_e.p3 = slow_pole;
-
- p_pos_rm.omega_n = 0.93;
+#ifdef ONELOOP_ANDI_POLES_POS_OMEGA_N
+ p_pos_rm.omega_n = ONELOOP_ANDI_POLES_POS_OMEGA_N;
+#else
+ p_pos_rm.omega_n = 0.93; //2.2;
+#endif
p_pos_rm.zeta = 1.0;
p_pos_rm.p3 = p_pos_rm.omega_n * p_pos_rm.zeta;
- p_alt_e.omega_n = 1.0;// 3.0;
- p_alt_e.zeta = 1.0;
- p_alt_e.p3 = slow_pole;
-
- p_alt_rm.omega_n = 0.93; //1.93;
+ p_pos_e.omega_n = ec_poles(p_pos_rm.omega_n,slow_pole,1.28);//1.0;
+ p_pos_e.zeta = 1.0;
+ p_pos_e.p3 = slow_pole;
+#ifdef ONELOOP_ANDI_POLES_ALT_OMEGA_N
+ p_alt_rm.omega_n = ONELOOP_ANDI_POLES_ALT_OMEGA_N;
+#else
+ p_alt_rm.omega_n = 0.93; //2.2;
+#endif
p_alt_rm.zeta = 1.0;
p_alt_rm.p3 = p_alt_rm.omega_n * p_alt_rm.zeta;
+
+ p_alt_e.omega_n = ec_poles(p_alt_rm.omega_n,slow_pole,1.28);//1.0;// 3.0;
+ p_alt_e.zeta = 1.0;
+ p_alt_e.p3 = slow_pole;
}
+
/**
* @brief Initialize Controller Gains
* FIXME: Calculate the gains dynamically for transition
@@ -1022,6 +1105,8 @@ void init_controller(void){
max_v_nav = nav_max_speed + max_wind;
max_a_nav = nav_max_acceleration_sp;
/*Some calculations in case new poles have been specified*/
+ init_poles_att();
+ init_poles_pos();
p_att_rm.p3 = p_att_rm.omega_n * p_att_rm.zeta;
p_pos_rm.p3 = p_pos_rm.omega_n * p_pos_rm.zeta;
p_alt_rm.p3 = p_alt_rm.omega_n * p_alt_rm.zeta;
@@ -1045,6 +1130,7 @@ void init_controller(void){
//printf("Attitude RM Gains: %f %f %f\n", k_att_rm.k1[0], k_att_rm.k2[0], k_att_rm.k3[0]);
//printf("Attitude E Gains: %f %f %f\n", k_att_e.k1[0], k_att_e.k2[0], k_att_e.k3[0]);
+ //printf("Heading E Gains: %f %f %f\n", k_att_e.k1[2], k_att_e.k2[2], k_att_e.k3[2]);
/*Heading Loop NAV*/
k_att_e.k1[2] = k_e_1_3_f_v2(p_head_e.omega_n, p_head_e.zeta, p_head_e.p3);
k_att_e.k2[2] = k_e_2_3_f_v2(p_head_e.omega_n, p_head_e.zeta, p_head_e.p3);
@@ -1116,70 +1202,193 @@ void init_controller(void){
//------------------------------------------------------------------------------------------
/*Approximated Dynamics*/
act_dynamics[COMMAND_ROLL] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
- act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
+ act_dynamics[COMMAND_PITCH] = w_approx(p_att_rm.p3, p_att_rm.p3, p_att_rm.p3, 1.0);
}
-
-
+// Complementary Filters Functions -----------------------------------------------------------
+/** @brief Initialize the Complementary Filters 2nd Order Butterworth */
+void init_cf2(struct CF2_t *cf, float fc){
+ cf->freq = fc;
+ cf->freq_set = fc;
+ cf->tau = 1/(2*M_PI*cf->freq);
+ init_butterworth_2_low_pass(&cf->model_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_2_low_pass(&cf->feedback_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ cf->model = 0.0;
+ cf->feedback = 0.0;
+ cf->out = 0.0;
+}
+/** @brief Initialize the Complementary Filters 4th Order Butterworth*/
+void init_cf4(struct CF4_t *cf, float fc){
+ cf->freq = fc;
+ cf->freq_set = fc;
+ cf->tau = 1/(2*M_PI*cf->freq);
+ init_butterworth_4_low_pass(&cf->model_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_4_low_pass(&cf->feedback_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ cf->model = 0.0;
+ cf->feedback = 0.0;
+ cf->out = 0.0;
+}
+/** @brief Initialize all the Complementary Filters */
+void init_all_cf(void){
+ init_cf2(&cf.ax, oneloop_andi_filt_cutoff_a);
+ init_cf2(&cf.ay, oneloop_andi_filt_cutoff_a);
+ init_cf2(&cf.az, oneloop_andi_filt_cutoff_a);
+ init_cf4(&cf.p_dot, 2.0);
+ init_cf4(&cf.q_dot, 2.0);
+ init_cf2(&cf.r_dot, oneloop_andi_filt_cutoff);
+ init_cf2(&cf.p, oneloop_andi_filt_cutoff_p);
+ init_cf2(&cf.q, oneloop_andi_filt_cutoff_q);
+ init_cf2(&cf.r, oneloop_andi_filt_cutoff_r);
+}
+/** @brief Reinitialize 2nd Order CF if new frequency setting or if forced */
+void reinit_cf2(struct CF2_t *cf, bool reinit){
+ if(cf->freq != cf->freq_set || reinit){
+ cf->freq = cf->freq_set;
+ cf->tau = 1/(2*M_PI*cf->freq);
+ init_butterworth_2_low_pass(&cf->model_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, get_butterworth_2_low_pass(&cf->model_filt));
+ init_butterworth_2_low_pass(&cf->feedback_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, get_butterworth_2_low_pass(&cf->feedback_filt));
+ }
+}
+/** @brief Reinitialize 4th Order CF if new frequency setting or if forced */
+void reinit_cf4(struct CF4_t *cf, bool reinit){
+ if(cf->freq != cf->freq_set || reinit){
+ cf->freq = cf->freq_set;
+ cf->tau = 1/(2*M_PI*cf->freq);
+ init_butterworth_4_low_pass(&cf->model_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, get_butterworth_4_low_pass(&cf->model_filt));
+ init_butterworth_4_low_pass(&cf->feedback_filt, cf->tau, 1.0 / PERIODIC_FREQUENCY, get_butterworth_4_low_pass(&cf->feedback_filt));
+ }
+}
+/** @brief Reinitialize all the Complementary Filters */
+void reinit_all_cf(bool reinit){
+ reinit_cf2(&cf.ax, reinit);
+ reinit_cf2(&cf.ay, reinit);
+ reinit_cf2(&cf.az, reinit);
+ reinit_cf4(&cf.p_dot, reinit);
+ reinit_cf4(&cf.q_dot, reinit);
+ reinit_cf2(&cf.r_dot, reinit);
+ reinit_cf2(&cf.p, reinit);
+ reinit_cf2(&cf.q, reinit);
+ reinit_cf2(&cf.r, reinit);
+}
+//------------------------------------------------------------------------------------------
/** @brief Initialize the filters */
void init_filter(void)
{
- //printf("oneloop andi filt cutoff PQR: %f %f %f\n", oneloop_andi_filt_cutoff_p,oneloop_andi_filt_cutoff_q,oneloop_andi_filt_cutoff_r);
+ // Store Notch filter values
+#ifdef ONELOOP_ANDI_ROLL_STRUCTURAL_MODE_FREQ
+ oneloop_notch.roll.freq = ONELOOP_ANDI_ROLL_STRUCTURAL_MODE_FREQ,
+#else
+ oneloop_notch.roll.freq = 8.46,
+#endif
+#ifdef ONELOOP_ANDI_PITCH_STRUCTURAL_MODE_FREQ
+ oneloop_notch.pitch.freq = ONELOOP_ANDI_PITCH_STRUCTURAL_MODE_FREQ,
+#else
+ oneloop_notch.pitch.freq = 6.44,
+#endif
+#ifdef ONELOOP_ANDI_YAW_STRUCTURAL_MODE_FREQ
+ oneloop_notch.yaw.freq = ONELOOP_ANDI_YAW_STRUCTURAL_MODE_FREQ,
+#else
+ oneloop_notch.yaw.freq = 17.90,
+#endif
+ oneloop_notch.roll.bandwidth = 2.0;
+ oneloop_notch.pitch.bandwidth = 1.0;
+ oneloop_notch.yaw.bandwidth = 4.0;
+ // Initialize Notch filters
+ notch_filter_init(&oneloop_notch.roll.filter, oneloop_notch.roll.freq, oneloop_notch.roll.bandwidth, PERIODIC_FREQUENCY);
+ notch_filter_init(&oneloop_notch.pitch.filter, oneloop_notch.pitch.freq, oneloop_notch.pitch.bandwidth, PERIODIC_FREQUENCY);
+ notch_filter_init(&oneloop_notch.yaw.filter, oneloop_notch.yaw.freq, oneloop_notch.yaw.bandwidth, PERIODIC_FREQUENCY);
+ // Filtering of the velocities
float tau = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff);
- float tau_a = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff_a);
float tau_v = 1.0 / (2.0 * M_PI * oneloop_andi_filt_cutoff_v);
- float sample_time = 1.0 / PERIODIC_FREQUENCY;
-
- // Filtering of the Inputs with 3 dimensions (e.g. rates and accelerations)
- int8_t i;
- for (i = 0; i < 3; i++) {
- init_butterworth_2_low_pass(&ang_rate_lowpass_filters[i], tau, sample_time, 0.0);
- init_butterworth_2_low_pass(&model_pred_aa_filt[i], tau, sample_time, 0.0);
- init_butterworth_2_low_pass(&filt_accel_ned[i], tau_a, sample_time, 0.0 );
- init_butterworth_2_low_pass(&filt_veloc_ned[i], tau_v, sample_time, 0.0 );
- init_butterworth_2_low_pass(&model_pred_la_filt[i], tau_a, sample_time, 0.0);
- }
-
- // Init rate filter for feedback
- float time_constants[3] = {1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_p), 1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_q), 1.0 / (2 * M_PI * oneloop_andi_filt_cutoff_r)};
- init_butterworth_2_low_pass(&rates_filt_bt[0], time_constants[0], sample_time, stateGetBodyRates_f()->p);
- init_butterworth_2_low_pass(&rates_filt_bt[1], time_constants[1], sample_time, stateGetBodyRates_f()->q);
- init_butterworth_2_low_pass(&rates_filt_bt[2], time_constants[2], sample_time, stateGetBodyRates_f()->r);
- init_butterworth_2_low_pass(&model_pred_ar_filt[0], time_constants[0], sample_time, 0.0);
- init_butterworth_2_low_pass(&model_pred_ar_filt[1], time_constants[1], sample_time, 0.0);
- init_butterworth_2_low_pass(&model_pred_ar_filt[2], time_constants[2], sample_time, 0.0);
-
- // Some other filters
- init_butterworth_2_low_pass(&accely_filt, tau, sample_time, 0.0);
- init_butterworth_2_low_pass(&airspeed_filt, tau, sample_time, 0.0);
+ //printf("tau: %f tau_v: %f\n", tau, tau_v);
+ //printf("initializing filters\n");
+ init_butterworth_2_low_pass(&filt_veloc_N, tau_v, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_2_low_pass(&filt_veloc_E, tau_v, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_2_low_pass(&filt_veloc_D, tau_v, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_2_low_pass(&accely_filt, tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
+ init_butterworth_2_low_pass(&airspeed_filt, tau, 1.0 / PERIODIC_FREQUENCY, 0.0);
}
/** @brief Propagate the filters */
void oneloop_andi_propagate_filters(void) {
+ reinit_all_cf(false);
struct NedCoor_f *accel = stateGetAccelNed_f();
struct NedCoor_f *veloc = stateGetSpeedNed_f();
+ //printf("veloc: %f %f %f\n", veloc->x, veloc->y, veloc->z);
struct FloatRates *body_rates = stateGetBodyRates_f();
- float rate_vect[3] = {body_rates->p, body_rates->q, body_rates->r};
- update_butterworth_2_low_pass(&filt_accel_ned[0], accel->x);
- update_butterworth_2_low_pass(&filt_accel_ned[1], accel->y);
- update_butterworth_2_low_pass(&filt_accel_ned[2], accel->z);
- update_butterworth_2_low_pass(&filt_veloc_ned[0], veloc->x);
- update_butterworth_2_low_pass(&filt_veloc_ned[1], veloc->y);
- update_butterworth_2_low_pass(&filt_veloc_ned[2], veloc->z);
+ // Store Feedbacks in the Complementary Filters
+ cf.ax.feedback = accel->x;
+ cf.ay.feedback = accel->y;
+ cf.az.feedback = accel->z;
+//#define USE_ROLL_NOTCH
+//#define USE_PITCH_NOTCH
+#define USE_YAW_NOTCH
+ float temp_p_dot = (body_rates->p-cf.p.feedback)*PERIODIC_FREQUENCY;
+ float temp_q_dot = (body_rates->q-cf.q.feedback)*PERIODIC_FREQUENCY;
+ float temp_r_dot = (body_rates->r-cf.r.feedback)*PERIODIC_FREQUENCY;
+#ifdef USE_ROLL_NOTCH
+ notch_filter_update(&oneloop_notch.roll.filter, &temp_p_dot, &cf.p_dot.feedback);
+#else
+ cf.p_dot.feedback = temp_p_dot;
+#endif
+#ifdef USE_PITCH_NOTCH
+ notch_filter_update(&oneloop_notch.pitch.filter, &temp_q_dot, &cf.q_dot.feedback);
+#else
+ cf.q_dot.feedback = temp_q_dot;
+#endif
+#ifdef USE_YAW_NOTCH
+ notch_filter_update(&oneloop_notch.yaw.filter, &temp_r_dot, &cf.r_dot.feedback);
+#else
+ cf.r_dot.feedback = temp_r_dot;
+#endif
+ cf.p.feedback = body_rates->p;
+ cf.q.feedback = body_rates->q;
+ cf.r.feedback = body_rates->r;
+ // Update Filters of Feedbacks
+ update_butterworth_2_low_pass(&cf.ax.feedback_filt, cf.ax.feedback);
+ update_butterworth_2_low_pass(&cf.ay.feedback_filt, cf.ay.feedback);
+ update_butterworth_2_low_pass(&cf.az.feedback_filt, cf.az.feedback);
+ update_butterworth_4_low_pass(&cf.p_dot.feedback_filt, cf.p_dot.feedback);
+ update_butterworth_4_low_pass(&cf.q_dot.feedback_filt, cf.q_dot.feedback);
+ update_butterworth_2_low_pass(&cf.r_dot.feedback_filt, cf.r_dot.feedback);
+ update_butterworth_2_low_pass(&cf.p.feedback_filt, cf.p.feedback);
+ update_butterworth_2_low_pass(&cf.q.feedback_filt, cf.q.feedback);
+ update_butterworth_2_low_pass(&cf.r.feedback_filt, cf.r.feedback);
+ //printf("veloc: %f %f %f\n", veloc->x, veloc->y, veloc->z);
+ update_butterworth_2_low_pass(&filt_veloc_N, veloc->x);
+ update_butterworth_2_low_pass(&filt_veloc_E, veloc->y);
+ update_butterworth_2_low_pass(&filt_veloc_D, veloc->z);
+ //printf("veloc_filt: %f %f %f\n", filt_veloc_N.o[0], filt_veloc_E.o[0], filt_veloc_D.o[0]);
+ // Calculate Model Predictions for Linear and Angular Accelerations Using the Effectiveness Matrix
calc_model();
- int8_t i;
-
- for (i = 0; i < 3; i++) {
- update_butterworth_2_low_pass(&model_pred_aa_filt[i], model_pred[3+i]);
- update_butterworth_2_low_pass(&model_pred_la_filt[i], model_pred[i]);
- update_butterworth_2_low_pass(&ang_rate_lowpass_filters[i], rate_vect[i]);
- update_butterworth_2_low_pass(&rates_filt_bt[i], rate_vect[i]);
- lin_acc[i] = filt_accel_ned[i].o[0] + model_pred[i] - model_pred_la_filt[i].o[0];
- ang_acc[i] = (ang_rate_lowpass_filters[i].o[0]- ang_rate_lowpass_filters[i].o[1]) * PERIODIC_FREQUENCY + model_pred[3+i] - model_pred_aa_filt[i].o[0];
- model_pred_ar[i] = model_pred_ar[i] + ang_acc[i] / PERIODIC_FREQUENCY;
- update_butterworth_2_low_pass(&model_pred_ar_filt[i], model_pred_ar[i]);
- ang_rate[i] = rates_filt_bt[i].o[0] + model_pred_ar[i] - model_pred_ar_filt[i].o[0];
- }
+ // Update Filters of Model Predictions for Linear and Angular Accelerations
+ update_butterworth_2_low_pass(&cf.ax.model_filt, cf.ax.model);
+ update_butterworth_2_low_pass(&cf.ay.model_filt, cf.ay.model);
+ update_butterworth_2_low_pass(&cf.az.model_filt, cf.az.model);
+ update_butterworth_4_low_pass(&cf.p_dot.model_filt, cf.p_dot.model);
+ update_butterworth_4_low_pass(&cf.q_dot.model_filt, cf.q_dot.model);
+ update_butterworth_2_low_pass(&cf.r_dot.model_filt, cf.r_dot.model);
+ // Calculate Complementary Filter outputs for Linear and Angular Accelerations
+ cf.ax.out = cf.ax.feedback_filt.o[0] + cf.ax.model - cf.ax.model_filt.o[0];
+ cf.ay.out = cf.ay.feedback_filt.o[0] + cf.ay.model - cf.ay.model_filt.o[0];
+ cf.az.out = cf.az.feedback_filt.o[0] + cf.az.model - cf.az.model_filt.o[0];
+ //cf.p_dot.out = cf.p_dot.feedback_filt.o[0] + cf.p_dot.model - cf.p_dot.model_filt.o[0];
+ cf.p_dot.out = cf.p_dot.feedback_filt.lp2.o[0] + cf.p_dot.model - cf.p_dot.model_filt.lp2.o[0];
+ //cf.q_dot.out = cf.q_dot.feedback_filt.o[0] + cf.q_dot.model - cf.q_dot.model_filt.o[0];
+ cf.q_dot.out = cf.q_dot.feedback_filt.lp2.o[0] + cf.q_dot.model - cf.q_dot.model_filt.lp2.o[0];
+ cf.r_dot.out = cf.r_dot.feedback_filt.o[0] + cf.r_dot.model - cf.r_dot.model_filt.o[0];
+ // Calculate Model Predictions for Angular Rates Using the output of the angular acceleration Complementary Filter
+ cf.p.model = cf.p.model + cf.p_dot.out / PERIODIC_FREQUENCY;
+ cf.q.model = cf.q.model + cf.q_dot.out / PERIODIC_FREQUENCY;
+ cf.r.model = cf.r.model + cf.r_dot.out / PERIODIC_FREQUENCY;
+ // Update Filters of Model Predictions for Angular Rates
+ update_butterworth_2_low_pass(&cf.p.model_filt, cf.p.model);
+ update_butterworth_2_low_pass(&cf.q.model_filt, cf.q.model);
+ update_butterworth_2_low_pass(&cf.r.model_filt, cf.r.model);
+ // Calculate Complementary Filter outputs for Angular Rates
+ cf.p.out = cf.p.feedback_filt.o[0] + cf.p.model - cf.p.model_filt.o[0];
+ cf.q.out = cf.q.feedback_filt.o[0] + cf.q.model - cf.q.model_filt.o[0];
+ cf.r.out = cf.r.feedback_filt.o[0] + cf.r.model - cf.r.model_filt.o[0];
// Propagate filter for sideslip correction
float accely = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->y);
update_butterworth_2_low_pass(&accely_filt, accely);
@@ -1206,6 +1415,7 @@ void oneloop_andi_init(void)
bwls_1l[i] = EFF_MAT_G[i];
}
// Initialize filters and other variables
+ init_all_cf();
init_filter();
init_controller();
float_vect_zero(andi_u, ANDI_NUM_ACT_TOT);
@@ -1218,16 +1428,11 @@ void oneloop_andi_init(void)
float_vect_zero(oneloop_andi.sta_ref.att_3d,3);
float_vect_zero(nu, ANDI_OUTPUTS);
float_vect_zero(nu_n, ANDI_OUTPUTS);
- float_vect_zero(ang_acc,3);
- float_vect_zero(lin_acc,3);
float_vect_zero(nav_target,3);
float_vect_zero(nav_target_new,3);
eulers_zxy_des.phi = 0.0;
eulers_zxy_des.theta = 0.0;
eulers_zxy_des.psi = 0.0;
- float_vect_zero(model_pred,ANDI_OUTPUTS);
- float_vect_zero(model_pred_ar,3);
-
// Start telemetry
#if PERIODIC_TELEMETRY
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_STAB_ATTITUDE, send_oneloop_andi);
@@ -1238,6 +1443,7 @@ void oneloop_andi_init(void)
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_DEBUG_VECT, send_oneloop_debug);
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_WLS_V, send_wls_v_oneloop);
register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_WLS_U, send_wls_u_oneloop);
+ // register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_COMPLEMENTARY_FILTER, send_cf_oneloop);
#endif
}
@@ -1260,6 +1466,7 @@ void oneloop_andi_enter(bool half_loop_sp, int ctrl_type)
for (i = 0; i < ANDI_OUTPUTS; i++) {
bwls_1l[i] = EFF_MAT_G[i];
}
+ reinit_all_cf(true);
init_filter();
init_controller();
/* Stabilization Reset */
@@ -1267,15 +1474,11 @@ void oneloop_andi_enter(bool half_loop_sp, int ctrl_type)
float_vect_zero(oneloop_andi.sta_ref.att_d,3);
float_vect_zero(oneloop_andi.sta_ref.att_2d,3);
float_vect_zero(oneloop_andi.sta_ref.att_3d,3);
- float_vect_zero(ang_acc,3);
- float_vect_zero(lin_acc,3);
float_vect_zero(nav_target,3);
float_vect_zero(nav_target_new,3);
eulers_zxy_des.phi = 0.0;
eulers_zxy_des.theta = 0.0;
eulers_zxy_des.psi = psi_des_rad;
- float_vect_zero(model_pred,ANDI_OUTPUTS);
- float_vect_zero(model_pred_ar,3);
/*Guidance Reset*/
}
@@ -1453,24 +1656,23 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
oneloop_andi.sta_state.att[1] = eulers_zxy.theta;
oneloop_andi.sta_state.att[2] = eulers_zxy.psi ;
oneloop_andi_propagate_filters(); //needs to be after update of attitude vector
- oneloop_andi.sta_state.att_d[0] = ang_rate[0];//rates_filt_bt[0].o[0];
- oneloop_andi.sta_state.att_d[1] = ang_rate[1];//rates_filt_bt[1].o[0];
- oneloop_andi.sta_state.att_d[2] = ang_rate[2];//rates_filt_bt[2].o[0];
- oneloop_andi.sta_state.att_2d[0] = ang_acc[0] ;
- oneloop_andi.sta_state.att_2d[1] = ang_acc[1] ;
- oneloop_andi.sta_state.att_2d[2] = ang_acc[2] ;
+ oneloop_andi.sta_state.att_d[0] = cf.p.out;
+ oneloop_andi.sta_state.att_d[1] = cf.q.out;
+ oneloop_andi.sta_state.att_d[2] = cf.r.out;
+ oneloop_andi.sta_state.att_2d[0] = cf.p_dot.out;
+ oneloop_andi.sta_state.att_2d[1] = cf.q_dot.out;
+ oneloop_andi.sta_state.att_2d[2] = cf.r_dot.out;
// (2) Position related
oneloop_andi.gui_state.pos[0] = stateGetPositionNed_f()->x;
oneloop_andi.gui_state.pos[1] = stateGetPositionNed_f()->y;
oneloop_andi.gui_state.pos[2] = stateGetPositionNed_f()->z;
- oneloop_andi.gui_state.vel[0] = filt_veloc_ned[0].o[0];
- oneloop_andi.gui_state.vel[1] = filt_veloc_ned[1].o[0];
- oneloop_andi.gui_state.vel[2] = filt_veloc_ned[2].o[0];
- oneloop_andi.gui_state.acc[0] = lin_acc[0];
- oneloop_andi.gui_state.acc[1] = lin_acc[1];
- oneloop_andi.gui_state.acc[2] = lin_acc[2];
-
- // Calculated feedforward signal for yaW CONTROL
+ oneloop_andi.gui_state.vel[0] = filt_veloc_N.o[0];
+ oneloop_andi.gui_state.vel[1] = filt_veloc_E.o[0];
+ oneloop_andi.gui_state.vel[2] = filt_veloc_D.o[0];
+ oneloop_andi.gui_state.acc[0] = cf.ax.out;
+ oneloop_andi.gui_state.acc[1] = cf.ay.out;
+ oneloop_andi.gui_state.acc[2] = cf.az.out;
+ // Calculated feedforward signal for yaw control
g2_ff = 0.0;
for (i = 0; i < ANDI_NUM_ACT; i++) {
@@ -1525,17 +1727,22 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
case COMMAND_MOTOR_FRONT:
case COMMAND_MOTOR_RIGHT:
case COMMAND_MOTOR_BACK:
- case COMMAND_MOTOR_LEFT:
+ case COMMAND_MOTOR_LEFT: {
+ float skew_bound = RW.skew.deg;
+ Bound(skew_bound,70.0,90.0);
+ float Wu_sched = (Wu_quad_motors_fwd-Wu_backup[i])/(90.0-70.0)*(skew_bound-70)+Wu_backup[i];
+ WLS_one_p.Wu[i] = Wu_sched;
WLS_one_p.u_min[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
WLS_one_p.u_pref[i] = (u_pref[i] - actuator_state_1l[i])/ratio_u_un[i];
WLS_one_p.u_max[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
- if (rotwing_state_settings.hover_motors_active){
+ if (rotwing_state.hover_motors_enabled){
WLS_one_p.u_max[i] = (act_max[i] - actuator_state_1l[i])/ratio_u_un[i];
} else
{
WLS_one_p.u_max[i] = (0.0 - actuator_state_1l[i])/ratio_u_un[i];
}
break;
+ }
case COMMAND_MOTOR_PUSHER:
case COMMAND_RUDDER:
WLS_one_p.u_min[i] = (act_min[i] - actuator_state_1l[i])/ratio_u_un[i];
@@ -1574,7 +1781,7 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
WLS_one_p.u_pref[i] = (u_pref[i] - oneloop_andi.sta_state.att[i-ANDI_NUM_ACT])/ratio_u_un[i];
break;
case COMMAND_PITCH:
- if (rotwing_state_settings.stall_protection){
+ if (RW.skew.deg > 70.0){
WLS_one_p.u_min[i] = (RadOfDeg(-17.0) - oneloop_andi.sta_state.att[i-ANDI_NUM_ACT])/ratio_u_un[i];
WLS_one_p.u_max[i] = (RadOfDeg(17.0) - oneloop_andi.sta_state.att[i-ANDI_NUM_ACT])/ratio_u_un[i];
} else {
@@ -1585,7 +1792,6 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
break;
}
}
-
// WLS Control Allocator
normalize_nu();
wls_alloc(&WLS_one_p, bwls_1l, 0, 0, 10);
@@ -1605,7 +1811,6 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
andi_u[COMMAND_ROLL] = andi_du[COMMAND_ROLL];
andi_u[COMMAND_PITCH] = andi_du[COMMAND_PITCH];
}
-
#ifdef COMMAND_MOTOR_PUSHER
if ((half_loop)){
andi_u[COMMAND_MOTOR_PUSHER] = radio_control.values[RADIO_AUX4];
@@ -1619,9 +1824,11 @@ void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 PSA_des,
/*Commit the actuator command*/
for (i = 0; i < ANDI_NUM_ACT; i++) {
- //actuators_pprz[i] = (int16_t) andi_u[i];
commands[i] = (int16_t) andi_u[i];
}
+ if (rotwing_state.fail_pusher_motor){
+ commands[COMMAND_MOTOR_PUSHER] = 0;//Min(1000,andi_u[COMMAND_MOTOR_PUSHER]);
+ }
commands[COMMAND_THRUST] = (commands[COMMAND_MOTOR_FRONT] + commands[COMMAND_MOTOR_RIGHT] + commands[COMMAND_MOTOR_BACK] + commands[COMMAND_MOTOR_LEFT])/num_thrusters_oneloop;
autopilot.throttle = commands[COMMAND_THRUST];
stabilization.cmd[COMMAND_THRUST] = commands[COMMAND_THRUST];
@@ -1693,12 +1900,13 @@ void G1G2_oneloop(int ctrl_type) {
break;
}
int j = 0;
+ bool turn_quad_off = ((!rotwing_state.hover_motors_enabled || !rotwing_state_hover_motors_running()) && rotwing_state.state != ROTWING_STATE_FORCE_HOVER);
for (j = 0; j < ANDI_OUTPUTS; j++) {
EFF_MAT_G[j][i] = EFF_MAT_RW[j][i] * scaler * ratio_vn_v[j];
if (airspeed_filt.o[0] < ELE_MIN_AS && i == COMMAND_ELEVATOR){
EFF_MAT_G[j][i] = 0.0;
}
- if (!rotwing_state_settings.hover_motors_active && i < 4){
+ if (turn_quad_off && i < 4){
EFF_MAT_G[j][i] = 0.0;
}
if (ctrl_off && i < 4 && j == 5){ //hack test
@@ -1774,19 +1982,22 @@ void calc_model(void){
float T = RW.T / RW.m; // Thrust specific force. Minus gravity is a guesstimate.
float P = RW.P / RW.m; // Pusher specific force
- model_pred[0] = -(cpsi * stheta + ctheta * sphi * spsi) * T + (cpsi * ctheta - sphi * spsi * stheta) * P - sphi * spsi * L;
- model_pred[1] = -(spsi * stheta - cpsi * ctheta * sphi) * T + (ctheta * spsi + cpsi * sphi * stheta) * P + cpsi * sphi * L;
- model_pred[2] = g - cphi * ctheta * T - cphi * stheta * P - cphi * L;
- for (i = 3; i < ANDI_OUTPUTS; i++){ // For loop for prediction of angular acceleration
- model_pred[i] = 0.0; //
+ cf.ax.model = -(cpsi * stheta + ctheta * sphi * spsi) * T + (cpsi * ctheta - sphi * spsi * stheta) * P - sphi * spsi * L;
+ cf.ay.model = -(spsi * stheta - cpsi * ctheta * sphi) * T + (ctheta * spsi + cpsi * sphi * stheta) * P + cpsi * sphi * L;
+ cf.az.model = g - cphi * ctheta * T - cphi * stheta * P - cphi * L;
+ float model_pqr_dot[3] = {0.0, 0.0, 0.0};
+ for (i = 0; i < 3; i++){ // For loop for prediction of angular acceleration
for (j = 0; j < ANDI_NUM_ACT; j++){
if(j == COMMAND_ELEVATOR){
- model_pred[i] = model_pred[i] + (actuator_state_1l[j] - RW.ele_pref) * EFF_MAT_RW[i][j]; // Ele pref is incidence angle
+ model_pqr_dot[i] = model_pqr_dot[i] + (actuator_state_1l[j] - RW.ele_pref) * EFF_MAT_RW[i+3][j]; // Ele pref is incidence angle
} else {
- model_pred[i] = model_pred[i] + actuator_state_1l[j] * EFF_MAT_RW[i][j];
+ model_pqr_dot[i] = model_pqr_dot[i] + actuator_state_1l[j] * EFF_MAT_RW[i+3][j];
}
}
}
+ cf.p_dot.model = model_pqr_dot[0];
+ cf.q_dot.model = model_pqr_dot[1];
+ cf.r_dot.model = model_pqr_dot[2];
}
/** @brief Function that maps navigation inputs to the oneloop controller for the generated autopilot. */
@@ -1898,7 +2109,7 @@ void chirp_pos(float time_elapsed, float f0, float f1, float t_chirp, float A, i
if (n < 0){
n = 0;
}
- // i think there should not be a problem with f1 being equal to f0
+ // I think there should not be a problem with f1 being equal to f0
float k = (f1 - f0) / t_chirp;
float p_ref_chirp = chirp_pos_p_ref(time_elapsed, f0, k, A);
float v_ref_chirp = chirp_pos_v_ref(time_elapsed, f0, k, A);
@@ -1983,7 +2194,6 @@ void reshape_wind(void)
float spsi = sinf(psi);
float airspeed = airspeed_filt.o[0];
struct FloatVect2 NT_v_NE = {nav_target[0], nav_target[1]}; // Nav target in North and East frame
- //struct FloatVect2 NT_v_B = {0.0, 0.0}; // Nav target in body frame (Overwritten later)
struct FloatVect2 airspeed_v = { cpsi * airspeed, spsi * airspeed };
struct FloatVect2 windspeed;
struct FloatVect2 groundspeed = { oneloop_andi.gui_state.vel[0], oneloop_andi.gui_state.vel[1] };
@@ -1993,14 +2203,17 @@ void reshape_wind(void)
VECT2_DIFF(windspeed, groundspeed, airspeed_v); // Wind speed in North and East frame
VECT2_DIFF(des_as_NE, NT_v_NE, windspeed); // Desired airspeed in North and East frame
float norm_des_as = FLOAT_VECT2_NORM(des_as_NE);
+ gi_unbounded_airspeed_sp = norm_des_as;
+ //Check if some minimum airspeed is desired (e.g. to prevent stall)
+ if (norm_des_as < min_as) {
+ norm_des_as = min_as;
+ }
nav_target_new[0] = NT_v_NE.x;
nav_target_new[1] = NT_v_NE.y;
// if the desired airspeed is larger than the max airspeed or we are in force forward reshape gs des to cancel wind and fly at max airspeed
- if ((norm_des_as > max_as)||(rotwing_state_settings.force_forward)){
- //printf("reshaping wind\n");
+ if ((norm_des_as > max_as)||(force_forward)){
float groundspeed_factor = 0.0f;
if (FLOAT_VECT2_NORM(windspeed) < max_as) {
- //printf("we can achieve wind cancellation\n");
float av = NT_v_NE.x * NT_v_NE.x + NT_v_NE.y * NT_v_NE.y; // norm squared of nav target
float bv = -2.f * (windspeed.x * NT_v_NE.x + windspeed.y * NT_v_NE.y);
float cv = windspeed.x * windspeed.x + windspeed.y * windspeed.y - max_as * max_as;
@@ -2020,7 +2233,7 @@ void reshape_wind(void)
norm_des_as = FLOAT_VECT2_NORM(des_as_NE); // Recalculate norm of desired airspeed
des_as_B.x = norm_des_as; // Desired airspeed in body x frame
des_as_B.y = 0.0; // Desired airspeed in body y frame
- if (((airspeed > ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD) && (norm_des_as > (ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD+2.0f)))|| (rotwing_state_settings.force_forward)){
+ if (((airspeed > ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD) && (norm_des_as > (ONELOOP_ANDI_AIRSPEED_SWITCH_THRESHOLD+2.0f)))|| (force_forward)){
float delta_psi = atan2f(des_as_NE.y, des_as_NE.x) - psi;
FLOAT_ANGLE_NORMALIZE(delta_psi);
des_acc_B.y = delta_psi * 5.0;//gih_params.heading_bank_gain;
@@ -2035,3 +2248,8 @@ void reshape_wind(void)
vect_bound_nd(nav_target_new, max_a_nav, 2);
}
+void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed) {
+ min_as = min_airspeed;
+ max_as = max_airspeed;
+}
+
diff --git a/sw/airborne/firmwares/rotorcraft/oneloop/oneloop_andi.h b/sw/airborne/firmwares/rotorcraft/oneloop/oneloop_andi.h
index 9a76793245..f38f61891c 100644
--- a/sw/airborne/firmwares/rotorcraft/oneloop/oneloop_andi.h
+++ b/sw/airborne/firmwares/rotorcraft/oneloop/oneloop_andi.h
@@ -30,6 +30,8 @@
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_common_int.h"
#include "firmwares/rotorcraft/stabilization/stabilization_attitude_ref_quat_int.h"
#include "generated/airframe.h"
+#include "filters/low_pass_filter.h"
+#include "filters/notch_filter_float.h"
#ifndef ANDI_NUM_ACT
#define ANDI_NUM_ACT COMMANDS_NB_REAL
@@ -72,6 +74,7 @@ extern struct FloatEulers eulers_zxy_des;
extern float psi_des_rad;
extern float k_as;
extern float max_as;
+extern float gi_unbounded_airspeed_sp;
/*Chirp test Variables*/
extern bool chirp_on;
@@ -147,6 +150,50 @@ struct Gains2ndOrder{
float k3;
};
+struct CF4_t {
+ float tau;
+ float freq;
+ float freq_set;
+ float model;
+ Butterworth4LowPass model_filt;
+ float feedback;
+ Butterworth4LowPass feedback_filt;
+ float out;
+};
+struct CF2_t {
+ float tau;
+ float freq;
+ float freq_set;
+ float model;
+ Butterworth2LowPass model_filt;
+ float feedback;
+ Butterworth2LowPass feedback_filt;
+ float out;
+};
+
+struct Oneloop_CF_t {
+ struct CF2_t p;
+ struct CF2_t q;
+ struct CF2_t r;
+ struct CF4_t p_dot;
+ struct CF4_t q_dot;
+ struct CF2_t r_dot;
+ struct CF2_t ax;
+ struct CF2_t ay;
+ struct CF2_t az;
+};
+extern struct Oneloop_CF_t cf;
+struct notch_axis_t{
+ struct SecondOrderNotchFilter filter;
+ float freq;
+ float bandwidth;
+};
+struct Oneloop_notch_t{
+ struct notch_axis_t roll;
+ struct notch_axis_t pitch;
+ struct notch_axis_t yaw;
+};
+
extern int16_t temp_pitch;
/*Declaration of Reference Model and Error Controller Gains*/
extern struct PolePlacement p_att_e;
@@ -174,4 +221,5 @@ extern void oneloop_andi_run(bool in_flight, bool half_loop, struct FloatVect3 P
extern void oneloop_andi_RM(bool half_loop, struct FloatVect3 PSA_des, int rm_order_h, int rm_order_v, bool in_flight_oneloop);
extern void oneloop_andi_read_rc(bool in_flight, bool in_carefree, bool coordinated_turn);
extern void oneloop_from_nav(bool in_flight);
+extern void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed);
#endif // ONELOOP_ANDI_H
diff --git a/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.c b/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.c
index 93d09b01c1..918b76bfd1 100644
--- a/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.c
+++ b/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.c
@@ -67,7 +67,8 @@ float actuator_state_filt_vect[EFF_MAT_COLS_NB] = {0};
float G2_RW[EFF_MAT_COLS_NB] = {0};//ROTWING_EFF_SCHED_G2; //scaled by RW_G_SCALE
float G1_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB] = {0};//{ROTWING_EFF_SCHED_G1_ZERO, ROTWING_EFF_SCHED_G1_ZERO, ROTWING_EFF_SCHED_G1_THRUST, ROTWING_EFF_SCHED_G1_ROLL, ROTWING_EFF_SCHED_G1_PITCH, ROTWING_EFF_SCHED_G1_YAW}; //scaled by RW_G_SCALE
float EFF_MAT_RW[EFF_MAT_ROWS_NB][EFF_MAT_COLS_NB] = {0};
-static float flt_cut = 1.0e-4;
+static float flt_cut_ap = 2.0e-3;
+static float flt_cut = 1.0e-4;
struct FloatEulers eulers_zxy_RW_EFF;
static Butterworth2LowPass skew_filt;
@@ -75,6 +76,8 @@ static Butterworth2LowPass skew_filt;
bool airspeed_fake_on = false;
float airspeed_fake = 0.0;
float ele_eff = 19.36; // (0.88*22.0);
+float roll_eff = 5.5 ;//3.835;
+float yaw_eff = 0.390;
float ele_min = 0.0;
/* Define Forces and Moments tructs for each actuator*/
struct RW_Model RW;
@@ -107,6 +110,8 @@ static void wing_position_cb(uint8_t sender_id UNUSED, struct act_feedback_t *po
}
}
+#include "generated/modules.h"
+PRINT_CONFIG_VAR(EFF_SCHEDULING_ROTWING_PERIODIC_FREQ)
void eff_scheduling_rotwing_init(void)
{
init_RW_Model();
@@ -130,22 +135,22 @@ void init_RW_Model(void)
RW.m = 6.670; // [kg]
// Motor Front
RW.mF.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
- RW.mF.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
+ RW.mF.dMdu = yaw_eff / RW_G_SCALE; // [Nm / pprz]
RW.mF.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
- RW.mF.l = 0.423 ; // [m]
+ RW.mF.l = 0.423 ; // [m] 435
// Motor Right
- RW.mR.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
- RW.mR.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
+ RW.mR.dFdu = roll_eff / RW_G_SCALE; // [N / pprz]
+ RW.mR.dMdu = yaw_eff / RW_G_SCALE; // [Nm / pprz]
RW.mR.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
- RW.mR.l = 0.408 ; // [m]
+ RW.mR.l = 0.408 ; // [m] 375
// Motor Back
RW.mB.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
- RW.mB.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
+ RW.mB.dMdu = yaw_eff / RW_G_SCALE; // [Nm / pprz]
RW.mB.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
RW.mB.l = 0.423 ; // [m]
// Motor Left
- RW.mL.dFdu = 3.835 / RW_G_SCALE; // [N / pprz]
- RW.mL.dMdu = 0.390 / RW_G_SCALE; // [Nm / pprz]
+ RW.mL.dFdu = roll_eff / RW_G_SCALE; // [N / pprz]
+ RW.mL.dMdu = yaw_eff / RW_G_SCALE; // [Nm / pprz]
RW.mL.dMdud = 0.020 / RW_G_SCALE; // [Nm / pprz]
RW.mL.l = 0.408 ; // [m]
// Motor Pusher
@@ -353,8 +358,21 @@ void sum_EFF_MAT_RW(void) {
for (i = 0; i < EFF_MAT_ROWS_NB; i++) {
for(j = 0; j < EFF_MAT_COLS_NB; j++) {
float abs = fabs(EFF_MAT_RW[i][j]);
- if (abs < flt_cut) {
- EFF_MAT_RW[i][j] = 0.0;
+ switch (i) {
+ case (RW_aN):
+ case (RW_aE):
+ case (RW_aD):
+ case (RW_aq):
+ case (RW_ar):
+ if (abs < flt_cut) {
+ EFF_MAT_RW[i][j] = 0.0;
+ }
+ break;
+ case (RW_ap):
+ if (abs < flt_cut_ap) {
+ EFF_MAT_RW[i][j] = 0.0;
+ }
+ break;
}
}
}
diff --git a/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.h b/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.h
index 2490895e79..bc0bda5b79 100644
--- a/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.h
+++ b/sw/airborne/modules/ctrl/eff_scheduling_rotwing_V2.h
@@ -187,6 +187,8 @@ struct RW_Model{
extern bool airspeed_fake_on;
extern float airspeed_fake;
extern float ele_eff;
+extern float roll_eff;
+extern float yaw_eff;
extern float ele_min;
extern float rotation_angle_setpoint_deg;
diff --git a/sw/airborne/modules/nav/nav_rotorcraft_hybrid.c b/sw/airborne/modules/nav/nav_rotorcraft_hybrid.c
index 115b23087c..054304aac8 100644
--- a/sw/airborne/modules/nav/nav_rotorcraft_hybrid.c
+++ b/sw/airborne/modules/nav/nav_rotorcraft_hybrid.c
@@ -265,7 +265,7 @@ static void nav_hybrid_circle(struct EnuCoor_f *wp_center, float radius)
VECT2_DIFF(pos_diff, *stateGetPositionEnu_f(), *wp_center);
// direction of rotation
- float sign_radius = radius > 0.f ? 1.f : -1.f;
+ float sign_radius = (radius > 0.f) ? 1.f : (radius < 0.f) ? -1.f : 0.f;
// absolute radius
float abs_radius = fabsf(radius);
#if NAV_HYBRID_LIMIT_CIRCLE_RADIUS
@@ -315,7 +315,6 @@ static void nav_hybrid_circle(struct EnuCoor_f *wp_center, float radius)
VECT2_DIFF(speed_unit, nav.target, *stateGetPositionEnu_f());
float_vect2_normalize(&speed_unit);
VECT2_SMUL(nav.speed, speed_unit, desired_speed);
-
nav_rotorcraft_base.circle.center = *wp_center;
nav_rotorcraft_base.circle.radius = sign_radius * abs_radius;
nav.horizontal_mode = NAV_HORIZONTAL_MODE_CIRCLE;
diff --git a/sw/airborne/modules/rotwing_drone/wing_rotation_adc_sensor.h b/sw/airborne/modules/rotwing_drone/wing_rotation_adc_sensor.h
index ac5d6d0657..70d782b055 100644
--- a/sw/airborne/modules/rotwing_drone/wing_rotation_adc_sensor.h
+++ b/sw/airborne/modules/rotwing_drone/wing_rotation_adc_sensor.h
@@ -26,7 +26,6 @@
#ifndef WING_ROTATION_ADC_SENSOR_H
#define WING_ROTATION_ADC_SENSOR_H
-extern float adc_wing_rotation_extern;
extern void wing_rotation_adc_init(void);
extern void wing_rotation_adc_to_deg(void);
diff --git a/sw/include/std.h b/sw/include/std.h
index 30174444ac..16523b6fbf 100644
--- a/sw/include/std.h
+++ b/sw/include/std.h
@@ -65,6 +65,10 @@ typedef uint8_t unit_t;
#define M_PI 3.14159265358979323846
#endif
+#ifndef M_PI_6
+#define M_PI_6 (M_PI/6)
+#endif
+
#ifndef M_PI_4
#define M_PI_4 (M_PI/4)
#endif