diff --git a/conf/airframes/examples/cube_orange.xml b/conf/airframes/examples/cube_orange.xml index ee2a0d930d..a235f9c9c8 100644 --- a/conf/airframes/examples/cube_orange.xml +++ b/conf/airframes/examples/cube_orange.xml @@ -109,7 +109,7 @@ - + diff --git a/conf/airframes/tudelft/bebop2_indi_convergence.xml b/conf/airframes/tudelft/bebop2_indi_convergence.xml index 1629e3cf67..8841cf854e 100644 --- a/conf/airframes/tudelft/bebop2_indi_convergence.xml +++ b/conf/airframes/tudelft/bebop2_indi_convergence.xml @@ -34,7 +34,7 @@ - + diff --git a/conf/airframes/tudelft/cyfoam.xml b/conf/airframes/tudelft/cyfoam.xml index 7fe2d6ce22..db3dab7afb 100644 --- a/conf/airframes/tudelft/cyfoam.xml +++ b/conf/airframes/tudelft/cyfoam.xml @@ -292,7 +292,7 @@ - + diff --git a/conf/airframes/tudelft/disco_rotorcraft_indi.xml b/conf/airframes/tudelft/disco_rotorcraft_indi.xml index 50e92066b2..c759e36508 100644 --- a/conf/airframes/tudelft/disco_rotorcraft_indi.xml +++ b/conf/airframes/tudelft/disco_rotorcraft_indi.xml @@ -60,7 +60,7 @@ - + @@ -409,7 +409,6 @@ - diff --git a/conf/modules/guidance_indi_hybrid.xml b/conf/modules/guidance_indi_hybrid.xml index 1535377fa5..c083ed67ad 100644 --- a/conf/modules/guidance_indi_hybrid.xml +++ b/conf/modules/guidance_indi_hybrid.xml @@ -3,7 +3,9 @@ - Guidance controller for hybrids using INDI + Common guidance controller code for hybrids using INDI: in your airframe file include one of the options: + - guidance_indi_hybid_tailsitter + - guidance_indi_hybid_quadplane
@@ -31,14 +33,13 @@ @navigation,guidance_rotorcraft,wls - guidance,attitude_command + guidance_indi_hybrid_tailsitter
- diff --git a/conf/modules/guidance_indi_hybrid_quadplane.xml b/conf/modules/guidance_indi_hybrid_quadplane.xml new file mode 100644 index 0000000000..5afcf0d6f8 --- /dev/null +++ b/conf/modules/guidance_indi_hybrid_quadplane.xml @@ -0,0 +1,27 @@ + + + + + + Guidance controller for hybrid quadplane vehicles + + + + guidance_indi_hybrid + guidance_indi_hybrid_tailsitter + guidance,attitude_command + +
+ +
+ + + + + + + + + + +
diff --git a/conf/modules/guidance_indi_hybrid_tailsitter.xml b/conf/modules/guidance_indi_hybrid_tailsitter.xml new file mode 100644 index 0000000000..3e6c10cac8 --- /dev/null +++ b/conf/modules/guidance_indi_hybrid_tailsitter.xml @@ -0,0 +1,24 @@ + + + + + + Guidance controller for hybrid tailsitter vehicles + + + + guidance_indi_hybrid + guidance_indi_hybrid_quadplane + guidance,attitude_command + +
+ +
+ + + + + + + +
diff --git a/conf/modules/nav_hybrid.xml b/conf/modules/nav_hybrid.xml index c5e2ccc2ad..15ed23187b 100644 --- a/conf/modules/nav_hybrid.xml +++ b/conf/modules/nav_hybrid.xml @@ -40,6 +40,8 @@ + +
diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c index f7fd05a723..c5a6b1e730 100644 --- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c @@ -90,20 +90,6 @@ float guidance_indi_max_airspeed = GUIDANCE_INDI_MAX_AIRSPEED; float guidance_indi_pitch_pref_deg = 0; -#if GUIDANCE_INDI_QUADPLANE -#ifndef GUIDANCE_INDI_THRUST_Z_EFF -#error "You need to define GUIDANCE_INDI_THRUST_Z_EFF" -#else -float guidance_indi_thrust_z_eff = GUIDANCE_INDI_THRUST_Z_EFF; -#endif - -#ifndef GUIDANCE_INDI_THRUST_X_EFF -#error "You need to define GUIDANCE_INDI_THRUST_X_EFF" -#else -float guidance_indi_thrust_x_eff = GUIDANCE_INDI_THRUST_X_EFF; -#endif -#endif - // If using WLS, check that the matrix size is sufficient #if GUIDANCE_INDI_HYBRID_USE_WLS #if GUIDANCE_INDI_HYBRID_U > WLS_N_U @@ -181,7 +167,6 @@ Butterworth2LowPass roll_filt; Butterworth2LowPass pitch_filt; Butterworth2LowPass thrust_filt; Butterworth2LowPass accely_filt; -Butterworth2LowPass accel_bodyz_filt; struct FloatVect2 desired_airspeed; @@ -207,7 +192,6 @@ float Wu_gih[GUIDANCE_INDI_HYBRID_U] = { 1.f, 1.f, 1.f }; #endif float filter_cutoff = GUIDANCE_INDI_FILTER_CUTOFF; -float bodyz_filter_cutoff = 0.2; float guidance_indi_hybrid_heading_sp = 0.f; struct FloatEulers guidance_euler_cmd; @@ -224,7 +208,6 @@ struct FloatVect3 indi_vel_sp = {0.0, 0.0, 0.0}; float time_of_vel_sp = 0.0; void guidance_indi_propagate_filters(void); -void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float v_body[GUIDANCE_INDI_HYBRID_V]); #if PERIODIC_TELEMETRY #include "modules/datalink/telemetry.h" @@ -289,7 +272,6 @@ void guidance_indi_enter(void) { guidance_indi_hybrid_heading_sp = stateGetNedToBodyEulers_f()->psi; float tau = 1.0 / (2.0 * M_PI * filter_cutoff); - float tau_bodyz = 1.0/(2.0*M_PI*bodyz_filter_cutoff); float sample_time = 1.0 / PERIODIC_FREQUENCY; for (int8_t i = 0; i < 3; i++) { init_butterworth_2_low_pass(&filt_accel_ned[i], tau, sample_time, 0.0); @@ -302,7 +284,6 @@ void guidance_indi_enter(void) { init_butterworth_2_low_pass(&pitch_filt, tau, sample_time, eulers_zxy.theta); init_butterworth_2_low_pass(&thrust_filt, tau, sample_time, thrust_in); init_butterworth_2_low_pass(&accely_filt, tau, sample_time, 0.0); - init_butterworth_2_low_pass(&accel_bodyz_filt, tau_bodyz, sample_time, -9.81); } #include "firmwares/rotorcraft/navigation.h" @@ -735,166 +716,8 @@ void guidance_indi_propagate_filters(void) { // Propagate filter for sideslip correction float accely = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->y); update_butterworth_2_low_pass(&accely_filt, accely); - - // Propagate filter for thrust/lift estimate - float accelz = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->z); - update_butterworth_2_low_pass(&accel_bodyz_filt, accelz); } -/** - * Calculate the matrix of partial derivatives of the roll, pitch and thrust - * w.r.t. the NED accelerations, taking into account the lift of a wing that is - * horizontal at -90 degrees pitch - * - * @param Gmat Dynamics matrix - * @param a_diff acceleration errors in earth frame - * @param body_v 3D vector to write the control objective v - */ -#if defined(GUIDANCE_INDI_QUADPLANE) -/** - * Perform WLS - * - * @param Gmat Dynamics matrix - * @param a_diff acceleration errors in earth frame - * @param body_v 3D vector to write the control objective v - */ -void WEAK guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float body_v[GUIDANCE_INDI_HYBRID_V]) { - /*Pre-calculate sines and cosines*/ - float sphi = sinf(eulers_zxy.phi); - float cphi = cosf(eulers_zxy.phi); - float stheta = sinf(eulers_zxy.theta); - float ctheta = cosf(eulers_zxy.theta); - float spsi = sinf(eulers_zxy.psi); - float cpsi = cosf(eulers_zxy.psi); - -#ifndef GUIDANCE_INDI_PITCH_EFF_SCALING -#define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0 -#endif - - /*Amount of lift produced by the wing*/ - float lift_thrust_bz = accel_bodyz_filt.o[0]; // Sum of lift and thrust in boxy z axis (level flight) - - // get the derivative of the lift wrt to theta - float liftd = guidance_indi_get_liftd(0.0f, 0.0f); - - Gmat[0][0] = -sphi*stheta*lift_thrust_bz; - Gmat[1][0] = -cphi*lift_thrust_bz; - Gmat[2][0] = -sphi*ctheta*lift_thrust_bz; - - Gmat[0][1] = cphi*ctheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING; - Gmat[1][1] = sphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*liftd; - Gmat[2][1] = -cphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd; - - Gmat[0][2] = cphi*stheta; - Gmat[1][2] = -sphi; - Gmat[2][2] = cphi*ctheta; - - Gmat[0][3] = ctheta; - Gmat[1][3] = 0; - Gmat[2][3] = -stheta; - - // Convert acceleration error to body axis system - body_v[0] = cpsi * a_diff.x + spsi * a_diff.y; - body_v[1] = -spsi * a_diff.x + cpsi * a_diff.y; - body_v[2] = a_diff.z; -} -#else -void WEAK guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float v_gih[GUIDANCE_INDI_HYBRID_V]) { - - /*Pre-calculate sines and cosines*/ - float sphi = sinf(eulers_zxy.phi); - float cphi = cosf(eulers_zxy.phi); - float stheta = sinf(eulers_zxy.theta); - float ctheta = cosf(eulers_zxy.theta); - float spsi = sinf(eulers_zxy.psi); - float cpsi = cosf(eulers_zxy.psi); - //minus gravity is a guesstimate of the thrust force, thrust measurement would be better - -#ifndef GUIDANCE_INDI_PITCH_EFF_SCALING -#define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0 -#endif - - /*Amount of lift produced by the wing*/ - float pitch_lift = eulers_zxy.theta; - Bound(pitch_lift,-M_PI_2,0); - float lift = sinf(pitch_lift)*9.81; - float T = cosf(pitch_lift)*-9.81; - - // get the derivative of the lift wrt to theta - float liftd = guidance_indi_get_liftd(stateGetAirspeed_f(), eulers_zxy.theta); - - Gmat[0][0] = cphi*ctheta*spsi*T + cphi*spsi*lift; - Gmat[1][0] = -cphi*ctheta*cpsi*T - cphi*cpsi*lift; - Gmat[2][0] = -sphi*ctheta*T -sphi*lift; - Gmat[0][1] = (ctheta*cpsi - sphi*stheta*spsi)*T*GUIDANCE_INDI_PITCH_EFF_SCALING + sphi*spsi*liftd; - Gmat[1][1] = (ctheta*spsi + sphi*stheta*cpsi)*T*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*cpsi*liftd; - Gmat[2][1] = -cphi*stheta*T*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd; - Gmat[0][2] = stheta*cpsi + sphi*ctheta*spsi; - Gmat[1][2] = stheta*spsi - sphi*ctheta*cpsi; - Gmat[2][2] = cphi*ctheta; - - v_gih[0] = a_diff.x; - v_gih[1] = a_diff.y; - v_gih[2] = a_diff.z; -} -#endif -/** - * - * @param body_v - * - * WEAK function to set the quadplane wls settings - */ -#if GUIDANCE_INDI_HYBRID_USE_WLS -void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3] UNUSED, float roll_angle, float pitch_angle) -{ - // Set lower limits - du_min_gih[0] = -guidance_indi_max_bank - roll_angle; // roll - du_min_gih[1] = RadOfDeg(guidance_indi_min_pitch) - pitch_angle; // pitch - du_min_gih[2] = (MAX_PPRZ - actuator_state_filt_vect[0]) * g1g2[3][0] + (MAX_PPRZ - actuator_state_filt_vect[1]) * g1g2[3][1] + (MAX_PPRZ - actuator_state_filt_vect[2]) * g1g2[3][2] + (MAX_PPRZ - actuator_state_filt_vect[3]) * g1g2[3][3]; - - // Set upper limits limits - du_max_gih[0] = guidance_indi_max_bank - roll_angle; //roll - du_max_gih[1] = RadOfDeg(GUIDANCE_INDI_MAX_PITCH) - pitch_angle; // pitch - du_max_gih[2] = -(actuator_state_filt_vect[0]*g1g2[3][0] + actuator_state_filt_vect[1]*g1g2[3][1] + actuator_state_filt_vect[2]*g1g2[3][2] + actuator_state_filt_vect[3]*g1g2[3][3]); - - // Set prefered states - du_pref_gih[0] = -roll_angle; // prefered delta roll angle - du_pref_gih[1] = -pitch_angle; // prefered delta pitch angle - du_pref_gih[2] = du_max_gih[2]; -} -#elif defined(GUIDANCE_INDI_QUADPLANE) -#warning We have GUIDANCE_INDI_QUADPLANE -void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle) -{ - float roll_limit_rad = GUIDANCE_H_MAX_BANK; - float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH); - float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH); - - float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg); - - // Set lower limits - du_min_gih[0] = -roll_limit_rad - roll_angle; //roll - du_min_gih[1] = min_pitch_limit_rad - pitch_angle; // pitch - du_min_gih[2] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST]) * guidance_indi_thrust_z_eff; - du_min_gih[3] = -stabilization_cmd[COMMAND_THRUST_X]*guidance_indi_thrust_x_eff; - - // Set upper limits limits - du_max_gih[0] = roll_limit_rad - roll_angle; //roll - du_max_gih[1] = max_pitch_limit_rad - pitch_angle; // pitch - du_max_gih[2] = -stabilization_cmd[COMMAND_THRUST] * guidance_indi_thrust_z_eff; - du_max_gih[3] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST_X])*guidance_indi_thrust_x_eff; - - // Set prefered states - du_pref_gih[0] = -roll_angle; // prefered delta roll angle - du_pref_gih[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle - du_pref_gih[2] = du_max_gih[2]; // Low thrust better for efficiency - du_pref_gih[3] = body_v[0]; // solve the body acceleration -} -#else -void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3] UNUSED, float roll_angle UNUSED, float pitch_angle UNUSED) { - -} -#endif /** * @brief Get the derivative of lift w.r.t. pitch. diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h index c687b96f89..4d46131beb 100644 --- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h @@ -37,11 +37,9 @@ #include "firmwares/rotorcraft/guidance.h" #include "firmwares/rotorcraft/stabilization.h" -#ifdef GUIDANCE_INDI_QUADPLANE -#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplanes.h" -#define GUIDANCE_INDI_HYBRID_USE_WLS true -#else -#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitters.h" + +#ifndef GUIDANCE_INDI_HYBRID_U +#error Please use guidance_indi_hybrid_tailsitter or guidance_indi_hybrid_quadplane in your airframe file. #endif @@ -50,7 +48,11 @@ extern void guidance_indi_init(void); extern void guidance_indi_enter(void); extern float guidance_indi_get_liftd(float pitch, float theta); +extern void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float v_body[GUIDANCE_INDI_HYBRID_V]); + +#if GUIDANCE_INDI_HYBRID_USE_WLS extern void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle); +#endif enum GuidanceIndiHybrid_HMode { GUIDANCE_INDI_HYBRID_H_POS, @@ -83,11 +85,14 @@ extern struct FloatVect3 gi_speed_sp; extern float guidance_indi_pitch_pref_deg; +#if GUIDANCE_INDI_HYBRID_USE_WLS extern float Wu_gih[GUIDANCE_INDI_HYBRID_U]; extern float Wv_gih[GUIDANCE_INDI_HYBRID_V]; extern float du_min_gih[GUIDANCE_INDI_HYBRID_U]; extern float du_max_gih[GUIDANCE_INDI_HYBRID_U]; extern float du_pref_gih[GUIDANCE_INDI_HYBRID_U]; +#endif + extern float guidance_indi_thrust_z_eff; extern float guidance_indi_thrust_x_eff; diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.c b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.c new file mode 100644 index 0000000000..c7bdac2220 --- /dev/null +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 Ewoud Smeur + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.c + * + */ + +#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid.h" +#include "stabilization/stabilization_attitude_ref_quat_int.h" +#include "filters/low_pass_filter.h" +#include "state.h" +#include "generated/modules.h" + + +#ifndef GUIDANCE_INDI_THRUST_Z_EFF +#error "You need to define GUIDANCE_INDI_THRUST_Z_EFF" +#else +float guidance_indi_thrust_z_eff = GUIDANCE_INDI_THRUST_Z_EFF; +#endif + +#ifndef GUIDANCE_INDI_THRUST_X_EFF +#error "You need to define GUIDANCE_INDI_THRUST_X_EFF" +#else +float guidance_indi_thrust_x_eff = GUIDANCE_INDI_THRUST_X_EFF; +#endif + + +float bodyz_filter_cutoff = 0.2; + +Butterworth2LowPass accel_bodyz_filt; + + + +/** + * + * Call upon entering indi guidance + */ +void guidance_indi_quadplane_init(void) { + float tau_bodyz = 1.0/(2.0*M_PI*bodyz_filter_cutoff); + float sample_time = 1.0 / PERIODIC_FREQUENCY; + init_butterworth_2_low_pass(&accel_bodyz_filt, tau_bodyz, sample_time, -9.81); +} + + +/** + * Low pass the accelerometer measurements to remove noise from vibrations. + * The roll and pitch also need to be filtered to synchronize them with the + * acceleration + * Called as a periodic function with PERIODIC_FREQ + */ +void guidance_indi_quadplane_propagate_filters(void) { + // Propagate filter for thrust/lift estimate + float accelz = ACCEL_FLOAT_OF_BFP(stateGetAccelBody_i()->z); + update_butterworth_2_low_pass(&accel_bodyz_filt, accelz); +} + + + + +/** + * Perform WLS + * + * @param Gmat Dynamics matrix + * @param a_diff acceleration errors in earth frame + * @param body_v 3D vector to write the control objective v + */ +void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float body_v[GUIDANCE_INDI_HYBRID_V]) { + // Get attitude + struct FloatEulers eulers_zxy; + float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f()); + + /*Pre-calculate sines and cosines*/ + float sphi = sinf(eulers_zxy.phi); + float cphi = cosf(eulers_zxy.phi); + float stheta = sinf(eulers_zxy.theta); + float ctheta = cosf(eulers_zxy.theta); + float spsi = sinf(eulers_zxy.psi); + float cpsi = cosf(eulers_zxy.psi); + +#ifndef GUIDANCE_INDI_PITCH_EFF_SCALING +#define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0 +#endif + + /*Amount of lift produced by the wing*/ + float lift_thrust_bz = accel_bodyz_filt.o[0]; // Sum of lift and thrust in boxy z axis (level flight) + + // get the derivative of the lift wrt to theta + float liftd = guidance_indi_get_liftd(0.0f, 0.0f); + + Gmat[0][0] = -sphi*stheta*lift_thrust_bz; + Gmat[1][0] = -cphi*lift_thrust_bz; + Gmat[2][0] = -sphi*ctheta*lift_thrust_bz; + + Gmat[0][1] = cphi*ctheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING; + Gmat[1][1] = sphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*liftd; + Gmat[2][1] = -cphi*stheta*lift_thrust_bz*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd; + + Gmat[0][2] = cphi*stheta; + Gmat[1][2] = -sphi; + Gmat[2][2] = cphi*ctheta; + + Gmat[0][3] = ctheta; + Gmat[1][3] = 0; + Gmat[2][3] = -stheta; + + // Convert acceleration error to body axis system + body_v[0] = cpsi * a_diff.x + spsi * a_diff.y; + body_v[1] = -spsi * a_diff.x + cpsi * a_diff.y; + body_v[2] = a_diff.z; +} + + +void WEAK guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle) +{ + float roll_limit_rad = GUIDANCE_H_MAX_BANK; + float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH); + float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH); + + float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg); + + // Set lower limits + du_min_gih[0] = -roll_limit_rad - roll_angle; //roll + du_min_gih[1] = min_pitch_limit_rad - pitch_angle; // pitch + du_min_gih[2] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST]) * guidance_indi_thrust_z_eff; + du_min_gih[3] = -stabilization_cmd[COMMAND_THRUST_X]*guidance_indi_thrust_x_eff; + + // Set upper limits limits + du_max_gih[0] = roll_limit_rad - roll_angle; //roll + du_max_gih[1] = max_pitch_limit_rad - pitch_angle; // pitch + du_max_gih[2] = -stabilization_cmd[COMMAND_THRUST] * guidance_indi_thrust_z_eff; + du_max_gih[3] = (MAX_PPRZ - stabilization_cmd[COMMAND_THRUST_X])*guidance_indi_thrust_x_eff; + + // Set prefered states + du_pref_gih[0] = -roll_angle; // prefered delta roll angle + du_pref_gih[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle + du_pref_gih[2] = du_max_gih[2]; // Low thrust better for efficiency + du_pref_gih[3] = body_v[0]; // solve the body acceleration +} diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplanes.h b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.h similarity index 79% rename from sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplanes.h rename to sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.h index 793e04f8f9..a1145e7247 100644 --- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplanes.h +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_quadplane.h @@ -19,14 +19,12 @@ * Boston, MA 02111-1307, USA. */ +#ifndef GUIDANCE_INDI_HYBRID_QUADPLANE +#define GUIDANCE_INDI_HYBRID_QUADPLANE -// Guidance actuators: (roll, pitch, thrust, push) for quadplanes -#define GUIDANCE_INDI_HYBRID_U 4 - -// Guidance control objectives: ax, ay, ay for quadplanes -#define GUIDANCE_INDI_HYBRID_V 3 - +extern void guidance_indi_quadplane_init(void); +extern void guidance_indi_quadplane_propagate_filters(void); #ifndef GUIDANCE_INDI_MIN_PITCH @@ -36,3 +34,4 @@ +#endif // GUIDANCE_INDI_HYBRID_QUADPLANE \ No newline at end of file diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.c b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.c new file mode 100644 index 0000000000..c4abe22813 --- /dev/null +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2015 Ewoud Smeur + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter + */ + +#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid.h" +#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.h" +#include "state.h" +#include "generated/modules.h" + +/** + * Calculate the matrix of partial derivatives of the roll, pitch and thrust + * w.r.t. the NED accelerations, taking into account the lift of a wing that is + * horizontal at -90 degrees pitch + * + * @param Gmat Dynamics matrix + * @param a_diff acceleration errors in earth frame + * @param body_v 3D vector to write the control objective v + */ + +void guidance_indi_calcg_wing(float Gmat[GUIDANCE_INDI_HYBRID_V][GUIDANCE_INDI_HYBRID_U], struct FloatVect3 a_diff, float v_gih[GUIDANCE_INDI_HYBRID_V]) { + // Get attitude + struct FloatEulers eulers_zxy; + float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f()); + + + /*Pre-calculate sines and cosines*/ + float sphi = sinf(eulers_zxy.phi); + float cphi = cosf(eulers_zxy.phi); + float stheta = sinf(eulers_zxy.theta); + float ctheta = cosf(eulers_zxy.theta); + float spsi = sinf(eulers_zxy.psi); + float cpsi = cosf(eulers_zxy.psi); + //minus gravity is a guesstimate of the thrust force, thrust measurement would be better + +#ifndef GUIDANCE_INDI_PITCH_EFF_SCALING +#define GUIDANCE_INDI_PITCH_EFF_SCALING 1.0 +#endif + + /*Amount of lift produced by the wing*/ + float pitch_lift = eulers_zxy.theta; + Bound(pitch_lift,-M_PI_2,0); + float lift = sinf(pitch_lift)*9.81; + float T = cosf(pitch_lift)*-9.81; + + // get the derivative of the lift wrt to theta + float liftd = guidance_indi_get_liftd(stateGetAirspeed_f(), eulers_zxy.theta); + + Gmat[0][0] = cphi*ctheta*spsi*T + cphi*spsi*lift; + Gmat[1][0] = -cphi*ctheta*cpsi*T - cphi*cpsi*lift; + Gmat[2][0] = -sphi*ctheta*T -sphi*lift; + Gmat[0][1] = (ctheta*cpsi - sphi*stheta*spsi)*T*GUIDANCE_INDI_PITCH_EFF_SCALING + sphi*spsi*liftd; + Gmat[1][1] = (ctheta*spsi + sphi*stheta*cpsi)*T*GUIDANCE_INDI_PITCH_EFF_SCALING - sphi*cpsi*liftd; + Gmat[2][1] = -cphi*stheta*T*GUIDANCE_INDI_PITCH_EFF_SCALING + cphi*liftd; + Gmat[0][2] = stheta*cpsi + sphi*ctheta*spsi; + Gmat[1][2] = stheta*spsi - sphi*ctheta*cpsi; + Gmat[2][2] = cphi*ctheta; + + v_gih[0] = a_diff.x; + v_gih[1] = a_diff.y; + v_gih[2] = a_diff.z; +} + + +#if GUIDANCE_INDI_HYBRID_USE_WLS + + + +void guidance_indi_hybrid_set_wls_settings(float body_v[3] UNUSED, float roll_angle, float pitch_angle) +{ + // Set lower limits + du_min_gih[0] = -guidance_indi_max_bank - roll_angle; // roll + du_min_gih[1] = RadOfDeg(guidance_indi_min_pitch) - pitch_angle; // pitch + du_min_gih[2] = (MAX_PPRZ - actuator_state_filt_vect[0]) * g1g2[3][0] + (MAX_PPRZ - actuator_state_filt_vect[1]) * g1g2[3][1] + (MAX_PPRZ - actuator_state_filt_vect[2]) * g1g2[3][2] + (MAX_PPRZ - actuator_state_filt_vect[3]) * g1g2[3][3]; + + // Set upper limits limits + du_max_gih[0] = guidance_indi_max_bank - roll_angle; //roll + du_max_gih[1] = RadOfDeg(GUIDANCE_INDI_MAX_PITCH) - pitch_angle; // pitch + du_max_gih[2] = -(actuator_state_filt_vect[0]*g1g2[3][0] + actuator_state_filt_vect[1]*g1g2[3][1] + actuator_state_filt_vect[2]*g1g2[3][2] + actuator_state_filt_vect[3]*g1g2[3][3]); + + // Set prefered states + du_pref_gih[0] = -roll_angle; // prefered delta roll angle + du_pref_gih[1] = -pitch_angle; // prefered delta pitch angle + du_pref_gih[2] = du_max_gih[2]; +} + + +#endif + + diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitters.h b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.h similarity index 82% rename from sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitters.h rename to sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.h index e0f4165de6..3d33ee125c 100644 --- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitters.h +++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid_tailsitter.h @@ -19,15 +19,15 @@ * Boston, MA 02111-1307, USA. */ +#ifndef GUIDANCE_INDI_HYBRID_TAILSITTER +#define GUIDANCE_INDI_HYBRID_TAILSITTER -// Guidance actuators: (roll, pitch, thrust) for tailsitters -#define GUIDANCE_INDI_HYBRID_U 3 - -// Guidance control objectives: ax, ay, ay for tailsitters -#define GUIDANCE_INDI_HYBRID_V 3 #ifndef GUIDANCE_INDI_MIN_PITCH #define GUIDANCE_INDI_MIN_PITCH -120 #define GUIDANCE_INDI_MAX_PITCH 25 #endif + + +#endif // GUIDANCE_INDI_HYBRID_TAILSITTER \ No newline at end of file