airbound-develop: Add airbound 4575 rc7 fixes - #127
Conversation
- 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
This reverts commit ea58cdf.
Reduce the Roll angle P gain to 3.75
Greptile SummaryThis PR bumps the firmware version to
Confidence Score: 4/5Mostly 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
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]
%%{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]
Reviews (2): Last reviewed commit: "Change version to 4.5.7.5-rc7-fixes" | Re-trigger Greptile |
| // 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; |
There was a problem hiding this comment.
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.
| ---@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 |
There was a problem hiding this comment.
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_newtable … return 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() |
There was a problem hiding this comment.
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.
| 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!
Notion page:
https://app.notion.com/p/airbound/airbound-develop-Add-4-5-7-5-rc7-features-39a21adf4be9800db502d649aafc48cd?source=copy_link