From 989b574c3afe15f31b1fb7e7a6df8a911af7e314 Mon Sep 17 00:00:00 2001 From: George Zogopoulos Date: Thu, 1 Aug 2024 16:58:11 +0200 Subject: [PATCH 1/4] Plane: TKOFF_THR_MIN is applied to SLT transitions Also split in_transition() to forward and backward. --- ArduPlane/Attitude.cpp | 6 +++--- ArduPlane/quadplane.cpp | 32 +++++++++++++++++++++++++++++--- ArduPlane/quadplane.h | 15 ++++++++++++--- ArduPlane/servos.cpp | 16 +++++++++++++--- ArduPlane/tailsitter.cpp | 2 ++ ArduPlane/tailsitter.h | 4 +++- ArduPlane/tiltrotor.cpp | 2 ++ ArduPlane/transition.h | 8 ++++++-- 8 files changed, 70 insertions(+), 15 deletions(-) diff --git a/ArduPlane/Attitude.cpp b/ArduPlane/Attitude.cpp index 788fe97dbada6..17cc78bc17397 100644 --- a/ArduPlane/Attitude.cpp +++ b/ArduPlane/Attitude.cpp @@ -204,9 +204,9 @@ float Plane::stabilize_pitch_get_pitch_out() #endif // if LANDING_FLARE RCx_OPTION switch is set and in FW mode, manual throttle,throttle idle then set pitch to LAND_PITCH_DEG if flight option FORCE_FLARE_ATTITUDE is set #if HAL_QUADPLANE_ENABLED - const bool quadplane_in_transition = quadplane.in_transition(); + const bool quadplane_in_frwd_transition = quadplane.in_frwd_transition(); #else - const bool quadplane_in_transition = false; + const bool quadplane_in_frwd_transition = false; #endif int32_t demanded_pitch = nav_pitch_cd + int32_t(g.pitch_trim * 100.0) + SRV_Channels::get_output_scaled(SRV_Channel::k_throttle) * g.kff_throttle_to_pitch; @@ -219,7 +219,7 @@ float Plane::stabilize_pitch_get_pitch_out() - throttle stick at zero thrust - in fixed wing non auto-throttle mode */ - if (!quadplane_in_transition && + if (!quadplane_in_frwd_transition && !control_mode->is_vtol_mode() && !control_mode->does_auto_throttle() && flare_mode == FlareMode::ENABLED_PITCH_TARGET && diff --git a/ArduPlane/quadplane.cpp b/ArduPlane/quadplane.cpp index 390787425d34e..cb2d9ee0d7880 100644 --- a/ArduPlane/quadplane.cpp +++ b/ArduPlane/quadplane.cpp @@ -810,6 +810,10 @@ bool QuadPlane::setup(void) pilot_speed_z_max_dn.convert_centi_parameter(AP_PARAM_INT16); pilot_accel_z.convert_centi_parameter(AP_PARAM_INT16); + // Provisionally assign the SLT thrust type. + // It will be overwritten by tailsitter or tiltorotor setups. + thrust_type = ThrustType::SLT; + tailsitter.setup(); tiltrotor.setup(); @@ -3967,11 +3971,28 @@ bool QuadPlane::is_vtol_land(uint16_t id) const } /* - return true if we are in a transition to fwd flight from hover + return true if we are in any kind of transition */ bool QuadPlane::in_transition(void) const { - return available() && transition->active(); + return in_frwd_transition() || in_back_transition(); +} + +/* + return true if we are in a transition to fwd flight from hover + */ +bool QuadPlane::in_frwd_transition(void) const +{ + return available() && transition->active_frwd(); +} + +/* + return true if we are in a transition to hover from fwd flight + */ +bool QuadPlane::in_back_transition(void) const +{ + // By default the + return available() && transition->active_back(); } /* @@ -4350,11 +4371,16 @@ bool SLT_Transition::allow_update_throttle_mix() const return !(quadplane.assisted_flight && (transition_state == TRANSITION_AIRSPEED_WAIT || transition_state == TRANSITION_TIMER)); } -bool SLT_Transition::active() const +bool SLT_Transition::active_frwd() const { return quadplane.assisted_flight && ((transition_state == TRANSITION_AIRSPEED_WAIT) || (transition_state == TRANSITION_TIMER)); } +bool SLT_Transition::active_back() const +{ + return false; +} + /* limit VTOL roll/pitch in POSITION1, POSITION2 and waypoint controller. This serves three roles: 1) an expanding envelope limit on pitch to prevent sudden pitch at the start of a back transition diff --git a/ArduPlane/quadplane.h b/ArduPlane/quadplane.h index 2ced92498b423..24f25c06e8216 100644 --- a/ArduPlane/quadplane.h +++ b/ArduPlane/quadplane.h @@ -76,6 +76,13 @@ class QuadPlane void control_auto(void); bool setup(void); + enum class ThrustType : uint8_t { + SLT=0, // Traditional quadplane, with a pusher motor and independent multicopter lift. + TAILSITTER, + TILTROTOR, + }; + ThrustType get_thrust_type(void) {return thrust_type;} + void vtol_position_controller(void); void setup_target_position(void); void takeoff_controller(void); @@ -103,10 +110,9 @@ class QuadPlane // abort landing, only valid when in a VTOL landing descent bool abort_landing(void); - /* - return true if we are in a transition to fwd flight from hover - */ bool in_transition(void) const; + bool in_frwd_transition(void) const; + bool in_back_transition(void) const; bool handle_do_vtol_transition(enum MAV_VTOL_STATE state) const; @@ -198,6 +204,9 @@ class QuadPlane AP_Enum frame_class; AP_Enum frame_type; + // Types of different "quadplane" configurations. + ThrustType thrust_type; + // Initialise motors to allow passing it to tailsitter in its constructor AP_MotorsMulticopter *motors = nullptr; const struct AP_Param::GroupInfo *motors_var_info; diff --git a/ArduPlane/servos.cpp b/ArduPlane/servos.cpp index aa2c7ce3737b7..92662c074820d 100644 --- a/ArduPlane/servos.cpp +++ b/ArduPlane/servos.cpp @@ -51,7 +51,7 @@ void Plane::throttle_slew_limit(SRV_Channel::Aux_servo_function_t func) slewrate = g.takeoff_throttle_slewrate; } #if HAL_QUADPLANE_ENABLED - if (g.takeoff_throttle_slewrate != 0 && quadplane.in_transition()) { + if (g.takeoff_throttle_slewrate != 0 && quadplane.in_frwd_transition()) { slewrate = g.takeoff_throttle_slewrate; } #endif @@ -555,10 +555,20 @@ float Plane::apply_throttle_limits(float throttle_in) // Handle throttle limits for transition conditions. #if HAL_QUADPLANE_ENABLED - if (quadplane.in_transition()) { + if (quadplane.in_frwd_transition()) { if (aparm.takeoff_throttle_max != 0) { max_throttle = aparm.takeoff_throttle_max.get(); } + + // Apply minimum throttle limits only for SLT thrust types. + // The other types don't support it well. + if (quadplane.get_thrust_type() == QuadPlane::ThrustType::SLT + && control_mode->does_auto_throttle() + ) { + if (aparm.takeoff_throttle_min.get() != 0) { + min_throttle = MAX(min_throttle, aparm.takeoff_throttle_min.get()); + } + } } #endif @@ -793,7 +803,7 @@ void Plane::servos_twin_engine_mix(void) void Plane::force_flare(void) { #if HAL_QUADPLANE_ENABLED - if (quadplane.in_transition() && plane.arming.is_armed()) { //allows for ground checking of flare tilts + if (quadplane.in_frwd_transition() && plane.arming.is_armed()) { //allows for ground checking of flare tilts return; } if (control_mode->is_vtol_mode()) { diff --git a/ArduPlane/tailsitter.cpp b/ArduPlane/tailsitter.cpp index b530dacce5594..33d111db3d066 100644 --- a/ArduPlane/tailsitter.cpp +++ b/ArduPlane/tailsitter.cpp @@ -208,6 +208,8 @@ void Tailsitter::setup() return; } + quadplane.thrust_type = QuadPlane::ThrustType::TAILSITTER; + // Set tailsitter transition rate to match old calculation if (!transition_rate_fw.configured()) { transition_rate_fw.set_and_save(transition_angle_fw / (quadplane.transition_time_ms/2000.0f)); diff --git a/ArduPlane/tailsitter.h b/ArduPlane/tailsitter.h index fbf26702f8ca9..422c9bd017798 100644 --- a/ArduPlane/tailsitter.h +++ b/ArduPlane/tailsitter.h @@ -175,7 +175,9 @@ friend class Tailsitter; uint8_t get_log_transition_state() const override { return static_cast(transition_state); } - bool active() const override { return transition_state != TRANSITION_DONE; } + bool active_frwd() const override { return transition_state == TRANSITION_ANGLE_WAIT_FW; } + + bool active_back() const override { return transition_state == TRANSITION_ANGLE_WAIT_VTOL; } bool show_vtol_view() const override; diff --git a/ArduPlane/tiltrotor.cpp b/ArduPlane/tiltrotor.cpp index 9fd1f8a2cbd1a..fe893b01cd730 100644 --- a/ArduPlane/tiltrotor.cpp +++ b/ArduPlane/tiltrotor.cpp @@ -106,6 +106,8 @@ void Tiltrotor::setup() return; } + quadplane.thrust_type = QuadPlane::ThrustType::TILTROTOR; + _is_vectored = tilt_mask != 0 && type == TILT_TYPE_VECTORED_YAW; // true if a fixed forward motor is configured, either throttle, throttle left or throttle right. diff --git a/ArduPlane/transition.h b/ArduPlane/transition.h index b31e45ff040ec..75d33948e5da7 100644 --- a/ArduPlane/transition.h +++ b/ArduPlane/transition.h @@ -36,7 +36,9 @@ class Transition virtual uint8_t get_log_transition_state() const = 0; - virtual bool active() const = 0; + virtual bool active_frwd() const = 0; + + virtual bool active_back() const = 0; virtual bool show_vtol_view() const = 0; @@ -85,7 +87,9 @@ class SLT_Transition : public Transition uint8_t get_log_transition_state() const override { return static_cast(transition_state); } - bool active() const override; + bool active_frwd() const override; + + bool active_back() const override; bool show_vtol_view() const override; From 9cf0b18d1abebab5edaf358306977fcf22a30cbb Mon Sep 17 00:00:00 2001 From: George Zogopoulos Date: Mon, 12 Aug 2024 21:56:22 +0200 Subject: [PATCH 2/4] autotest: Added TKOFF_THR_MIN test --- Tools/autotest/quadplane.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Tools/autotest/quadplane.py b/Tools/autotest/quadplane.py index 1395e245c22d8..c19c83662787a 100644 --- a/Tools/autotest/quadplane.py +++ b/Tools/autotest/quadplane.py @@ -1560,6 +1560,29 @@ def mavlink_MAV_CMD_DO_VTOL_TRANSITION(self): self.fly_home_land_and_disarm() + def TransitionMinThrottle(self): + '''Ensure that TKOFF_THR_MIN is applied during the forward transition''' + wps = self.create_simple_relhome_mission([ + (mavutil.mavlink.MAV_CMD_NAV_TAKEOFF, 0, 0, 30), + (mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, 2000, 0, 30), + (mavutil.mavlink.MAV_CMD_NAV_RETURN_TO_LAUNCH, 0, 0, 0), + ]) + self.check_mission_upload_download(wps) + self.set_parameter('TKOFF_THR_MIN', 80) + + self.change_mode('AUTO') + self.wait_ready_to_arm() + + self.arm_vehicle() + self.wait_current_waypoint(2) + # Wait for 5 seconds into the transition. + self.delay_sim_time(5) + # Ensure TKOFF_THR_MIN is still respected. + thr_min = self.get_parameter('TKOFF_THR_MIN') + self.wait_servo_channel_value(3, 1000+thr_min*10, comparator=operator.eq) + + self.fly_home_land_and_disarm() + def MAV_CMD_NAV_TAKEOFF(self): '''test issuing takeoff command via mavlink''' self.change_mode('GUIDED') @@ -1815,6 +1838,7 @@ def tests(self): self.RCDisableAirspeedUse, self.mission_MAV_CMD_DO_VTOL_TRANSITION, self.mavlink_MAV_CMD_DO_VTOL_TRANSITION, + self.TransitionMinThrottle, self.MAV_CMD_NAV_TAKEOFF, self.Q_GUIDED_MODE, self.DCMClimbRate, From 11454427391bcf86051c9fb326673003350a8e6a Mon Sep 17 00:00:00 2001 From: George Zogopoulos Date: Wed, 14 Aug 2024 17:04:05 +0200 Subject: [PATCH 3/4] Plane: Removed all instances of in_back_transition It is not currently used anywhere. --- ArduPlane/quadplane.cpp | 22 ---------------------- ArduPlane/quadplane.h | 2 -- ArduPlane/tailsitter.h | 2 -- ArduPlane/transition.h | 4 ---- 4 files changed, 30 deletions(-) diff --git a/ArduPlane/quadplane.cpp b/ArduPlane/quadplane.cpp index cb2d9ee0d7880..17bde998d6189 100644 --- a/ArduPlane/quadplane.cpp +++ b/ArduPlane/quadplane.cpp @@ -3970,14 +3970,6 @@ bool QuadPlane::is_vtol_land(uint16_t id) const return false; } -/* - return true if we are in any kind of transition - */ -bool QuadPlane::in_transition(void) const -{ - return in_frwd_transition() || in_back_transition(); -} - /* return true if we are in a transition to fwd flight from hover */ @@ -3986,15 +3978,6 @@ bool QuadPlane::in_frwd_transition(void) const return available() && transition->active_frwd(); } -/* - return true if we are in a transition to hover from fwd flight - */ -bool QuadPlane::in_back_transition(void) const -{ - // By default the - return available() && transition->active_back(); -} - /* calculate current stopping distance for a quadplane in fixed wing flight */ @@ -4376,11 +4359,6 @@ bool SLT_Transition::active_frwd() const return quadplane.assisted_flight && ((transition_state == TRANSITION_AIRSPEED_WAIT) || (transition_state == TRANSITION_TIMER)); } -bool SLT_Transition::active_back() const -{ - return false; -} - /* limit VTOL roll/pitch in POSITION1, POSITION2 and waypoint controller. This serves three roles: 1) an expanding envelope limit on pitch to prevent sudden pitch at the start of a back transition diff --git a/ArduPlane/quadplane.h b/ArduPlane/quadplane.h index 24f25c06e8216..ea3bba8779132 100644 --- a/ArduPlane/quadplane.h +++ b/ArduPlane/quadplane.h @@ -110,9 +110,7 @@ class QuadPlane // abort landing, only valid when in a VTOL landing descent bool abort_landing(void); - bool in_transition(void) const; bool in_frwd_transition(void) const; - bool in_back_transition(void) const; bool handle_do_vtol_transition(enum MAV_VTOL_STATE state) const; diff --git a/ArduPlane/tailsitter.h b/ArduPlane/tailsitter.h index 422c9bd017798..143c26cb9beaa 100644 --- a/ArduPlane/tailsitter.h +++ b/ArduPlane/tailsitter.h @@ -177,8 +177,6 @@ friend class Tailsitter; bool active_frwd() const override { return transition_state == TRANSITION_ANGLE_WAIT_FW; } - bool active_back() const override { return transition_state == TRANSITION_ANGLE_WAIT_VTOL; } - bool show_vtol_view() const override; void set_FW_roll_pitch(int32_t& nav_pitch_cd, int32_t& nav_roll_cd) override; diff --git a/ArduPlane/transition.h b/ArduPlane/transition.h index 75d33948e5da7..bf0e0dc5029d8 100644 --- a/ArduPlane/transition.h +++ b/ArduPlane/transition.h @@ -38,8 +38,6 @@ class Transition virtual bool active_frwd() const = 0; - virtual bool active_back() const = 0; - virtual bool show_vtol_view() const = 0; virtual void set_FW_roll_pitch(int32_t& nav_pitch_cd, int32_t& nav_roll_cd) {}; @@ -89,8 +87,6 @@ class SLT_Transition : public Transition bool active_frwd() const override; - bool active_back() const override; - bool show_vtol_view() const override; void set_FW_roll_pitch(int32_t& nav_pitch_cd, int32_t& nav_roll_cd) override; From 7e36beb0e2013b26c9c82081dacbf0f5ecd4a33b Mon Sep 17 00:00:00 2001 From: George Zogopoulos Date: Mon, 26 Aug 2024 14:56:35 +0200 Subject: [PATCH 4/4] Plane: In transition use TRIM_THROTTLE when TKOFF_THR_MIN==0 --- ArduPlane/Parameters.cpp | 2 +- ArduPlane/servos.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ArduPlane/Parameters.cpp b/ArduPlane/Parameters.cpp index 2c4d9cfed6c56..bbb8d234486ea 100644 --- a/ArduPlane/Parameters.cpp +++ b/ArduPlane/Parameters.cpp @@ -156,7 +156,7 @@ const AP_Param::Info Plane::var_info[] = { // @Range: 0 100 // @Increment: 1 // @User: Standard - ASCALAR(takeoff_throttle_min, "TKOFF_THR_MIN", 60), + ASCALAR(takeoff_throttle_min, "TKOFF_THR_MIN", 0), // @Param: TKOFF_OPTIONS // @DisplayName: Takeoff options diff --git a/ArduPlane/servos.cpp b/ArduPlane/servos.cpp index 92662c074820d..496255a75a54c 100644 --- a/ArduPlane/servos.cpp +++ b/ArduPlane/servos.cpp @@ -567,6 +567,8 @@ float Plane::apply_throttle_limits(float throttle_in) ) { if (aparm.takeoff_throttle_min.get() != 0) { min_throttle = MAX(min_throttle, aparm.takeoff_throttle_min.get()); + } else { + min_throttle = MAX(min_throttle, aparm.throttle_cruise.get()); } } }