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 d85cf8c309..60bc43d668 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
@@ -133,9 +133,7 @@
-
-
-
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
index ce3adc8c25..1cf9ae7201 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop.xml
@@ -138,9 +138,7 @@
-
-
-
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
index 98ad2de41f..38044f59e2 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack.xml
@@ -140,9 +140,7 @@
-
-
-
+
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 067a355951..c084012f24 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_optitrack_ext_pose.xml
@@ -131,9 +131,7 @@
-
-
-
+
@@ -216,7 +214,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml b/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
index f953d78602..19b1a6a441 100644
--- a/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
+++ b/conf/airframes/tudelft/rotwing_v3c_oneloop_simulation.xml
@@ -99,11 +99,7 @@
-
-
-
-
-
+
@@ -186,7 +182,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -264,26 +277,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml
new file mode 100644
index 0000000000..57d4538da2
--- /dev/null
+++ b/conf/airframes/tudelft/rotwing_v3g_oneloop_optitrack_ext_pose.xml
@@ -0,0 +1,373 @@
+
+
+
+ RotatingWingV3G with optitrack and INS ext pose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 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/autopilot/rotorcraft_oneloop_switch.xml b/conf/autopilot/rotorcraft_oneloop_switch.xml
index c0d2baf611..784ec2c589 100644
--- a/conf/autopilot/rotorcraft_oneloop_switch.xml
+++ b/conf/autopilot/rotorcraft_oneloop_switch.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/conf/flight_plans/tudelft/oneloop_valkenburg.xml b/conf/flight_plans/tudelft/oneloop_valkenburg.xml
index ab8b4d57b5..7879814cd1 100644
--- a/conf/flight_plans/tudelft/oneloop_valkenburg.xml
+++ b/conf/flight_plans/tudelft/oneloop_valkenburg.xml
@@ -60,6 +60,11 @@
+
+
+
+
+
-
+
-
+
-
+
-
-
+
-
-
-
-
+
+
+
-
-
+
-
+
-
-
-
+
+
-
-
-
+
+
-
-
-
+
+
-
-
-
+
+
-
+
-
-
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
-
-
+
+
diff --git a/conf/modules/eff_scheduling_rotwing.xml b/conf/modules/eff_scheduling_rotwing.xml
index 0d206200d0..331b41da3b 100644
--- a/conf/modules/eff_scheduling_rotwing.xml
+++ b/conf/modules/eff_scheduling_rotwing.xml
@@ -55,7 +55,7 @@
-
+
@@ -70,6 +70,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/conf/modules/rotwing_state_V2.xml b/conf/modules/rotwing_state_V2.xml
deleted file mode 100644
index 9e84dfd830..0000000000
--- a/conf/modules/rotwing_state_V2.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- This module keeps track of the current state of a rotating wing drone and desired state set by the RC or flightplan. Paramters are being scheduled in each change of a current state and desired state. Functions are defined in this module to call the actual state and desired state and set a desired state.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c
index 9cb80b584d..bbeabaff91 100644
--- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c
+++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.c
@@ -411,7 +411,7 @@ void guidance_indi_enter(void)
init_butterworth_2_low_pass(&guidance_indi_airspeed_filt, tau_guidance_indi_airspeed, sample_time, 0.0);
}
-void guidance_indi_set_min_max_airspeed(float min_airspeed, float max_airspeed) {
+void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed) {
gih_params.min_airspeed = min_airspeed;
gih_params.max_airspeed = max_airspeed;
}
diff --git a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h
index fb7a9f0b3d..408e49fc33 100644
--- a/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h
+++ b/sw/airborne/firmwares/rotorcraft/guidance/guidance_indi_hybrid.h
@@ -70,7 +70,7 @@ enum GuidanceIndiHybrid_VMode {
extern struct StabilizationSetpoint guidance_indi_run(struct FloatVect3 *accep_sp, float heading_sp);
extern struct StabilizationSetpoint guidance_indi_run_mode(bool in_flight, struct HorizontalGuidance *gh, struct VerticalGuidance *gv, enum GuidanceIndiHybrid_HMode h_mode, enum GuidanceIndiHybrid_VMode v_mode);
-extern void guidance_indi_set_min_max_airspeed(float min_airspeed, float max_airspeed);
+extern void guidance_set_min_max_airspeed(float min_airspeed, float max_airspeed);
struct guidance_indi_hybrid_params {
float pos_gain;
diff --git a/sw/airborne/modules/ctrl/eff_scheduling_rotwing.c b/sw/airborne/modules/ctrl/eff_scheduling_rotwing.c
index 5197cf1c63..d9ca4a9a42 100644
--- a/sw/airborne/modules/ctrl/eff_scheduling_rotwing.c
+++ b/sw/airborne/modules/ctrl/eff_scheduling_rotwing.c
@@ -29,7 +29,8 @@
#include "state.h"
#include "firmwares/rotorcraft/stabilization/stabilization_indi.h"
-
+#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid.h"
+#include "modules/rotwing_drone/rotwing_state.h"
#include "autopilot.h"
#include "modules/actuators/actuators.h"
@@ -173,6 +174,8 @@ inline float bound_or_zero(float value, float low_lim, float up_lim) {
float eff_sched_pusher_time = 0.002;
float roll_eff_slider = 12.f;
+static const float Wu_gih_original[GUIDANCE_INDI_HYBRID_U] = GUIDANCE_INDI_WLS_WU;
+
struct rotwing_eff_sched_var_t eff_sched_var;
inline void eff_scheduling_rotwing_update_wing_angle(void);
@@ -189,6 +192,7 @@ inline void eff_scheduling_rotwing_schedule_liftd(void);
inline float guidance_indi_get_liftd(float pitch UNUSED, float theta UNUSED);
void stabilization_indi_set_wls_settings(void);
+inline void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle);
/** ABI binding wing position data.
@@ -496,3 +500,91 @@ void stabilization_indi_set_wls_settings(void)
}
}
}
+
+void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
+{
+ // adjust weights
+ float fixed_wing_percentile = (rotwing_state_hover_motors_idling())? 1:0; // TODO: when hover props go below 40%, ...
+ Bound(fixed_wing_percentile, 0, 1);
+#define AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT 16
+
+ float Wv_original[GUIDANCE_INDI_HYBRID_V] = GUIDANCE_INDI_WLS_PRIORITIES;
+
+ // Increase importance of forward acceleration in forward flight
+ wls_guid_p.Wv[0] = Wv_original[0] * (1.0f + fixed_wing_percentile *
+ AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT); // stall n low hover motor_off (weight 16x more important than vertical weight)
+
+ struct FloatEulers eulers_zxy;
+ float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f());
+
+ float du_min_thrust_z = ((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]) * rotwing_state_hover_motors_running();
+ Bound(du_min_thrust_z, -50., 0.);
+ float du_max_thrust_z = -(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]);
+ Bound(du_max_thrust_z, 0., 50.);
+
+ float roll_limit_rad = guidance_indi_max_bank;
+ float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
+ float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH);
+
+ float fwd_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
+ float quad_pitch_limit_rad = RadOfDeg(5.0);
+
+ float airspeed = stateGetAirspeed_f();
+
+ float scheduled_pitch_angle = 0.f;
+ float pitch_angle_range = 3.;
+ float meas_skew_angle = rotwing_state.meas_skew_angle_deg;
+ Bound(meas_skew_angle, 0, 90); // Bound to prevent errors
+ if (meas_skew_angle < ROTWING_SKEW_ANGLE_STEP) {
+ scheduled_pitch_angle = ROTWING_QUAD_PREF_PITCH;
+ wls_guid_p.Wu[1] = Wu_gih_original[1];
+ max_pitch_limit_rad = quad_pitch_limit_rad;
+ } else {
+ float pitch_progression = (airspeed - rotwing_state.fw_min_airspeed) / 2.f;
+ Bound(pitch_progression, 0.f, 1.f);
+ scheduled_pitch_angle = pitch_angle_range * pitch_progression + ROTWING_QUAD_PREF_PITCH*(1.f-pitch_progression);
+ wls_guid_p.Wu[1] = Wu_gih_original[1] * (1.f - pitch_progression*0.99);
+ max_pitch_limit_rad = quad_pitch_limit_rad + (fwd_pitch_limit_rad - quad_pitch_limit_rad) * pitch_progression;
+ }
+ if (!rotwing_state_hover_motors_running()) {
+ scheduled_pitch_angle = 8.;
+ max_pitch_limit_rad = fwd_pitch_limit_rad;
+ }
+ Bound(scheduled_pitch_angle, -5., 8.);
+ guidance_indi_pitch_pref_deg = scheduled_pitch_angle;
+
+ float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg);
+
+ // Set lower limits
+ wls_guid_p.u_min[0] = -roll_limit_rad - roll_angle; //roll
+ wls_guid_p.u_min[1] = min_pitch_limit_rad - pitch_angle; // pitch
+
+ // Set upper limits limits
+ wls_guid_p.u_max[0] = roll_limit_rad - roll_angle; //roll
+ wls_guid_p.u_max[1] = max_pitch_limit_rad - pitch_angle; // pitch
+
+ if(rotwing_state_hover_motors_running()) {
+ wls_guid_p.u_min[2] = du_min_thrust_z;
+ wls_guid_p.u_max[2] = du_max_thrust_z;
+ } else {
+ wls_guid_p.u_min[2] = 0.;
+ wls_guid_p.u_max[2] = 0.;
+ }
+
+ if(rotwing_state_pusher_motor_running()) {
+ wls_guid_p.u_min[3] = (-actuator_state_filt_vect[8] * g1g2[4][8]);
+ wls_guid_p.u_max[3] = 9.0; // Hacky value to prevent drone from pitching down in transition
+ } else {
+ wls_guid_p.u_min[3] = 0.;
+ wls_guid_p.u_max[3] = 0.;
+ }
+
+ // Set prefered states
+ wls_guid_p.u_pref[0] = 0; // prefered delta roll angle
+ wls_guid_p.u_pref[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle
+ wls_guid_p.u_pref[2] = wls_guid_p.u_max[2]; // Low thrust better for efficiency
+ wls_guid_p.u_pref[3] = body_v[0]; // solve the body acceleration
+}
\ No newline at end of file
diff --git a/sw/airborne/modules/rotwing_drone/rotwing_state.c b/sw/airborne/modules/rotwing_drone/rotwing_state.c
index 500956c40a..63d509b030 100644
--- a/sw/airborne/modules/rotwing_drone/rotwing_state.c
+++ b/sw/airborne/modules/rotwing_drone/rotwing_state.c
@@ -24,13 +24,12 @@
*/
#include "modules/rotwing_drone/rotwing_state.h"
-#include "firmwares/rotorcraft/stabilization/stabilization_indi.h"
-#include "firmwares/rotorcraft/guidance/guidance_indi_hybrid.h"
#include "firmwares/rotorcraft/autopilot_firmware.h"
-
+#include "modules/core/commands.h"
#include "modules/actuators/actuators.h"
#include "modules/core/abi.h"
+
/* Minimum measured RPM to consider the hover motors running (RPM) */
#ifndef ROTWING_QUAD_MIN_RPM
#define ROTWING_QUAD_MIN_RPM 400
@@ -61,11 +60,6 @@
#define ROTWING_FW_SKEW_ANGLE 85.0
#endif
-/* Magnitude skew angle jump away from quad */
-#ifndef ROTWING_SKEW_ANGLE_STEP
-#define ROTWING_SKEW_ANGLE_STEP 55.0
-#endif
-
/* TODO: Give a name.... */
#ifndef ROTWING_SKEW_BACK_MARGIN
#define ROTWING_SKEW_BACK_MARGIN 5.0
@@ -81,11 +75,6 @@
#define ROTWING_MIN_AIRSPEED_SLOPE_START_ANGLE 30.0
#endif
-/* Preferred pitch angle for the quad mode (deg) */
-#ifndef ROTWING_QUAD_PREF_PITCH
-#define ROTWING_QUAD_PREF_PITCH -5.0
-#endif
-
/* Amount of time the airspeed needs to be below the FW_MIN_AIRSPEED */
#ifndef ROTWING_FW_STALL_TIMEOUT
#define ROTWING_FW_STALL_TIMEOUT 0.5
@@ -107,13 +96,7 @@
#endif
abi_event rotwing_state_feedback_ev;
static void rotwing_state_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback_msg, uint8_t num_act);
-
-static bool rotwing_state_hover_motors_idling(void);
-static const float Wu_gih_original[GUIDANCE_INDI_HYBRID_U] = GUIDANCE_INDI_WLS_WU;
struct rotwing_state_t rotwing_state;
-
-inline void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle);
-
#if PERIODIC_TELEMETRY
#include "modules/datalink/telemetry.h"
static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
@@ -164,7 +147,6 @@ void rotwing_state_init(void)
rotwing_state.fail_hover_motor = false;
rotwing_state.fail_pusher_motor = false;
rotwing_state.ref_model_skew_angle_deg = 0;
-
// Bind ABI messages
AbiBindMsgACT_FEEDBACK(ROTWING_STATE_ACT_FEEDBACK_ID, &rotwing_state_feedback_ev, rotwing_state_feedback_cb);
@@ -177,7 +159,7 @@ void rotwing_state_init(void)
* @brief Check if hover motors are idling (COMMAND_THRUST < ROTWING_QUAD_IDLE_MIN_THRUST) for ROTWING_QUAD_IDLE_TIMEOUT time
* @return true if hover motors are idling, false otherwise
*/
-static bool rotwing_state_hover_motors_idling(void) {
+bool rotwing_state_hover_motors_idling(void) {
static float last_idle_time = 0;
// Check if hover motors are idling and reset timer
if(stabilization.cmd[COMMAND_THRUST] > ROTWING_QUAD_IDLE_MIN_THRUST) {
@@ -306,9 +288,7 @@ void rotwing_state_periodic(void)
rotwing_state.max_airspeed = 0; // Max airspeed FW
}*/
- guidance_indi_set_min_max_airspeed(rotwing_state.min_airspeed, rotwing_state.max_airspeed);
-
-
+ guidance_set_min_max_airspeed(rotwing_state.min_airspeed, rotwing_state.max_airspeed);
/* Set navigation/guidance settings */
nav_max_deceleration_sp = ROTWING_FW_MAX_DECELERATION * meas_skew_angle / 90.f + ROTWING_QUAD_MAX_DECELERATION * (90.f - meas_skew_angle) / 90.f; //TODO: Do we really want to based this on the skew?
@@ -333,13 +313,18 @@ void rotwing_state_periodic(void)
#else
rotwing_state.skew_cmd = servo_pprz_cmd;
#endif
-
+#ifdef COMMAND_ROT_MECH
+ commands[COMMAND_ROT_MECH] = rotwing_state.skew_cmd;
+#endif
/* Add simulation feedback for the skewing and RPM */
#if USE_NPS
// Export to the index of the SKEW in the NPS_ACTUATOR_NAMES array
+#ifdef COMMAND_ROT_MECH
+ commands[COMMAND_ROT_MECH] = (rotwing_state.skew_cmd + MAX_PPRZ) / 2.f; // Scale to simulation command
+#else
actuators_pprz[INDI_NUM_ACT] = (rotwing_state.skew_cmd + MAX_PPRZ) / 2.f; // Scale to simulation command
-
+#endif
// SEND ABI Message to ctr_eff_sched, ourself and other modules that want Actuator position feedback
struct act_feedback_t feedback;
feedback.idx = SERVO_ROTATION_MECH_IDX;
@@ -448,94 +433,6 @@ bool rotwing_state_skew_angle_valid(void) {
return (!skew_timeout && skew_angle_match);
}
-void guidance_indi_hybrid_set_wls_settings(float body_v[3], float roll_angle, float pitch_angle)
-{
- // adjust weights
- float fixed_wing_percentile = (rotwing_state_hover_motors_idling())? 1:0; // TODO: when hover props go below 40%, ...
- Bound(fixed_wing_percentile, 0, 1);
-#define AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT 16
-
- float Wv_original[GUIDANCE_INDI_HYBRID_V] = GUIDANCE_INDI_WLS_PRIORITIES;
-
- // Increase importance of forward acceleration in forward flight
- wls_guid_p.Wv[0] = Wv_original[0] * (1.0f + fixed_wing_percentile *
- AIRSPEED_IMPORTANCE_IN_FORWARD_WEIGHT); // stall n low hover motor_off (weight 16x more important than vertical weight)
-
- struct FloatEulers eulers_zxy;
- float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f());
-
- float du_min_thrust_z = ((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]) * rotwing_state_hover_motors_running();
- Bound(du_min_thrust_z, -50., 0.);
- float du_max_thrust_z = -(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]);
- Bound(du_max_thrust_z, 0., 50.);
-
- float roll_limit_rad = guidance_indi_max_bank;
- float max_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
- float min_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MIN_PITCH);
-
- float fwd_pitch_limit_rad = RadOfDeg(GUIDANCE_INDI_MAX_PITCH);
- float quad_pitch_limit_rad = RadOfDeg(5.0);
-
- float airspeed = stateGetAirspeed_f();
-
- float scheduled_pitch_angle = 0.f;
- float pitch_angle_range = 3.;
- float meas_skew_angle = rotwing_state.meas_skew_angle_deg;
- Bound(meas_skew_angle, 0, 90); // Bound to prevent errors
- if (meas_skew_angle < ROTWING_SKEW_ANGLE_STEP) {
- scheduled_pitch_angle = ROTWING_QUAD_PREF_PITCH;
- wls_guid_p.Wu[1] = Wu_gih_original[1];
- max_pitch_limit_rad = quad_pitch_limit_rad;
- } else {
- float pitch_progression = (airspeed - rotwing_state.fw_min_airspeed) / 2.f;
- Bound(pitch_progression, 0.f, 1.f);
- scheduled_pitch_angle = pitch_angle_range * pitch_progression + ROTWING_QUAD_PREF_PITCH*(1.f-pitch_progression);
- wls_guid_p.Wu[1] = Wu_gih_original[1] * (1.f - pitch_progression*0.99);
- max_pitch_limit_rad = quad_pitch_limit_rad + (fwd_pitch_limit_rad - quad_pitch_limit_rad) * pitch_progression;
- }
- if (!rotwing_state_hover_motors_running()) {
- scheduled_pitch_angle = 8.;
- max_pitch_limit_rad = fwd_pitch_limit_rad;
- }
- Bound(scheduled_pitch_angle, -5., 8.);
- guidance_indi_pitch_pref_deg = scheduled_pitch_angle;
-
- float pitch_pref_rad = RadOfDeg(guidance_indi_pitch_pref_deg);
-
- // Set lower limits
- wls_guid_p.u_min[0] = -roll_limit_rad - roll_angle; //roll
- wls_guid_p.u_min[1] = min_pitch_limit_rad - pitch_angle; // pitch
-
- // Set upper limits limits
- wls_guid_p.u_max[0] = roll_limit_rad - roll_angle; //roll
- wls_guid_p.u_max[1] = max_pitch_limit_rad - pitch_angle; // pitch
-
- if(rotwing_state_hover_motors_running()) {
- wls_guid_p.u_min[2] = du_min_thrust_z;
- wls_guid_p.u_max[2] = du_max_thrust_z;
- } else {
- wls_guid_p.u_min[2] = 0.;
- wls_guid_p.u_max[2] = 0.;
- }
-
- if(rotwing_state_pusher_motor_running()) {
- wls_guid_p.u_min[3] = (-actuator_state_filt_vect[8] * g1g2[4][8]);
- wls_guid_p.u_max[3] = 9.0; // Hacky value to prevent drone from pitching down in transition
- } else {
- wls_guid_p.u_min[3] = 0.;
- wls_guid_p.u_max[3] = 0.;
- }
-
- // Set prefered states
- wls_guid_p.u_pref[0] = 0; // prefered delta roll angle
- wls_guid_p.u_pref[1] = -pitch_angle + pitch_pref_rad;// prefered delta pitch angle
- wls_guid_p.u_pref[2] = wls_guid_p.u_max[2]; // Low thrust better for efficiency
- wls_guid_p.u_pref[3] = body_v[0]; // solve the body acceleration
-}
-
void rotwing_state_set(enum rotwing_states_t state) {
rotwing_state.nav_state = state;
}
diff --git a/sw/airborne/modules/rotwing_drone/rotwing_state.h b/sw/airborne/modules/rotwing_drone/rotwing_state.h
index cfb03d887c..9d1db31259 100644
--- a/sw/airborne/modules/rotwing_drone/rotwing_state.h
+++ b/sw/airborne/modules/rotwing_drone/rotwing_state.h
@@ -28,6 +28,16 @@
#include "std.h"
+/* Magnitude skew angle jump away from quad */
+#ifndef ROTWING_SKEW_ANGLE_STEP
+#define ROTWING_SKEW_ANGLE_STEP 55.0
+#endif
+
+/* Preferred pitch angle for the quad mode (deg) */
+#ifndef ROTWING_QUAD_PREF_PITCH
+#define ROTWING_QUAD_PREF_PITCH -5.0
+#endif
+
enum rotwing_states_t {
ROTWING_STATE_FORCE_HOVER,
ROTWING_STATE_REQUEST_HOVER,
@@ -84,6 +94,7 @@ void rotwing_state_periodic(void);
bool rotwing_state_hover_motors_running(void);
bool rotwing_state_pusher_motor_running(void);
bool rotwing_state_skew_angle_valid(void);
+bool rotwing_state_hover_motors_idling(void);
void rotwing_state_set(enum rotwing_states_t state);
bool rotwing_state_choose_circle_direction(uint8_t wp_id);
diff --git a/sw/airborne/modules/rotwing_drone/rotwing_state_V2.c b/sw/airborne/modules/rotwing_drone/rotwing_state_V2.c
deleted file mode 100644
index 6a9d517736..0000000000
--- a/sw/airborne/modules/rotwing_drone/rotwing_state_V2.c
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
- * Copyright (C) 2023 Tomaso De Ponti
- *
- * 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, see
- * .
- */
-
-/** @file "modules/rotwing/rotwing_state_V2.c"
- * @author Tomaso De Ponti
- * This module keeps track of the current state of a rotating wing drone and desired state set by the RC or flightplan. Paramters are being scheduled in each change of a current state and desired state. Functions are defined in this module to call the actual state and desired state and set a desired state.
- */
-
-#include "modules/rotwing_drone/rotwing_state_V2.h"
-#include "firmwares/rotorcraft/autopilot_firmware.h"
-#include "modules/core/commands.h"
-#include "modules/actuators/actuators.h"
-#include "modules/core/abi.h"
-
-// Quad state identification
-#ifndef ROTWING_MIN_SKEW_ANGLE_DEG_QUAD
-#define ROTWING_MIN_SKEW_ANGLE_DEG_QUAD 10.0
-#endif
-
-#ifndef ROTWING_MIN_SKEW_ANGLE_COUNTER
-#define ROTWING_MIN_SKEW_ANGLE_COUNTER 10 // Minimum number of loops the skew angle is below ROTWING_MIN_SKEW_ANGLE_COUNTER
-#endif
-
-// Skewing state identification
-#ifndef ROTWING_SKEWING_COUNTER
-#define ROTWING_SKEWING_COUNTER 10 // Minimum number of loops the skew angle is in between QUAD and FW
-#endif
-
-// maximum quad airspeed to force quad state
-#ifndef ROTWING_MAX_QUAD_AIRSPEED
-#define ROTWING_MAX_QUAD_AIRSPEED 20.0
-#endif
-
-// Half skew state identification
-#ifndef ROTWING_HALF_SKEW_ANGLE_DEG
-#define ROTWING_HALF_SKEW_ANGLE_DEG 55.0
-#endif
-
-#ifndef ROTWING_HALF_SKEW_ANGLE_RANG
-#define ROTWING_HALF_SKEW_ANGLE_HALF_RANGE 10.0
-#endif
-
-#ifndef ROTWING_HALF_SKEW_COUNTER
-#define ROTWING_HALF_SKEW_COUNTER 10 // Minimum number of loops the skew angle is at HALF_SKEW_ANGLE_DEG +/- ROTWING_HALF_SKEW_ANGLE_HALF_RANGE to trigger ROTWING_HALF_SKEW_ANGLE state
-#endif
-
-// FW state identification
-#ifndef ROTWING_MIN_FW_SKEW_ANGLE_DEG
-#define ROTWING_MIN_FW_SKEW_ANGLE_DEG 80.0 // Minimum wing angle to fly in fixed wing state
-#endif
-
-#ifndef ROTWING_MIN_FW_COUNTER
-#define ROTWING_MIN_FW_COUNTER 10 // Minimum number of loops the skew angle is above the MIN_FW_SKEW_ANGLE
-#endif
-
-// FW idle state identification
-#ifndef ROTWING_MIN_THRUST_IDLE
-#define ROTWING_MIN_THRUST_IDLE 100
-#endif
-
-#ifndef ROTWING_MIN_THRUST_IDLE_COUNTER
-#define ROTWING_MIN_THRUST_IDLE_COUNTER 10
-#endif
-
-// FW hov mot off state identification
-#ifndef ROTWING_HOV_MOT_RUN_RPM_TH
-#define ROTWING_HOV_MOT_RUN_RPM_TH 800
-#endif
-#ifndef ROTWING_HOV_MOT_OFF_RPM_TH
-#define ROTWING_HOV_MOT_OFF_RPM_TH 50
-#endif
-
-#ifndef ROTWING_HOV_MOT_OFF_COUNTER
-#define ROTWING_HOV_MOT_OFF_COUNTER 10
-#endif
-
-#ifndef ROTWING_STATE_USE_ROTATION_REF_MODEL
-#define ROTWING_STATE_USE_ROTATION_REF_MODEL FALSE
-#endif
-
-// Hover preferred pitch (deg)
-#ifndef ROTWING_STATE_HOVER_PREF_PITCH
-#define ROTWING_STATE_HOVER_PREF_PITCH 0.0
-#endif
-
-// Transition preferred pitch (deg)
-#ifndef ROTWING_STATE_TRANSITION_PREF_PITCH
-#define ROTWING_STATE_TRANSITION_PREF_PITCH 3.0
-#endif
-
-// Forward preferred pitch (deg)
-#ifndef ROTWING_STATE_FW_PREF_PITCH
-#define ROTWING_STATE_FW_PREF_PITCH 8.0
-#endif
-
-// Make sure the rotmech dynamics are provided if the virtual rotmech is used
-#ifndef USE_ROTMECH_VIRTUAL
-#define USE_ROTMECH_VIRTUAL FALSE
-#endif
-
-#if USE_ROTMECH_VIRTUAL
-#ifndef ROTMECH_DYN
-#error "Rotmech dynamics are not provided. Please provide them in your airframe file."
-#endif
-#endif
-
-// stream ADC data if ADC rotation sensor
-#ifndef ADC_WING_ROTATION
-#define ADC_WING_ROTATION FALSE
-#endif
-#if ADC_WING_ROTATION
-#include "wing_rotation_adc_sensor.h"
-#endif
-/** ABI binding feedback data.
- */
-#ifndef ROTWING_STATE_ACT_FEEDBACK_ID
-#define ROTWING_STATE_ACT_FEEDBACK_ID ABI_BROADCAST
-#endif
-abi_event rotwing_state_feedback_ev;
-static void rotwing_state_feedback_cb(uint8_t sender_id, struct act_feedback_t *feedback_msg, uint8_t num_act);
-#define ROTWING_STATE_NUM_HOVER_RPM 4
-int32_t rotwing_state_hover_rpm[ROTWING_STATE_NUM_HOVER_RPM] = {0, 0, 0, 0};
-
-struct RotwingState rotwing_state;
-struct RotWingStateSettings rotwing_state_settings;
-struct RotWingStateSkewing rotwing_state_skewing;
-
-uint8_t rotwing_state_hover_counter = 0;
-uint8_t rotwing_state_skewing_counter = 0;
-uint8_t rotwing_state_fw_counter = 0;
-uint8_t rotwing_state_fw_idle_counter = 0;
-uint8_t rotwing_state_fw_m_off_counter = 0;
-
-float rotwing_state_max_hover_speed = 7;
-#ifdef NAV_HYBRID_MAX_AIRSPEED
-float rotwing_state_max_fw_speed = NAV_HYBRID_MAX_AIRSPEED;
-#else
-float rotwing_state_max_fw_speed = 20;
-#endif
-
-bool hover_motors_active = true;
-bool bool_disable_hover_motors = false;
-//DEMO Sine skew
-bool demo_skew = false;
-float max_skew_demo = 50;
-float min_skew_demo = 0;
-float freq_skew_demo = 0.8;
-int time_step_skew_demo = 0;
-
-
-inline void rotwing_check_set_current_state(void);
-inline void rotwing_switch_state(void);
-
-inline void rotwing_state_set_hover_settings(void);
-inline void rotwing_state_set_skewing_settings(void);
-inline void rotwing_state_set_fw_settings(void);
-inline void rotwing_state_set_fw_hov_mot_idle_settings(void);
-inline void rotwing_state_set_fw_hov_mot_off_settings(void);
-
-inline void rotwing_state_set_state_settings(void);
-inline void rotwing_state_skewer(void);
-inline void rotwing_state_free_processor(void);
-
-#if PERIODIC_TELEMETRY
-#include "modules/datalink/telemetry.h"
-static void send_rotating_wing_state(struct transport_tx *trans, struct link_device *dev)
-{
- uint16_t dummy = 0;
- float nav_airspeed = stateGetAirspeed_f();;
- float min_airspeed = 0;
- float max_airspeed = rotwing_state_max_fw_speed;
-
- pprz_msg_send_ROTATING_WING_STATE(trans, dev, AC_ID,
- &rotwing_state.current_state,
- &rotwing_state.desired_state,
- &dummy,
- &rotwing_state_skewing.wing_angle_deg,
- &rotwing_state_skewing.wing_angle_deg_sp,
- &nav_airspeed,
- &min_airspeed,
- &max_airspeed);
-}
-#endif // PERIODIC_TELEMETRY
-
-void rotwing_state_force_skew_off(void)
-{
- rotwing_state_skewing.force_rotation_angle = false;
- demo_skew = false;
-}
-
-void init_rotwing_state(void)
-{
- // Bind ABI messages
- AbiBindMsgACT_FEEDBACK(ROTWING_STATE_ACT_FEEDBACK_ID, &rotwing_state_feedback_ev, rotwing_state_feedback_cb);
-
- // Start the drone in a desired hover state
- rotwing_state.current_state = ROTWING_STATE_HOVER;
- rotwing_state.desired_state = ROTWING_STATE_HOVER;
- rotwing_state.requested_config = ROTWING_CONFIGURATION_HOVER;
-
- rotwing_state_settings.preferred_pitch_value = 0;
-
- rotwing_state_skewing.wing_angle_deg_sp = 0;
- rotwing_state_skewing.wing_angle_deg = 0;
- rotwing_state_skewing.servo_pprz_cmd = -MAX_PPRZ;
- rotwing_state_skewing.airspeed_scheduling = false;
- rotwing_state_skewing.force_rotation_angle = false;
- demo_skew = false;
-
-#if PERIODIC_TELEMETRY
- register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_ROTATING_WING_STATE, send_rotating_wing_state);
-#endif
-}
-
-void periodic_rotwing_state(void)
-{
- // Check and set the current state
- rotwing_check_set_current_state();
-
- // Check and update desired state
- if (guidance_h.mode == GUIDANCE_H_MODE_NAV) {
- // Run the free state requester if free configuration requestes
- if(rotwing_state.requested_config == ROTWING_CONFIGURATION_FREE) {
- rotwing_state_free_processor();
- }
- rotwing_switch_state();
- } else if (guidance_h.mode == GUIDANCE_H_MODE_NONE) {
- if (stabilization.mode == STABILIZATION_MODE_ATTITUDE) {
- if (stabilization.att_submode == STABILIZATION_ATT_SUBMODE_FORWARD) {
- rotwing_state_set_fw_settings();
- } else {
- rotwing_state_set_hover_settings();
- }
- }
- }
- // } else {
- // rotwing_switch_state();
- // }
-
- // Run the wing skewer
- rotwing_state_skewer();
-
- //TODO: incorparate motor active / disbaling depending on called flight state
- // Switch on motors if flight mode is attitude
- if (guidance_h.mode == GUIDANCE_H_MODE_NONE) {
- bool_disable_hover_motors = false;
- }
- struct FloatEulers eulers_zxy;
- float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f());
-
- // Evaluate motors_on boolean
- if (!hover_motors_active) {
- if (stateGetAirspeed_f() < 15.) {
- hover_motors_active = true;
- bool_disable_hover_motors = false;
- } else if (eulers_zxy.theta > RadOfDeg(15.0)) {
- hover_motors_active = true;
- bool_disable_hover_motors = false;
- }
- } else {
- bool_disable_hover_motors = false;
- }
- float pitch_progression = (rotwing_state_skewing.wing_angle_deg - ROTWING_HALF_SKEW_ANGLE_DEG) / (90.0-ROTWING_HALF_SKEW_ANGLE_DEG);
- // Calculate scheduled pitch angle
- switch (rotwing_state_settings.preferred_pitch_setting){
- case ROTWING_STATE_PITCH_QUAD_SETTING:
- rotwing_state_settings.preferred_pitch_value = RadOfDeg(ROTWING_STATE_HOVER_PREF_PITCH);
- break;
- case ROTWING_STATE_PITCH_TRANSITION_SETTING:
- rotwing_state_settings.preferred_pitch_value = RadOfDeg(ROTWING_STATE_TRANSITION_PREF_PITCH * pitch_progression);
- break;
- case ROTWING_STATE_PITCH_FW_SETTING:
- rotwing_state_settings.preferred_pitch_value = RadOfDeg(ROTWING_STATE_FW_PREF_PITCH);
- break;
- }
-}
-
-// Function to request a state
-void request_rotwing_state(uint8_t state)
-{
- if (state <= ROTWING_STATE_FW_HOV_MOT_OFF) {
- rotwing_state.desired_state = state;
- }
-}
-
-// Function to prefer configuration
-void rotwing_request_configuration(uint8_t configuration)
-{
- switch (configuration) {
- case ROTWING_CONFIGURATION_HOVER:
- request_rotwing_state(ROTWING_STATE_HOVER);
- rotwing_state.requested_config = ROTWING_CONFIGURATION_HOVER;
- break;
- case ROTWING_CONFIGURATION_HYBRID:
- request_rotwing_state(ROTWING_STATE_SKEWING);
- rotwing_state.requested_config = ROTWING_CONFIGURATION_HYBRID;
- break;
- case ROTWING_CONFIGURATION_EFFICIENT:
- request_rotwing_state(ROTWING_STATE_FW_HOV_MOT_OFF);
- rotwing_state.requested_config = ROTWING_CONFIGURATION_EFFICIENT;
- break;
- case ROTWING_CONFIGURATION_FREE:
- rotwing_state.requested_config = ROTWING_CONFIGURATION_FREE;
- break;
- }
-}
-
-void rotwing_check_set_current_state(void)
-{
- float current_thrust = (commands[COMMAND_MOTOR_FRONT] + commands[COMMAND_MOTOR_RIGHT] + commands[COMMAND_MOTOR_BACK] + commands[COMMAND_MOTOR_LEFT])/4.0;
- // if !in_flight, set state to hover
- if (!autopilot.in_flight) {
- rotwing_state_hover_counter = 0;
- rotwing_state_skewing_counter = 0;
- rotwing_state_fw_counter = 0;
- rotwing_state_fw_idle_counter = 0;
- rotwing_state_fw_m_off_counter = 0;
- rotwing_state.current_state = ROTWING_STATE_HOVER;
- return;
- }
-
- // States can be checked according to wing angle sensor, setpoints .....
- uint8_t prev_state = rotwing_state.current_state;
- switch (prev_state) {
- case ROTWING_STATE_HOVER:
- // Check if state needs to be set to skewing
- if (rotwing_state_skewing.wing_angle_deg > ROTWING_MIN_SKEW_ANGLE_DEG_QUAD) {
- rotwing_state_skewing_counter++;
- } else {
- rotwing_state_skewing_counter = 0;
- }
-
- // Switch state if necessary
- if (rotwing_state_skewing_counter > ROTWING_MIN_SKEW_ANGLE_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_SKEWING;
- rotwing_state_skewing_counter = 0;
- }
- break;
-
- case ROTWING_STATE_SKEWING:
- // Check if state needs to be set to hover
- if (rotwing_state_skewing.wing_angle_deg < ROTWING_MIN_SKEW_ANGLE_DEG_QUAD) {
- rotwing_state_hover_counter++;
- } else {
- rotwing_state_hover_counter = 0;
- }
-
- // Check if state needs to be set to fixed wing
- if (rotwing_state_skewing.wing_angle_deg > ROTWING_MIN_FW_SKEW_ANGLE_DEG) {
- rotwing_state_fw_counter++;
- } else {
- rotwing_state_fw_counter = 0;
- }
-
- // Switch state if necessary
- if (rotwing_state_hover_counter > ROTWING_MIN_SKEW_ANGLE_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_HOVER;
- rotwing_state_hover_counter = 0;
- }
-
- if (rotwing_state_fw_counter > ROTWING_MIN_FW_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_FW;
- rotwing_state_fw_counter = 0;
- }
- break;
-
- case ROTWING_STATE_FW:
- // Check if state needs to be set to skewing
- if (rotwing_state_skewing.wing_angle_deg < ROTWING_MIN_FW_SKEW_ANGLE_DEG) {
- rotwing_state_skewing_counter++;
- } else {
- rotwing_state_skewing_counter = 0;
- }
-
- // Check if state needs to be set to fixed wing with hover motors idle (If hover thrust below threshold)
- if (current_thrust < ROTWING_MIN_THRUST_IDLE && rotwing_state.desired_state > ROTWING_STATE_FW) {
- rotwing_state_fw_idle_counter++;
- } else {
- rotwing_state_fw_idle_counter = 0;
- }
-
- // Switch state if necessary
- if (rotwing_state_skewing_counter > ROTWING_MIN_FW_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_SKEWING;
- rotwing_state_skewing_counter = 0;
- rotwing_state_fw_idle_counter = 0;
- } else if (rotwing_state_fw_idle_counter > ROTWING_MIN_THRUST_IDLE_COUNTER
- && rotwing_state_skewing_counter == 0) {
- rotwing_state.current_state = ROTWING_STATE_FW_HOV_MOT_IDLE;
- rotwing_state_skewing_counter = 0;
- rotwing_state_fw_idle_counter = 0;
- }
- break;
-
- case ROTWING_STATE_FW_HOV_MOT_IDLE:
- // Check if state needs to be set to fixed wing with hover motors activated
- if (current_thrust > ROTWING_MIN_THRUST_IDLE
- || rotwing_state.desired_state < ROTWING_STATE_FW_HOV_MOT_IDLE) {
- rotwing_state_fw_counter++;
- } else {
- rotwing_state_fw_counter = 0;
- }
- // Check if state needs to be set to fixed wing with hover motors off (if zero rpm on hover motors)
- if (rotwing_state_hover_rpm[0] == 0
- && rotwing_state_hover_rpm[1] == 0
- && rotwing_state_hover_rpm[2] == 0
- && rotwing_state_hover_rpm[3] == 0) {
-#if !USE_NPS
- rotwing_state_fw_m_off_counter++;
-#endif
- } else {
- rotwing_state_fw_m_off_counter = 0;
- }
-
- // Switch state if necessary
- if (rotwing_state_fw_counter > ROTWING_MIN_THRUST_IDLE_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_FW;
- rotwing_state_fw_counter = 0;
- rotwing_state_fw_m_off_counter = 0;
- } else if (rotwing_state_fw_m_off_counter > ROTWING_HOV_MOT_OFF_COUNTER
- && rotwing_state_fw_counter == 0) {
- rotwing_state.current_state = ROTWING_STATE_FW_HOV_MOT_OFF;
- rotwing_state_fw_counter = 0;
- rotwing_state_fw_m_off_counter = 0;
- }
- break;
-
- case ROTWING_STATE_FW_HOV_MOT_OFF:
- // Check if state needs to be set to fixed wing with hover motors idle (if rpm on hover motors)
- if (rotwing_state_hover_rpm[0] > ROTWING_HOV_MOT_OFF_RPM_TH
- && rotwing_state_hover_rpm[1] > ROTWING_HOV_MOT_OFF_RPM_TH
- && rotwing_state_hover_rpm[2] > ROTWING_HOV_MOT_OFF_RPM_TH
- && rotwing_state_hover_rpm[3] > ROTWING_HOV_MOT_OFF_RPM_TH) {
- rotwing_state_fw_idle_counter++;
- } else {
- rotwing_state_fw_idle_counter = 0;
- }
-
- // Switch state if necessary
- if (rotwing_state_fw_idle_counter > ROTWING_MIN_THRUST_IDLE_COUNTER) {
- rotwing_state.current_state = ROTWING_STATE_FW_HOV_MOT_IDLE;
- rotwing_state_fw_idle_counter = 0;
- }
- break;
-
- default:
- break;
- }
-}
-
-// Function that handles settings for switching state(s)
-void rotwing_switch_state(void)
-{
- switch (rotwing_state.current_state) {
- case ROTWING_STATE_HOVER:
- if (rotwing_state.desired_state > ROTWING_STATE_HOVER) {
- rotwing_state_set_skewing_settings();
- } else {
- rotwing_state_set_hover_settings();
- }
- break;
-
- case ROTWING_STATE_SKEWING:
- if (rotwing_state.desired_state < ROTWING_STATE_SKEWING && stateGetAirspeed_f() < ROTWING_MAX_QUAD_AIRSPEED) {
- rotwing_state_set_hover_settings();
- } else {
- rotwing_state_set_skewing_settings();
- }
- break;
-
- case ROTWING_STATE_FW:
- if (rotwing_state.desired_state > ROTWING_STATE_FW) {
- rotwing_state_set_fw_hov_mot_idle_settings();
- } else if (rotwing_state.desired_state < ROTWING_STATE_FW) {
- rotwing_state_set_skewing_settings();
- } else {
- rotwing_state_set_fw_settings();
- }
- break;
-
- case ROTWING_STATE_FW_HOV_MOT_IDLE:
- if (rotwing_state.desired_state > ROTWING_STATE_FW_HOV_MOT_IDLE) {
- rotwing_state_set_fw_hov_mot_off_settings();
- } else if (rotwing_state.desired_state < ROTWING_STATE_FW_HOV_MOT_IDLE) {
- rotwing_state_set_fw_settings();
- } else {
- rotwing_state_set_fw_hov_mot_idle_settings();
- }
- break;
-
- case ROTWING_STATE_FW_HOV_MOT_OFF:
- if (rotwing_state.desired_state < ROTWING_STATE_FW_HOV_MOT_OFF) {
- rotwing_state_set_fw_hov_mot_idle_settings();
- } else {
- rotwing_state_set_fw_hov_mot_off_settings();
- }
- break;
- }
-}
-
-void rotwing_state_set_hover_settings(void)
-{
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_QUAD_SETTING;
- rotwing_state_settings.hover_motors_active = true;
- rotwing_state_settings.hover_motors_disable = false;
- rotwing_state_settings.force_forward = false;
- rotwing_state_settings.preferred_pitch_setting = ROTWING_STATE_PITCH_QUAD_SETTING;
- rotwing_state_settings.stall_protection = false;
- rotwing_state_settings.max_v_climb = 2.0;
- rotwing_state_settings.max_v_descend = 1.0;
- rotwing_state_settings.nav_max_speed = rotwing_state_max_hover_speed; // Using setting
- rotwing_state_set_state_settings();
-}
-
-void rotwing_state_set_skewing_settings(void)
-{
- // Wing may be skewed to quad when desired state is hover and skewing settings set by state machine
- if (rotwing_state.desired_state == ROTWING_STATE_HOVER) {
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_QUAD_SETTING;
- } else {
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_SCHEDULING_SETTING;
- }
- rotwing_state_settings.hover_motors_active = true;
- rotwing_state_settings.hover_motors_disable = false;
- rotwing_state_settings.force_forward = false;
- rotwing_state_settings.preferred_pitch_setting = ROTWING_STATE_PITCH_TRANSITION_SETTING;
- rotwing_state_settings.stall_protection = false;
- rotwing_state_settings.max_v_climb = 2.0;
- rotwing_state_settings.max_v_descend = 1.0;
- rotwing_state_settings.nav_max_speed = rotwing_state_max_fw_speed;// Big as we use airspeed guidance
- rotwing_state_set_state_settings();
-}
-
-void rotwing_state_set_fw_settings(void)
-{
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_FW_SETTING;
- rotwing_state_settings.hover_motors_active = true;
- rotwing_state_settings.hover_motors_disable = false;
- rotwing_state_settings.force_forward = true;
- rotwing_state_settings.preferred_pitch_setting = ROTWING_STATE_PITCH_FW_SETTING;
- rotwing_state_settings.stall_protection = true;
- rotwing_state_settings.max_v_climb = 4.0;
- rotwing_state_settings.max_v_descend = 4.0;
- rotwing_state_settings.nav_max_speed = rotwing_state_max_fw_speed; // Big as we use airspeed guidance
- //rotwing_state_settings.nav_max_speed = 100; // Big as we use airspeed guidance
- rotwing_state_set_state_settings();
-}
-
-void rotwing_state_set_fw_hov_mot_idle_settings(void)
-{
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_FW_SETTING;
- rotwing_state_settings.hover_motors_active = false;
- rotwing_state_settings.hover_motors_disable = false;
- rotwing_state_settings.force_forward = true;
- rotwing_state_settings.preferred_pitch_setting = ROTWING_STATE_PITCH_FW_SETTING;
- rotwing_state_settings.stall_protection = true;
- rotwing_state_settings.max_v_climb = 4.0;
- rotwing_state_settings.max_v_descend = 4.0;
- rotwing_state_settings.nav_max_speed = rotwing_state_max_fw_speed; // Big as we use airspeed guidance
- rotwing_state_set_state_settings();
-}
-
-void rotwing_state_set_fw_hov_mot_off_settings(void)
-{
- rotwing_state_settings.wing_scheduler = ROTWING_STATE_WING_FW_SETTING;
- rotwing_state_settings.hover_motors_active = false;
- rotwing_state_settings.hover_motors_disable = true;
- rotwing_state_settings.force_forward = true;
- rotwing_state_settings.preferred_pitch_setting = ROTWING_STATE_PITCH_FW_SETTING;
- rotwing_state_settings.stall_protection = true;
- rotwing_state_settings.max_v_climb = 4.0;
- rotwing_state_settings.max_v_descend = 4.0;
- rotwing_state_settings.nav_max_speed = rotwing_state_max_fw_speed; // Big as we use airspeed guidance
- rotwing_state_set_state_settings();
-}
-
-void rotwing_state_set_state_settings(void)
-{
- if (!rotwing_state_skewing.force_rotation_angle) {
- switch (rotwing_state_settings.wing_scheduler) {
- case ROTWING_STATE_WING_QUAD_SETTING:
- rotwing_state_skewing.airspeed_scheduling = false;
- rotwing_state_skewing.wing_angle_deg_sp = 0;
- break;
- case ROTWING_STATE_WING_SCHEDULING_SETTING:
- rotwing_state_skewing.airspeed_scheduling = true;
- break;
- case ROTWING_STATE_WING_FW_SETTING:
- rotwing_state_skewing.airspeed_scheduling = true;
- break;
- }
- } else {
- rotwing_state_skewing.airspeed_scheduling = false;
- }
-
- hover_motors_active = rotwing_state_settings.hover_motors_active;
-
- bool_disable_hover_motors = rotwing_state_settings.hover_motors_disable;
-
- force_forward = rotwing_state_settings.force_forward;
-
- nav_max_speed = rotwing_state_settings.nav_max_speed;
-
- // TO DO: pitch angle now hard coded scheduled by wing angle
-
- // Stall protection handled by hover_motors_active boolean
-
- // TO DO: Climb and descend speeds now handled by guidance airspeed
-}
-
-void rotwing_state_skewer(void)
-{
- if (rotwing_state_skewing.airspeed_scheduling) {
- float wing_angle_scheduled_sp_deg = 0;
- float airspeed = stateGetAirspeed_f();
- if (airspeed < 8) {
- wing_angle_scheduled_sp_deg = 0;
- } else if (airspeed < 10 && (rotwing_state.desired_state > ROTWING_STATE_HOVER)) {
- wing_angle_scheduled_sp_deg = ROTWING_HALF_SKEW_ANGLE_DEG;
- } else if (airspeed > 10) {
- wing_angle_scheduled_sp_deg = ((airspeed - 10.)) / 4. * (90.-ROTWING_HALF_SKEW_ANGLE_DEG) + ROTWING_HALF_SKEW_ANGLE_DEG;
- } else {
- wing_angle_scheduled_sp_deg = 0;
- }
-
- Bound(wing_angle_scheduled_sp_deg, 0., 90.)
- rotwing_state_skewing.wing_angle_deg_sp = wing_angle_scheduled_sp_deg;
- } else {
- if(demo_skew) {
- float amplitude_skew_demo = (max_skew_demo - min_skew_demo) / 2;
- float offset_skew_demo = (max_skew_demo + min_skew_demo) / 2;
- float time_skew_demo = (float) time_step_skew_demo / PERIODIC_FREQUENCY;
- float angle_skew_demo = amplitude_skew_demo * (-cosf(2 * M_PI * freq_skew_demo * time_skew_demo)) + offset_skew_demo;
- rotwing_state_skewing.wing_angle_deg_sp = angle_skew_demo;
- time_step_skew_demo++;
- }else{
- time_step_skew_demo = 0;
- }
- }
-}
-
-void rotwing_state_free_processor(void)
-{
- // Get current speed vector
- struct EnuCoor_f *groundspeed = stateGetSpeedEnu_f();
- float current_groundspeed = FLOAT_VECT2_NORM(*groundspeed);
-
- // Get current airspeed
- float airspeed = stateGetAirspeed_f();
-
- // Get windspeed vector
- struct FloatEulers eulers_zxy;
- float_eulers_of_quat_zxy(&eulers_zxy, stateGetNedToBodyQuat_f());
-
- float psi = eulers_zxy.psi;
- float cpsi = cosf(psi);
- float spsi = sinf(psi);
- struct FloatVect2 airspeed_v = { spsi * airspeed, cpsi * airspeed };
- struct FloatVect2 windspeed_v;
- VECT2_DIFF(windspeed_v, *groundspeed, airspeed_v);
-
- // Get goto target information
- struct FloatVect2 pos_error;
- struct EnuCoor_f *pos = stateGetPositionEnu_f();
- VECT2_DIFF(pos_error, nav_rotorcraft_base.goto_wp.to, *pos);
-
- /*
- Calculations
- */
- // speed over pos_error projection
- struct FloatVect2 pos_error_norm;
- VECT2_COPY(pos_error_norm, pos_error);
- float_vect2_normalize(&pos_error_norm);
- float dist_to_target = sqrtf(nav_rotorcraft_base.goto_wp.dist2_to_wp);
- float max_speed_decel2 = fabsf(2.f * dist_to_target * nav_max_deceleration_sp); // dist_to_wp can only be positive, but just in case
- float max_speed_decel = sqrtf(max_speed_decel2);
-
- // Check if speed setpoint above set airspeed
- struct FloatVect2 desired_airspeed_v;
- struct FloatVect2 groundspeed_sp;
- groundspeed_sp.x = pos_error.x * nav_hybrid_pos_gain;
- groundspeed_sp.y = pos_error.y * nav_hybrid_pos_gain;
- VECT2_COPY(desired_airspeed_v, groundspeed_sp);
- VECT2_ADD(desired_airspeed_v, windspeed_v);
-
- float desired_airspeed = FLOAT_VECT2_NORM(desired_airspeed_v);
- float airspeed_error = rotwing_state_max_fw_speed - airspeed;
-
- // Request hybrid if we have to decelerate and approaching target
- if (max_speed_decel < current_groundspeed) {
- request_rotwing_state(ROTWING_STATE_SKEWING);
- } else if ((desired_airspeed > 15) && ((current_groundspeed + airspeed_error) < max_speed_decel)) {
- request_rotwing_state(ROTWING_STATE_FW_HOV_MOT_OFF);
- }
-}
-
-void rotwing_state_skew_actuator_periodic(void)
-{
-
- // calc rotation percentage of setpoint (0 deg = -1, 45 deg = 0, 90 deg = 1)
- float wing_rotation_percentage = (rotwing_state_skewing.wing_angle_deg_sp - 45.) / 45.;
- Bound(wing_rotation_percentage, -1., 1.);
-
- float servo_pprz_cmd = MAX_PPRZ * wing_rotation_percentage;
- // Calulcate rotation_cmd
- Bound(servo_pprz_cmd, -MAX_PPRZ, MAX_PPRZ);
-
-#if ROTWING_STATE_USE_ROTATION_REF_MODEL
- // Rotate with second order filter
- static float rotwing_state_skew_p_cmd = -MAX_PPRZ;
- static float rotwing_state_skew_d_cmd = 0;
- float speed_sp = 0.001 * (servo_pprz_cmd - rotwing_state_skew_p_cmd);
- rotwing_state_skew_d_cmd += 0.003 * (speed_sp - rotwing_state_skew_d_cmd);
- rotwing_state_skew_p_cmd += rotwing_state_skew_d_cmd;
- Bound(rotwing_state_skew_p_cmd, -MAX_PPRZ, MAX_PPRZ);
- rotwing_state_skewing.servo_pprz_cmd = rotwing_state_skew_p_cmd;
-#else
- // Directly controlling the wing rotation
- rotwing_state_skewing.servo_pprz_cmd = servo_pprz_cmd;
-#endif
-
-#if USE_NPS
- // Export to the index of the SKEW in the NPS_ACTUATOR_NAMES array
- commands[COMMAND_ROT_MECH] = (rotwing_state_skewing.servo_pprz_cmd + MAX_PPRZ) / 2.; // Scale to simulation command
-
-#if USE_ROTMECH_VIRTUAL
- // Calculate discrete first order dynamics of rot mech
- float dyn_dis = 1.0-exp(-ROTMECH_DYN / PERIODIC_FREQUENCY);
- // Simulate wing angle from command
- float prev_rotmech_state = rotwing_state_skewing.wing_angle_deg;
- rotwing_state_skewing.wing_angle_deg = prev_rotmech_state + dyn_dis * (rotwing_state_skewing.wing_angle_deg_sp - prev_rotmech_state);
-#else
- // Simulate wing angle from command
- rotwing_state_skewing.wing_angle_deg = (float) rotwing_state_skewing.servo_pprz_cmd / MAX_PPRZ * 45. + 45.;
-#endif // USE_ROTMECH_VIRTUAL
- // SEND ABI Message to ctr_eff_sched and other modules that want Actuator position feedback
- struct act_feedback_t feedback;
- feedback.idx = SERVO_ROTATION_MECH_IDX;
- feedback.position = 0.5 * M_PI - RadOfDeg(rotwing_state_skewing.wing_angle_deg);
- feedback.set.position = true;
- // Send ABI message
- AbiSendMsgACT_FEEDBACK(ACT_FEEDBACK_UAVCAN_ID, &feedback, 1);
-#else
- commands[COMMAND_ROT_MECH] = rotwing_state_skewing.servo_pprz_cmd;
-#endif // USE_NPS
-}
-
-static void rotwing_state_feedback_cb(uint8_t __attribute__((unused)) sender_id,
- struct act_feedback_t UNUSED *feedback_msg, uint8_t UNUSED num_act_message)
-{
- for (int i = 0; i < num_act_message; i++) {
-
- for (int i = 0; i < num_act_message; i++) {
- // Check for wing rotation feedback
- if ((feedback_msg[i].set.position) && (feedback_msg[i].idx == SERVO_ROTATION_MECH_IDX)) {
- // Get wing rotation angle from sensor
- float wing_angle_rad = 0.5 * M_PI - feedback_msg[i].position;
- rotwing_state_skewing.wing_angle_deg = DegOfRad(wing_angle_rad);
-
- // Bound wing rotation angle
- Bound(rotwing_state_skewing.wing_angle_deg, 0, 90.);
- }
- }
-
- // Sanity check that index is valid
- int idx = feedback_msg[i].idx;
- if (feedback_msg[i].set.rpm) {
- if ((idx == SERVO_MOTOR_FRONT_IDX) || (idx == SERVO_BMOTOR_FRONT_IDX)) {
- rotwing_state_hover_rpm[0] = feedback_msg->rpm;
- } else if ((idx == SERVO_MOTOR_RIGHT_IDX) || (idx == SERVO_BMOTOR_RIGHT_IDX)) {
- rotwing_state_hover_rpm[1] = feedback_msg->rpm;
- } else if ((idx == SERVO_MOTOR_BACK_IDX) || (idx == SERVO_BMOTOR_BACK_IDX)) {
- rotwing_state_hover_rpm[2] = feedback_msg->rpm;
- } else if ((idx == SERVO_MOTOR_LEFT_IDX) || (idx == SERVO_BMOTOR_LEFT_IDX)) {
- rotwing_state_hover_rpm[3] = feedback_msg->rpm;
- }
- }
- }
-}
-
diff --git a/sw/airborne/modules/rotwing_drone/rotwing_state_V2.h b/sw/airborne/modules/rotwing_drone/rotwing_state_V2.h
deleted file mode 100644
index e3a0ac93cc..0000000000
--- a/sw/airborne/modules/rotwing_drone/rotwing_state_V2.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2023 Tomaso De Ponti
- *
- * 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, see
- * .
- */
-
-/** @file "modules/rotwing/rotwing_state_V2.h"
- * @author Tomaso De Ponti
- * This module keeps track of the current state of a rotating wing drone and desired state set by the RC or flightplan. Paramters are being scheduled in each change of a current state and desired state. Functions are defined in this module to call the actual state and desired state and set a desired state.
- */
-
-#ifndef ROTWING_STATE_H
-#define ROTWING_STATE_H
-
-#include "std.h"
-
-/** Rotwing States
- */
-#define ROTWING_STATE_HOVER 0 // Wing is skewed in 0 degrees (quad)
-#define ROTWING_STATE_SKEWING 1 // WIng is skewing
-#define ROTWING_STATE_FW 2 // Wing is skewed at 90 degrees (fixed wing), hover motors have full authority
-#define ROTWING_STATE_FW_HOV_MOT_IDLE 3 // Wing is skewed at 90 degrees (fixed wing), hover motors are forced to idle
-#define ROTWING_STATE_FW_HOV_MOT_OFF 4 // Wing is skewed at 90 degrees (fixed wubg), hover motors are switched off
-#define ROTWING_STATE_FREE 5 // This is a desired state for which the controller has to decide the desired state itself
-
-/** Rotwing Configurations
- */
-#define ROTWING_CONFIGURATION_HOVER 0 // UAV is in hover
-#define ROTWING_CONFIGURATION_HYBRID 1 // UAV can fly forward and hover if airspeed low, hover motors on
-#define ROTWING_CONFIGURATION_EFFICIENT 2 // UAV flies efficiently forward (FW)
-#define ROTWING_CONFIGURATION_FREE 3 // UAV switched between efficient and hybrid dependent on deceleration
-
-struct RotwingState {
- uint8_t current_state;
- uint8_t desired_state;
- uint8_t requested_config;
-};
-
-#define ROTWING_STATE_WING_QUAD_SETTING 0 // Wing skew at 0 degrees
-#define ROTWING_STATE_WING_SCHEDULING_SETTING 1 // Wing skew handled by airspeed scheduler
-#define ROTWING_STATE_WING_FW_SETTING 2 // Wing skew at 90 degrees
-
-#define ROTWING_STATE_PITCH_QUAD_SETTING 0 // Pitch at prefered hover
-#define ROTWING_STATE_PITCH_TRANSITION_SETTING 1 // Pitch scheduled
-#define ROTWING_STATE_PITCH_FW_SETTING 2 // Pitch at prefered forward
-
-struct RotWingStateSettings {
- uint8_t wing_scheduler;
- bool hover_motors_active;
- bool hover_motors_disable;
- bool force_forward;
- uint8_t preferred_pitch_setting;
- float preferred_pitch_value;
- bool stall_protection;
- float max_v_climb;
- float max_v_descend;
- float nav_max_speed;
-};
-
-struct RotWingStateSkewing {
- float wing_angle_deg_sp; // Wing angle setpoint in deg
- float wing_angle_deg; // Wing angle from sensor in deg
- int32_t servo_pprz_cmd; // Wing rotation servo pprz cmd
- bool airspeed_scheduling; // Airspeed scheduling on or off
- bool force_rotation_angle; // Setting to force wing_angle_deg_sp
-};
-
-extern struct RotwingState rotwing_state;
-extern struct RotWingStateSettings rotwing_state_settings;
-extern struct RotWingStateSkewing rotwing_state_skewing;
-
-extern float rotwing_state_max_hover_speed;
-
-extern bool hover_motors_active;
-extern bool bool_disable_hover_motors;
-extern bool demo_skew;
-extern float max_skew_demo;
-extern float min_skew_demo;
-extern float freq_skew_demo;
-
-extern void init_rotwing_state(void);
-extern void periodic_rotwing_state(void);
-extern void request_rotwing_state(uint8_t state);
-extern void rotwing_request_configuration(uint8_t configuration);
-extern void rotwing_state_skew_actuator_periodic(void);
-extern void rotwing_state_force_skew_off(void);
-
-#endif // ROTWING_STATE_H