Skip to content

airbound-develop: Add airbound 4575 rc7 fixes - #127

Open
akshar-airbound wants to merge 15 commits into
airbound-developfrom
pr-airbound-4575-rc7-fixes
Open

airbound-develop: Add airbound 4575 rc7 fixes#127
akshar-airbound wants to merge 15 commits into
airbound-developfrom
pr-airbound-4575-rc7-fixes

Conversation

@akshar-airbound

Copy link
Copy Markdown
Collaborator

vigneshm-debug and others added 14 commits June 16, 2026 12:39
- AP_Scripting: expose rate PID info to Lua via get_rate_pid_info(axis)
- Adds lua_get_rate_pid_info() binding returning a table of PID fields
(P, I, D, FF, target, actual, error) for roll (0), pitch (1), or yaw (2)
rate controllers. Used to compute control effort (|P + D + FF|) from Lua.
- Add get_attitude_control() public accessor to QuadPlane
- Add despitch, roll and yaw
…ed pitch (#111)

* Remove controller desaturation in control effort
* Add desaturation logic for Desired servo tilt
* Add logging for VH Power
* Add hard limit for pitch angle setpoint
* Add new parameters in default.param
* Add logging for the position controller demanded pitch
---------

Co-authored-by: Manuraj P M <[email protected]>
* introduced parameter LND_DET_TIM that controls how many milliseconds before disarm is detected
* add disarm watchdog and disable weathervane after touchdown
* Weathervane disable logic changed
* expose land detection timing as params Q_LND_RELAX_MS and Q_LND_LLIM_MS
---------

Co-authored-by: Stefard100 <[email protected]>
* Fix feedforward_scalar calculation when thrust angle error exceeds limits in AC_AttitudeControl.cpp
* add resume after autobailout
@akshar-airbound akshar-airbound self-assigned this Jul 13, 2026
@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR bumps the firmware version to rc7-fixes and delivers several targeted fixes and new features for the Airbound tailsitter platform: a correct feedforward-scalar formula in the attitude controller, a new PIT_CLIP_MAX pitch-clamping parameter, additional Lua scripting bindings that expose attitude and PID state, a major autobailout rewrite with rolling-window analysis and auto-resume logic, and revised door-control logic tied to VTOL transition detection.

  • Feedforward scalar fix (AC_AttitudeControl.cpp): The else if (_thrust_error_angle > 2×threshold) branch previously subtracted only threshold from _thrust_error_angle, producing a scalar of 0 (instead of 1) exactly at the branch boundary and going negative above it. The corrected formula subtracts 2×threshold, giving a clean [0, 1] taper from the 2× to 3× threshold band.
  • PIT_CLIP_MAX pitch clamp (AC_AttitudeControl.cpp): Clamps _attitude_target pitch when the tailsitter is in steady VTOL flight; _ang_vel_target is not updated alongside it, so feedforward continues to command pitch rate at the boundary, which can produce modest overshoot until the I-term compensates.
  • Autobailout rewrite (autobailout.lua): Adds configurable rolling-window average/peak pitch monitoring, rate-based prediction, a bounded auto-resume mechanism, and a loop-rate parameter; previously flagged global-variable issues (is_vtol_flight, residual globals in para_deploy()) persist.

Confidence Score: 4/5

Mostly safe to merge; the open issue from the previous review (yaw I-term wind-up when pitch saturates tilt range) is the most consequential outstanding concern.

The feedforward scalar formula fix is correct and the new autobailout logic is substantially more robust than what it replaces. The new PIT_CLIP_MAX pitch-clamp feature works, but omits updating _ang_vel_target when the attitude target is clamped, meaning feedforward continues to push pitch rate at the boundary and may cause consistent overshoot in borderline conditions. Combined with the still-unresolved yaw saturation / I-term wind-up removal from AP_MotorsTailsitter, the flight-control path has a couple of open correctness gaps that should be tracked even if they are unlikely to cause immediate failures in nominal flight.

libraries/AC_AttitudeControl/AC_AttitudeControl.cpp (pitch clamp vs _ang_vel_target) and libraries/AP_Motors/AP_MotorsTailsitter.cpp (yaw saturation / limit.yaw removal)

Important Files Changed

Filename Overview
libraries/AC_AttitudeControl/AC_AttitudeControl.cpp Adds pitch-clamp feature for tailsitter VTOL (PIT_CLIP_MAX) and fixes the feedforward scalar formula in attitude_controller_run_quat; the scalar is now correctly 1.0 at the 2×threshold boundary and tapers to 0 at 3×threshold. New pitch-clamp block only updates _attitude_target without zeroing _ang_vel_target, leaving residual feedforward that can drive pitch rate beyond the clamped limit.
libraries/AP_Scripting/lua_bindings.cpp Adds four new Lua bindings (qp_att_desired, qp_att_actual, qp_angle_rate, qp_rate_pid_info) that expose attitude controller internals via table returns; implementations are cleanly guarded with #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) && HAL_QUADPLANE_ENABLED.
libraries/AP_Scripting/lua_bindings.h New function declarations added without the same #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) && HAL_QUADPLANE_ENABLED guard used in the .cpp implementations; linker safety relies entirely on callers being guarded.
libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C-bdshot/scripts/autobailout.lua Significant rewrite adding rolling-window pitch monitoring, rate-based pitch prediction, and auto-resume logic. Several variables in para_deploy() remain global (pre-existing). is_vtol_flight assignment is still a global (noted in previous review).
libraries/AP_HAL_ChibiOS/hwdef/Pixhawk6C-bdshot/scripts/ab_door_auto_control.lua Door logic rewritten from landing-latch approach to VTOL-flight-detection based on first forward transition completion; backtransition_complete_time_ms is assigned but never read back for a delay gate (noted in previous review).
libraries/AP_Motors/AP_MotorsTailsitter.cpp Removed yaw headroom computation and limit.yaw signalling; tilt outputs now pass unsaturated pitch_thrust and raw yaw_thrust with no clipping or I-term wind-up protection (addressed in previous review).
ArduPlane/tailsitter.cpp Moved extra_elevator to outer function scope (initialized to 0) so it is available for PHID logging; added position_pitch_sp logging field. Functional behaviour unchanged.
ArduPlane/quadplane.h Adds two inline public getters to expose attitude_control and ahrs_view pointers for the new Lua bindings layer; straightforward accessor additions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[attitude_controller_run_quat] --> B{_ts_enabled &&\n!_ts_in_transition?}
    B -- Yes --> C[to_euler _attitude_target]
    C --> D[constrain pitch to ±PIT_CLIP_MAX]
    D --> E[from_euler back to quaternion]
    E --> F[_ang_vel_target unchanged ⚠️]
    B -- No --> G
    F --> G[thrust_heading_rotation_angles]
    G --> H[update_ang_vel_target_from_att_error]
    H --> I[ang_vel_body_feedforward = rotation * _ang_vel_target]
    I --> J{thrust_error_angle?}
    J -- "> 3×threshold" --> K[zero feedforward\nreset yaw I-term]
    J -- "> 2×threshold" --> L[scalar = 1 - err-2t / t\napply scaled feedforward]
    J -- "≤ 2×threshold" --> M[full feedforward applied]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[attitude_controller_run_quat] --> B{_ts_enabled &&\n!_ts_in_transition?}
    B -- Yes --> C[to_euler _attitude_target]
    C --> D[constrain pitch to ±PIT_CLIP_MAX]
    D --> E[from_euler back to quaternion]
    E --> F[_ang_vel_target unchanged ⚠️]
    B -- No --> G
    F --> G[thrust_heading_rotation_angles]
    G --> H[update_ang_vel_target_from_att_error]
    H --> I[ang_vel_body_feedforward = rotation * _ang_vel_target]
    I --> J{thrust_error_angle?}
    J -- "> 3×threshold" --> K[zero feedforward\nreset yaw I-term]
    J -- "> 2×threshold" --> L[scalar = 1 - err-2t / t\napply scaled feedforward]
    J -- "≤ 2×threshold" --> M[full feedforward applied]
Loading

Reviews (2): Last reviewed commit: "Change version to 4.5.7.5-rc7-fixes" | Re-trigger Greptile

Comment on lines 212 to +214
// thrust vectoring
pitch_thrust = constrain_float(pitch_thrust, -1.0f, 1.0f);
float yaw_headroom = 1.0f - fabsf(pitch_thrust);
float yaw_thrust_limited = constrain_float(yaw_thrust, -yaw_headroom, yaw_headroom);
if (fabsf(yaw_thrust_limited) < fabsf(yaw_thrust)) {
limit.yaw = true;
}
_tilt_left = pitch_thrust - yaw_thrust_limited;
_tilt_right = pitch_thrust + yaw_thrust_limited;
_tilt_left = pitch_thrust - yaw_thrust;
_tilt_right = pitch_thrust + yaw_thrust;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Yaw saturation no longer signalled to the attitude controller

The removed block constrained pitch_thrust to [-1, 1], computed the remaining headroom for yaw, and — critically — set limit.yaw = true when yaw demand had to be clipped. ArduPilot uses limit.yaw to freeze the yaw PID I-term while the actuator is saturated; without it the integrator winds up freely whenever pitch consumes the full tilt range. When pitch demand later decreases, the accumulated yaw I-term discharges suddenly, introducing an uncontrolled yaw kick that can destabilise the vehicle. The pitch_thrust constraint was also a safety net; its removal means values outside [-1, 1] silently propagate into the tilt outputs with no saturation flag set.

Comment on lines +1699 to 1730
---@return number -- yaw_cd
function qp_att_desired() end

-- desc
---@return number -- roll_cd
---@return number -- pitch_cd
---@return number -- yaw_cd
function qp_att_actual() end

-- desc
---@return number -- roll_dps
---@return number -- pitch_dps
---@return number -- yaw_dps
function qp_angle_rate() end


--desc
---@param axis integer
---| '0' # Roll axis
---| '1' # Pitch axis
---| '2' # Yaw axis
---@return number -- P
---@return number -- I
---@return number -- D
---@return number -- FF
---@return number -- target rad/s
---@return number -- actual rad/s
---@return number -- error rad/s
function qp_rate_pid_info(axis) end

-- desc
---@class LED

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 LuaDoc return-type annotations don't match the implementation

All four new functions (qp_att_desired, qp_att_actual, qp_angle_rate, qp_rate_pid_info) are annotated as returning multiple ---@return number values, but the C++ implementations each push a single Lua table onto the stack (lua_newtablereturn 1). The autobailout.lua script uses the table form correctly (desired.pitch_cd, vtol_pitch_rate_pid.actual), but any user relying on the docs will write code expecting three separate return values and get a table instead, breaking their script silently at runtime.

logger:write('AUTB', 'AvgErr,PeakAng,PitchDeg,QPit,QRateP', 'fffff', avg_err, peak_ang, pitch_deg, actual_vtol_pitch_deg, actual_vtol_pitch_rate)
end

is_vtol_flight = in_vtol_flight()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing local keyword causes is_vtol_flight to be written into the global Lua namespace on every update() call. While functionally harmless here (it is written before each read within the same call), global namespace pollution is a common source of hard-to-debug cross-script interference in ArduPilot's Lua environment.

Suggested change
is_vtol_flight = in_vtol_flight()
local is_vtol_flight = in_vtol_flight()

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants