diff --git a/conf/modules/stabilization_indi.xml b/conf/modules/stabilization_indi.xml index 27400cdb3d..4a2f725902 100644 --- a/conf/modules/stabilization_indi.xml +++ b/conf/modules/stabilization_indi.xml @@ -28,7 +28,10 @@ - + + + + diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi.c b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi.c index a84f240cd5..7fca1ee535 100644 --- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi.c +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi.c @@ -165,9 +165,10 @@ void guidance_indi_run(float *heading_sp) float pos_y_err = POS_FLOAT_OF_BFP(guidance_h.ref.pos.y) - stateGetPositionNed_f()->y; float pos_z_err = POS_FLOAT_OF_BFP(guidance_v_z_ref - stateGetPositionNed_i()->z); - float speed_sp_x = pos_x_err * guidance_indi_pos_gain; - float speed_sp_y = pos_y_err * guidance_indi_pos_gain; - float speed_sp_z = pos_z_err * guidance_indi_pos_gain; + // Use feed forward part from reference model + float speed_sp_x = pos_x_err * guidance_indi_pos_gain + SPEED_FLOAT_OF_BFP(guidance_h.ref.speed.x); + float speed_sp_y = pos_y_err * guidance_indi_pos_gain + SPEED_FLOAT_OF_BFP(guidance_h.ref.speed.y); + float speed_sp_z = pos_z_err * guidance_indi_pos_gain + SPEED_FLOAT_OF_BFP(guidance_v_zd_ref); // If the acceleration setpoint is set over ABI message if (indi_accel_sp_set_2d) { @@ -190,9 +191,9 @@ void guidance_indi_run(float *heading_sp) indi_accel_sp_set_3d = false; } } else { - sp_accel.x = (speed_sp_x - stateGetSpeedNed_f()->x) * guidance_indi_speed_gain; - sp_accel.y = (speed_sp_y - stateGetSpeedNed_f()->y) * guidance_indi_speed_gain; - sp_accel.z = (speed_sp_z - stateGetSpeedNed_f()->z) * guidance_indi_speed_gain; + sp_accel.x = (speed_sp_x - stateGetSpeedNed_f()->x) * guidance_indi_speed_gain + ACCEL_FLOAT_OF_BFP(guidance_h.ref.accel.x); + sp_accel.y = (speed_sp_y - stateGetSpeedNed_f()->y) * guidance_indi_speed_gain + ACCEL_FLOAT_OF_BFP(guidance_h.ref.accel.y); + sp_accel.z = (speed_sp_z - stateGetSpeedNed_f()->z) * guidance_indi_speed_gain + ACCEL_FLOAT_OF_BFP(guidance_v_zdd_ref); } #if GUIDANCE_INDI_RC_DEBUG diff --git a/sw/airborne/firmwares/rotorcraft/stabilization/stabilization_indi.c b/sw/airborne/firmwares/rotorcraft/stabilization/stabilization_indi.c index 517943370e..c4d53f7d89 100644 --- a/sw/airborne/firmwares/rotorcraft/stabilization/stabilization_indi.c +++ b/sw/airborne/firmwares/rotorcraft/stabilization/stabilization_indi.c @@ -48,6 +48,24 @@ // Factor that the estimated G matrix is allowed to deviate from initial one #define INDI_ALLOWED_G_FACTOR 2.0 +#ifdef STABILIZATION_INDI_FILT_CUTOFF_P +#define STABILIZATION_INDI_FILTER_ROLL_RATE TRUE +#else +#define STABILIZATION_INDI_FILT_CUTOFF_P 20.0 +#endif + +#ifdef STABILIZATION_INDI_FILT_CUTOFF_Q +#define STABILIZATION_INDI_FILTER_PITCH_RATE TRUE +#else +#define STABILIZATION_INDI_FILT_CUTOFF_Q 20.0 +#endif + +#ifdef STABILIZATION_INDI_FILT_CUTOFF_R +#define STABILIZATION_INDI_FILTER_YAW_RATE TRUE +#else +#define STABILIZATION_INDI_FILT_CUTOFF_R 20.0 +#endif + float du_min[INDI_NUM_ACT]; float du_max[INDI_NUM_ACT]; float du_pref[INDI_NUM_ACT]; @@ -169,6 +187,7 @@ Butterworth2LowPass estimation_input_lowpass_filters[INDI_NUM_ACT]; Butterworth2LowPass measurement_lowpass_filters[3]; Butterworth2LowPass estimation_output_lowpass_filters[3]; Butterworth2LowPass acceleration_lowpass_filter; +static struct FirstOrderLowPass rates_filt_fo[3]; struct FloatVect3 body_accel_f; @@ -286,6 +305,13 @@ void init_filters(void) // Filtering of the accel body z init_butterworth_2_low_pass(&acceleration_lowpass_filter, tau_est, sample_time, 0.0); + + // Init rate filter for feedback + float time_constants[3] = {1.0/(2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_P), 1.0/(2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_Q), 1.0/(2 * M_PI * STABILIZATION_INDI_FILT_CUTOFF_R)}; + + init_first_order_low_pass(&rates_filt_fo[0], time_constants[0], sample_time, stateGetBodyRates_f()->p); + init_first_order_low_pass(&rates_filt_fo[1], time_constants[1], sample_time, stateGetBodyRates_f()->q); + init_first_order_low_pass(&rates_filt_fo[2], time_constants[2], sample_time, stateGetBodyRates_f()->r); } /** @@ -364,14 +390,30 @@ void stabilization_indi_rate_run(struct FloatRates rate_sp, bool in_flight) estimation_rate_dd[i] = (estimation_rate_d[i] - estimation_rate_d_prev) * PERIODIC_FREQUENCY; } - // FIXME: this should be configurable! - q_filt = (q_filt*3+body_rates->q)/4; - r_filt = (r_filt*3+body_rates->r)/4; + //The rates used for feedback are by default the measured rates. + //If there is a lot of noise on the gyroscope, it might be good to use the filtered value for feedback. + //Note that due to the delay, the PD controller may need relaxed gains. + struct FloatRates rates_filt; +#if STABILIZATION_INDI_FILTER_ROLL_RATE + rates_filt.p = update_first_order_low_pass(&rates_filt_fo[0], body_rates->p); +#else + rates_filt.p = body_rates->p; +#endif +#if STABILIZATION_INDI_FILTER_PITCH_RATE + rates_filt.q = update_first_order_low_pass(&rates_filt_fo[1], body_rates->q); +#else + rates_filt.q = body_rates->q; +#endif +#if STABILIZATION_INDI_FILTER_YAW_RATE + rates_filt.r = update_first_order_low_pass(&rates_filt_fo[2], body_rates->r); +#else + rates_filt.r = body_rates->r; +#endif //calculate the virtual control (reference acceleration) based on a PD controller - angular_accel_ref.p = (rate_sp.p - body_rates->p) * indi_gains.rate.p; - angular_accel_ref.q = (rate_sp.q - q_filt) * indi_gains.rate.q; - angular_accel_ref.r = (rate_sp.r - r_filt) * indi_gains.rate.r; + angular_accel_ref.p = (rate_sp.p - rates_filt.p) * indi_gains.rate.p; + angular_accel_ref.q = (rate_sp.q - rates_filt.q) * indi_gains.rate.q; + angular_accel_ref.r = (rate_sp.r - rates_filt.r) * indi_gains.rate.r; g2_times_du = 0.0; for (i = 0; i < INDI_NUM_ACT; i++) {