Add 4575 rc4 fixes to airbound-develop - #118
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.
Greptile SummaryThis PR bumps the firmware version to
Confidence Score: 3/5Not safe to merge as-is: the removal of The most impactful change — moving servo saturation from the motors library to libraries/AP_Motors/AP_MotorsTailsitter.cpp (limit.yaw removal) and ArduPlane/tailsitter.cpp (desaturation output calculation) need the most attention before merging. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant AC as AC_AttitudeControl
participant MT as AP_MotorsTailsitter
participant TS as Tailsitter::output()
participant SRV as SRV_Channels
AC->>MT: output_armed_stabilizing()
Note over MT: pitch_thrust, yaw_thrust → _tilt_left/_tilt_right<br/>(no saturation, limit.yaw never set)
MT->>SRV: set_output_scaled(tiltLeft, _tilt_left × 4500)
MT->>SRV: set_output_scaled(tiltRight, _tilt_right × 4500)
TS->>SRV: get_output_scaled(tiltLeft/Right)
Note over TS: Apply vectored_hover_gain + extra_elevator
Note over TS: Desaturation block:<br/>pitch_phi_limited = clamp(pitch_phi, ±4500)<br/>yaw headroom = 4500 − |pitch_phi_limited|<br/>tilt = pitch_phi ± yaw_phi_limited ⚠ uses pitch_phi not pitch_phi_limited
TS->>SRV: set_output_scaled(tiltLeft, tilt_left)
TS->>SRV: set_output_scaled(tiltRight, tilt_right)
Note over AC: limit.yaw never set →<br/>yaw I-term winds up silently
%%{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"}}}%%
sequenceDiagram
participant AC as AC_AttitudeControl
participant MT as AP_MotorsTailsitter
participant TS as Tailsitter::output()
participant SRV as SRV_Channels
AC->>MT: output_armed_stabilizing()
Note over MT: pitch_thrust, yaw_thrust → _tilt_left/_tilt_right<br/>(no saturation, limit.yaw never set)
MT->>SRV: set_output_scaled(tiltLeft, _tilt_left × 4500)
MT->>SRV: set_output_scaled(tiltRight, _tilt_right × 4500)
TS->>SRV: get_output_scaled(tiltLeft/Right)
Note over TS: Apply vectored_hover_gain + extra_elevator
Note over TS: Desaturation block:<br/>pitch_phi_limited = clamp(pitch_phi, ±4500)<br/>yaw headroom = 4500 − |pitch_phi_limited|<br/>tilt = pitch_phi ± yaw_phi_limited ⚠ uses pitch_phi not pitch_phi_limited
TS->>SRV: set_output_scaled(tiltLeft, tilt_left)
TS->>SRV: set_output_scaled(tiltRight, tilt_right)
Note over AC: limit.yaw never set →<br/>yaw I-term winds up silently
Reviews (1): Last reviewed commit: "Revert "Fix reduce disarm delay (#109)"" | 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.
Missing
limit.yaw flag after saturation removal
The old code set limit.yaw = true whenever yaw thrust was clipped to its headroom. That flag is read by AC_AttitudeControl to suppress yaw integrator accumulation during saturation. The new code removes the saturation entirely here and relies on tailsitter.cpp to clamp servo outputs — but tailsitter.cpp runs after the motors library returns, so it never feeds limit.yaw back to the attitude controller. When yaw is saturated at the servo level, the yaw PID I-term will keep winding up unabated, potentially causing yaw oscillations or a persistent heading error after the saturation clears.
| tilt_left = pitch_phi - yaw_phi_limited; | ||
| tilt_right = pitch_phi + yaw_phi_limited; |
There was a problem hiding this comment.
Desaturation uses unsaturated
pitch_phi for final output
When pitch_phi > 4500, pitch_phi_limited is clamped to 4500 and yaw_phi_headroom collapses to 0. But tilt_left and tilt_right are then set to pitch_phi - 0 = pitch_phi, not pitch_phi_limited. The outputs can exceed ±4500 centidegrees whenever pitch is saturated. Physical servo movement is ultimately clamped by the SRV_Channels framework, but the values stored in the SRV channel, used for logging (DesLPst, DesRPst), and any downstream consumers are incorrect — they show an unsaturated pitch value when the intent of the block is to log the post-saturation command.
| tilt_left = pitch_phi - yaw_phi_limited; | |
| tilt_right = pitch_phi + yaw_phi_limited; | |
| tilt_left = pitch_phi_limited - yaw_phi_limited; | |
| tilt_right = pitch_phi_limited + yaw_phi_limited; |
| if(_ts_enabled && !_ts_in_transition){ | ||
| Vector3f euler_sp; | ||
| _attitude_target.to_euler(euler_sp.x, euler_sp.y, euler_sp.z); | ||
| euler_sp.y = constrain_float(euler_sp.y,radians(-_att_max_pit),radians(_att_max_pit)); | ||
| _attitude_target.from_euler(euler_sp.x, euler_sp.y, euler_sp.z); | ||
| } |
There was a problem hiding this comment.
_ang_vel_target.y not updated alongside pitch quaternion clipping
The attitude relaxation code immediately above (line ~782) clips both euler_sp.y and _ang_vel_target.y together before rebuilding the quaternion. The new pitch-clipping block clips euler_sp.y inside the quaternion but leaves _ang_vel_target.y at its pre-clip value. When the pitch target is being actively limited, the quaternion encodes one pitch and the feed-forward angular velocity encodes a different (higher) pitch rate, creating a brief velocity-attitude mismatch that can produce an overshoot impulse at the clip boundary.
| int lua_get_rate_pid_info(lua_State *L); | ||
| int lua_get_att_target_euler_cd(lua_State *L); | ||
| int lua_get_rate_ef_targets(lua_State *L); | ||
| int lua_get_actual_euler_cd(lua_State *L); |
There was a problem hiding this comment.
New declarations lack the same conditional compilation guard used in the implementation
In lua_bindings.cpp the four new functions are wrapped in #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) && HAL_QUADPLANE_ENABLED, but their declarations here are unconditional. Any non-ArduPlane build that includes this header and tries to link against these symbols will fail at link time. Wrapping the declarations in the same guard keeps the two files consistent.
| int lua_get_rate_pid_info(lua_State *L); | |
| int lua_get_att_target_euler_cd(lua_State *L); | |
| int lua_get_rate_ef_targets(lua_State *L); | |
| int lua_get_actual_euler_cd(lua_State *L); | |
| #if APM_BUILD_TYPE(APM_BUILD_ArduPlane) && HAL_QUADPLANE_ENABLED | |
| int lua_get_rate_pid_info(lua_State *L); | |
| int lua_get_att_target_euler_cd(lua_State *L); | |
| int lua_get_rate_ef_targets(lua_State *L); | |
| int lua_get_actual_euler_cd(lua_State *L); | |
| #endif |
Reverts disarm delay changes added in pr-airbound-4575-rc3-fixes branch.
Notion Page: https://app.notion.com/p/airbound/Revert-disarm-delay-PR-109-38721adf4be980f09db1ffd435316ea8?source=copy_link
Note: This PR replaces #117
The branch pr-4575-rc3-fixes contains rc3 fixes. See 4575 build page
This branch reverts only the disarm delay change added to pr-airbound-4575-rc3 using #109