VTOL Backtransition lateral position control improvements (#25704)

During backtransition in gusty conditions the current "pitch-up to decelerate" strategy had deficiencies as the motion is not always purely in body-x direction. Thus we replace it here with a "tilt-up to decelerate" strategy.
Secondly, in GNSS-denied environments where the position error increases, tracking a precise landing point through position feedback is not reasonable, and we now instead discard the position feedback in cases where the position error exceeds 10m.

* add eph limit check for dist-to-target VT BT deceleration

* add alphafilter for acceleration estimate in VT BT, rename constants

* explicitly set yawspeed_setpoint to 0

* replace backtransition pitch-setpoint with tilt-setpoint

* blend vtol-backtransition roll vehicle_attitude_sp based on mc_weight

* remove memcpy for v_att_sp
This commit is contained in:
Marco Hauswirth
2025-11-06 13:36:22 +01:00
committed by GitHub
parent 517f04259c
commit 561a83cf6c
4 changed files with 49 additions and 29 deletions
+19 -13
View File
@@ -180,7 +180,7 @@ void Standard::update_transition_state()
return;
}
memcpy(_v_att_sp, _mc_virtual_att_sp, sizeof(vehicle_attitude_setpoint_s));
*_v_att_sp = *_mc_virtual_att_sp;
} else {
// we need a recent incoming (fw virtual) attitude setpoint, otherwise return (means the previous setpoint stays active)
@@ -188,7 +188,7 @@ void Standard::update_transition_state()
return;
}
memcpy(_v_att_sp, _fw_virtual_att_sp, sizeof(vehicle_attitude_setpoint_s));
*_v_att_sp = *_fw_virtual_att_sp;
_v_att_sp->thrust_body[2] = -_fw_virtual_att_sp->thrust_body[0];
}
@@ -198,11 +198,12 @@ void Standard::update_transition_state()
float pitch_body = attitude_setpoint_euler.theta();
float yaw_body = attitude_setpoint_euler.psi();
if (_v_control_mode->flag_control_climb_rate_enabled) {
roll_body = Eulerf(Quatf(_fw_virtual_att_sp->q_d)).phi();
}
if (_vtol_mode == vtol_mode::TRANSITION_TO_FW) {
if (_v_control_mode->flag_control_climb_rate_enabled) {
roll_body = Eulerf(Quatf(_fw_virtual_att_sp->q_d)).phi();
}
if (_param_vt_psher_slew.get() <= FLT_EPSILON) {
// just set the final target throttle value
_pusher_throttle = _param_vt_f_trans_thr.get();
@@ -239,12 +240,24 @@ void Standard::update_transition_state()
_v_att_sp->thrust_body[0] = _pusher_throttle;
const Quatf q_sp(Eulerf(roll_body, pitch_body, yaw_body));
q_sp.copyTo(_v_att_sp->q_d);
mc_weight = math::constrain(mc_weight, 0.0f, 1.0f);
} else if (_vtol_mode == vtol_mode::TRANSITION_TO_MC) {
// continually increase mc attitude control as we transition back to mc mode
if (_param_vt_b_trans_ramp.get() > FLT_EPSILON) {
mc_weight = _time_since_trans_start / _param_vt_b_trans_ramp.get();
}
mc_weight = math::constrain(mc_weight, 0.0f, 1.0f);
if (_v_control_mode->flag_control_climb_rate_enabled) {
// control backtransition deceleration using pitch.
pitch_body = Eulerf(Quatf(_mc_virtual_att_sp->q_d)).theta();
// blend roll setpoint between FW and MC
const float roll_body_fw = Eulerf(Quatf(_fw_virtual_att_sp->q_d)).phi();
roll_body = mc_weight * roll_body + (1.0f - mc_weight) * roll_body_fw;
}
const Quatf q_sp(Eulerf(roll_body, pitch_body, yaw_body));
@@ -252,15 +265,8 @@ void Standard::update_transition_state()
q_sp.copyTo(_v_att_sp->q_d);
_pusher_throttle = 0.0f;
// continually increase mc attitude control as we transition back to mc mode
if (_param_vt_b_trans_ramp.get() > FLT_EPSILON) {
mc_weight = _time_since_trans_start / _param_vt_b_trans_ramp.get();
}
}
mc_weight = math::constrain(mc_weight, 0.0f, 1.0f);
_mc_roll_weight = mc_weight;
_mc_pitch_weight = mc_weight;
_mc_yaw_weight = mc_weight;
@@ -341,7 +341,7 @@ PARAM_DEFINE_FLOAT(VT_FW_DIFTHR_S_P, 1.f);
PARAM_DEFINE_FLOAT(VT_FW_DIFTHR_S_Y, 0.1f);
/**
* Backtransition deceleration setpoint to pitch I gain.
* Backtransition deceleration setpoint to tilt I gain.
*
* @unit rad s/m
* @min 0