Attendees (unique) : 7
UTC0800
master ← peterbarker:pr-claude2/pr/dca-takeoff-settle
opened 09:12AM - 16 Aug 26 UTC
### Summary
Hacks in a settle period for DO_CHANGE_ALTITUDE's takeoff step. … TECS causes the Plane to overshoot its 30m target by 11m. That was 1.5m in 2024.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [x] Non-functional change
- [x] No-binary change
- [x] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
The test takes off to 30m and immediately asserts 30m +-1m held for 10s within 60s. TAKEOFF hands back to TECS 2m below the target while the vehicle is still climbing at 9.3m/s, so it overshoots to about 40m, sinks to 26.5m and takes some 25s to settle - and the assertion was paying for that transient out of its own budget, using 34s of the 60. Three runs in 26 overnight ran out of time and reported an altitude on the way back up, which is why the failures were always just below the band and never above it.
Wait for the vehicle to be established first. Measured over three runs: +-2m held for 5s completes 25s after the handover. A shorter hold is no use - +-2m for 2s is satisfied after 7s by the climb passing through the band on its way up, while still 10m from settled.
The overshoot itself is a vehicle-side regression, traced to three commits between August 2024 and April 2025; this only stops the test tripping over it.
Some analysis of the overshoot. The regression from 2024 actually came in multiple tranches.
TECS severely overshoots the takeoff altitude in SITL.
George : 2 options
Use the airspeed control
Or I’ll go in and improve TECS
Peter : I’d prefer we fix this properly
Andrew : Reduce TKOFF_THR_MAX
TECS isn’t very good at takeoffs, we don’t want it to nose down when the airspeed is low.
UTC0814
master ← Hwurzburg:hwdef-vtx-bootloader-float-fix
opened 04:14PM - 18 Aug 26 UTC
### Summary
Fixes VTX power pin left floating during bootloader (DFU/SD-card fl… ashing) on 12 in-tree boards, by mirroring the `hwdef.dat` pin default into `hwdef-bl.dat` and rebuilding each board's bootloader binary.
### Classification & Testing (check all that apply and add your own)
- [ ] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [ ] Automated test(s) verify changes (e.g. unit test, autotest)
- [x] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
`Tools/scripts/check_branch_conventions.py --base-branch upstream/master` passes (commit
structure, subsystem tags, trailing newlines). Each board's bootloader rebuilt successfully
with `./waf configure --board <board> --bootloader --Werror && ./waf bootloader` (GNU Arm
Embedded Toolchain 10-2020-q4-major, via `Tools/scripts/build_bootloaders.py`).
Not yet bench-tested on hardware to confirm the VTX rail no longer floats during DFU — I
don't have access to all 12 boards, flagging for maintainers/vendors who do.
### Description
On 12 in-tree boards, the VTX power switch pin (a `RELAYn_PIN_DEFAULT`/`PINIOn`/bare-GPIO
output) is given a default `OUTPUT` level in `hwdef.dat`, but that pin was never mirrored
into `hwdef-bl.dat`. ChibiOS's own default for an unconfigured pin is `INPUT FLOATING`, so
for the entire time each of these boards sits in the bootloader (DFU flashing or SD-card
firmware loading), the VTX power rail floats — even though the main firmware correctly
drives it once it boots.
Found while auditing this exact issue on open new-board PRs (originally flagged by an
automated review on #33519); this PR is the same fix applied to boards already merged to
master:
- AEDROXH7 (PB12 `VTX_SW`)
- DAKEFPVF405 (PB4 `VTX_PWR`)
- DAKEFPVH743Pro (PE3 `PINIO2`)
- FlyFishRCF405 (PC5 `PINIO1`)
- HWH7 (PE4 `VTX_POWER`)
- JHEMCUF405WING (PC13 `PINIO1`)
- LongBowF405WING (PC13 `PINIO1`)
- OrqaF405Pro (PB9 `VTX_SW`)
- SIMPLIFLYH7 (PB2 `PINIO1`)
- SPEDIXH743 (PA2 `VTX_SW`)
- SpeedyBeeF405WING (PC13 `PINIO1`)
- speedybeef4v5 (PC13 `VTX_PWR`)
Each board gets two commits: the `hwdef-bl.dat` source fix (`hwdef:` prefix), and a
rebuilt bootloader binary (`bootloaders:` prefix, built with GNU Arm Embedded Toolchain
10-2020-q4-major via `Tools/scripts/build_bootloaders.py`). `LongBowF405WING` and
`SpeedyBeeF405WING` didn't have a `.hex` committed previously (only `.bin`) — the rebuild
script generates both, so both are now included for those two boards as well.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
A : Yes, I’m not opposed to that.
It will not end up in people’s boards anytime soon. People don’t upload their bootloaders frequently at all.
Merged!
UTC0819
master ← tridge:pr-fix-blheli-race
opened 11:42PM - 17 Aug 26 UTC
alternative minimal fix for #33933
we want a minimal fix for backport to 4.7, … we can address the shared DMA guards separately but don't want to hold up the fix
A : I need a little more time to process this.
UTC0820
master ← Ecognize:pr/multisource_radio_status
opened 06:55PM - 15 Aug 26 UTC
### Summary
Allows to distinguish between data coming from multiple radios co… nnected to the same system.
### Classification & Testing (check all that apply and add your own)
- [X] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [ ] Automated test(s) verify changes (e.g. unit test, autotest)
- [X] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [X] Logs attached
- [ ] Logs available on request
### Description
Quality of life change for logging multiple redundant radios at the same time and being able to tell them apart. Assuming the system integrator is supposed to ensure differing (sysid,compid) designation. Works in SITL, e.g. when sending mock `RADIO_STATUS` from a python script:
```
$ mavlogdump.py --types RAD logs/00000013.BIN
2026-08-15 21:46:50.02: RAD {TimeUS : 29065036, RSSI : 80, RemRSSI : 75, TxBuf : 100, Noise : 10, RemNoise : 5, RxErrors : 0, Fixed : 0, SS : 51, SC : 3}
2026-08-15 21:46:51.01: RAD {TimeUS : 30064636, RSSI : 85, RemRSSI : 80, TxBuf : 100, Noise : 12, RemNoise : 7, RxErrors : 1, Fixed : 0, SS : 52, SC : 1}
2026-08-15 21:46:52.02: RAD {TimeUS : 31065069, RSSI : 90, RemRSSI : 85, TxBuf : 100, Noise : 14, RemNoise : 9, RxErrors : 2, Fixed : 0, SS : 53, SC : 2}
```
A : This sytem is very rare, in my opinion.
UTC0829
master ← andyp1per:pr-ek3-magcal7-ground-yaw-anchor
opened 05:28PM - 14 Aug 26 UTC
### Summary
EK3_MAG_CAL=7 (6774c1b31e) learns the mag field states while on t… he ground, but a stationary vehicle gives the 3-axis fusion no yaw observability, so the yaw estimate can walk away from the compass heading and block arming. This anchors the yaw with a magnetic heading fusion while ground-learning is active.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [x] Tested manually, description below (e.g. SITL)
- [x] Tested on hardware
- [x] Logs available on request
Replay A/B on the two bench logs that hit the failure (same tree, only this change different): unfixed reproduces the walk, 54 to 207 deg over 105 s; fixed holds both cores within 1 deg of the compass heading for the full log. Bench-tested on a second vehicle: 47 s stationary through origin set and then a ~200 deg hand rotation, both cores tracked DCM within 1.6 deg with the 3-axis learning path active throughout.
### Description
With mag field learning active on a stationary vehicle, a yaw error is absorbed by the body field states with zero innovation, so nothing corrects it and each core free-integrates its own gyro bias. We hit this on an octaquad at a site whose local field disagrees with the WMM tables: the walk starts the moment the origin is set and the earth field states reset to the tables, each core reconciling the mismatch by rotating yaw in its own direction at ~0.35 deg/s. The pre-arm reported "EKF3 Yaw inconsistent" growing 86 to 169 deg (so "Wait" could never clear it) while DCM held the true heading on the same magnetometer and the mag test ratio never exceeded 0.34 - the filter was self-consistent and wrong.
The fix fuses the magnetic heading alongside the 3-axis fusion while learning on the ground in mode 7. The heading measurement comes from the raw compass, not the learned field states, so the anchor is not circular. With yaw pinned and the earth field held to the tables, the body field states become fully observable at a fixed heading, which is the battery-signature learning the mode exists for. Falling back to plain heading fusion on the ground (as mode 3 does) would also stop the walk, but it inhibits the ground learning that is the point of mode 7.
Replay of the failing log, unfixed vs fixed, against the compass-only DCM reference (the step at ~42 s is a real field disturbance that DCM also tracks):
<img width="1170" height="585" alt="pr_magcal7_yaw_anchor" src="https://github.com/user-attachments/assets/ba9001a9-b5f7-4cb4-96e8-f56dcdf7a776" />
Mode 4 (ALWAYS) shares the same on-ground observability gap but its behaviour is long-standing, so this change is scoped to mode 7 only.
A : To what yaw measurement/baseline would the compass learning anchor to?
P : Not flying doesn’t mean the aircraft doesn’t move. A person might be carrying it around.
UTC0838
master ← peterbarker:pr-claude2/waf-single-firmware
opened 01:17AM - 12 Aug 26 UTC
### Summary
Stops people attempting to (e.g.) `./waf copter rover` as it can … not just fail to compile but provide "corrupt" binaries
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [x] Non-functional change
- [x] No-binary change
- [x] Infrastructure change (e.g. unit tests, helper scripts)
- [ ] Automated test(s) verify changes (e.g. unit test, autotest)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
```
┌────────────────────────┬──────────────────────────────────────────┐
│ Invocation │ Result │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf copter plane │ fatal, before any build work │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf copter AP_Periph │ fatal │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf copter │ builds │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf copter copter │ builds (same firmware twice is harmless) │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf copter examples │ builds │
├────────────────────────┼──────────────────────────────────────────┤
│ ./waf bin / ./waf all │ unaffected │
└────────────────────────┴──────────────────────────────────────────┘
```
### Description
`./waf copter plane` does not do what it looks like it does. Each build command extends bld.options.program_group, and bld.options is waf's global options object rather than anything owned by the build context, so the list accumulates across the commands run by one invocation. The second command therefore selects the first's programs as well as its own:
ACCUM cmd=copter program_group=['copter'] (id=123652359700064)
ACCUM cmd=plane program_group=['copter', 'plane'] (id=123652359700064)
Same options object both times. The vehicles compile the shared libraries with their own feature defines, so building them this way can link one firmware against objects compiled for another. The symptom seen was a link failure naming symbols only another vehicle enables:
undefined reference to `AC_PrecLand::get_target_location(Location&)'
undefined reference to `AP_Winch::set_desired_rate(float)'
from `./waf plane copter rover sub blimp heli`, reproducible from a clean build directory and absent when the same tree was built one vehicle at a time. A link which fails is the good case; the same mixing can also produce a binary which links cleanly.
Two in-tree callers already avoid this, both carrying the comment "we can't run `./waf copter blimp plane` without error, so do them one-at-a-time" - so make it a fatal error with a message saying what to do instead, rather than leaving it as folklore.
This only rejects asking for two *different* firmwares in one invocation. Group builds such as `./waf bin` are unaffected: they are a single command producing a single task graph, in which each vehicle's objects are distinct tasks. Repeating one firmware is also still fine.
P : Bad things happen when you try to build more than one vehicle at once.
A : This used to work fine! That’s likely a regression.
P : ./waf all still works.
A : The appveyor script fails, but we can drop it, we don’t use it anymore.
The robot review points to legacy defines injecting the wrong thing at the wrong place. It’s likely not a problem with waf itself.
UTC0845
master ← Georacer:pr/last_letter_ci
opened 12:31PM - 11 Aug 26 UTC
### Summary
Adds a CI test for the last_letter simulation backend.
### Cla… ssification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [x] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [x] Logs attached
- [ ] Logs available on request
SITL log: https://www.dropbox.com/scl/fi/77cdmqabx0lq48s4qostf/00000003.BIN?rlkey=bos9sbvkrglk9q9n20s2upxda&st=6fkdta46&dl=0
### Description
Adds a new github workflow which:
- Builds plane SITL.
- Pulls a pinned version of the last_letter_ardupilot binary, its dynamic library and the models folder.
- Runs a duplicate of the `LOITER` test.
A : It would be nice to have a .sh script to configure the downloads (apart from the classic ardupilot invocations). It would allow us to test it locally more easilly.
Point your AI to the comments raised by my AI.
UTC0853
master ← andyp1per:pr-bdshot-gcr-validation
opened 10:47AM - 08 Aug 26 UTC
### Summary
The GCR decode table mapped the sixteen quintets the encoding never… emits to nibble 0, which is indistinguishable from the legitimate 0 at index 25. A corrupt quintet therefore decoded silently, leaving the four bit checksum as the only guard against a bad eRPM reaching the harmonic notch.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
Table verified exhaustively against the old one: the sixteen entries now marked `0xff` are exactly the codes the encoder cannot produce, the sixteen valid entries are unchanged and cover all sixteen nibbles, and all 65536 words built only from valid quintets decode to the same value as before. Every word containing an impossible quintet is rejected. Builds for a bdshot target.
### Description
Betaflight measures 5-8% of bidirectional DShot frames failing to decode with motors running, so this path takes corrupt input constantly and by design - it is not an error case. What it did with that input was to map any impossible quintet onto nibble 0 rather than rejecting it, because 0 was also the table's "no such code" filler. The checksum was then the only thing standing between a corrupted frame and an accepted eRPM, and four bits lets roughly one in sixteen through.
The value matters beyond a telemetry display: it drives RPM-referenced harmonic notch tracking, so a wrong eRPM moves the notch off the real motor frequency.
Impossible quintets are now marked `0xff` and the word is rejected if any of its four nibbles came from one. The test is a single OR and compare, on a path that already computes a checksum.
The four lookups had to be pulled out into named values rather than left as the running `|=` accumulation: a valid result uses all sixteen bits, so there is no spare bit for a sentinel to survive the shifts - only the top quintet's would land clear of the result.
P : Looks OK, but we need to wait for the fix suggested.
UTC0856
https://github.com/ArduPilot/ardupilot/pull/mavlink/mavlink/2251
P : My concern is with the orientation field. The orientation changes.
A : You would have to use the v1 message.
P : The idea is to deprecate it. I suggest an extension to the v2 message, carrying the orientation quaoternion.
A : Do we have the orientation reported in another message, e.g. a camera or gimbal message?
P : Can’t find one.
A : Up to you whether to ask for the orientation field.
Would be nice to have an implementation in mind, in order to judge this.
P : Approved!
UTC0908
https://github.com/ArduPilot/ardupilot/pull/mavlink/rfcs/30
A : I’m not keen. An operator responding to a message is too slow. You would want Lua or a companion to react automatically, which is another route.
This looks very bespoke and not scalable.
These one-off messages are also costing flash onboard.
P : Maybe there is enough time in the system for an operator to react manually.
A : Perhaps. But the response mechanism/workflow is also missing from this suggestion.
UTC0922
master ← andyp1per:pr-ins-gyro-cal-rotation
opened 10:44AM - 08 Aug 26 UTC
### Summary
Gyro calibration zeroed `_board_orientation` so its own samples cam… e out in board frame, but that field is global, so the accel lost its rotation too. DCM's startup alignment reads the last accel published in that window, so on a board whose orientation flips Z it aligns 180 degrees out and takes minutes of drift correction to walk back, failing the attitude pre-arm throughout.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [x] Tested on hardware
Found on a board with an `AHRS_ORIENTATION` that flips Z, where the DCM attitude pre-arm failed for minutes after every boot. With the change it passes immediately. Builds and runs in SITL.
### Description
`_init_gyro()` saved `_board_orientation`, set it to `ROTATION_NONE` for the duration of the calibration and restored it afterwards. The intent was to keep the calibration samples in board frame, but `_board_orientation` is also applied by `_rotate_and_correct_accel()`, so every accel published during the calibration is unrotated as well.
That matters because the value outlives the calibration. `_accel[0]` holds the last one, and `AP_AHRS_DCM::reset()` reads it a few lines later in `init_ardupilot()` to set the initial attitude, gating only on the vector magnitude - a board-frame 9.81 passes. On an upright board the two frames agree and nothing shows, which is why it has gone unnoticed; it needs an orientation that flips Z to be visible at all.
The gyro backend already skips the offset subtraction while `_calibrating_gyro` is set, so the rotation is now skipped in the same place and `_board_orientation` is left alone. The accel is then never published in board frame, and DCM aligns level whether the value it reads is fresh or stale.
Teaching DCM to reject a stale accel instead would leave the board-frame value visible to everything else that reads the accel during calibration, so it treats the symptom rather than the cause.
MergeOnCIPass
UTC0924
master ← tridge:pr-mavlink-rangefinder-id
opened 12:53AM - 08 Aug 26 UTC
### Summary
Allow multiple MAVLink rangefinders by using `RNGFNDn_ADDR` to sele… ct which `DISTANCE_SENSOR` message id each backend accepts.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [x] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
The existing Copter `RangeFinder` autotest is extended to configure two MAVLink
backends with `RNGFND1_ADDR=1` and `RNGFND2_ADDR=2`, feed `DISTANCE_SENSOR`
messages with each id in turn, and check that the reported distance shows up on
the matching backend only.
### Description
Previously the MAVLink rangefinder backend filtered incoming `DISTANCE_SENSOR`
messages on orientation only, so two MAVLink rangefinders with the same
orientation could not be distinguished and both backends consumed every message.
This adds an id filter based on the existing `RNGFNDn_ADDR` parameter:
- `RNGFNDn_ADDR` of 0 keeps the old behaviour and accepts any `DISTANCE_SENSOR` id
- a non-zero `RNGFNDn_ADDR` only accepts messages whose `id` field matches
The `ADDR` parameter documentation is updated to describe the MAVLink use.
P : Approved!
Merged!
UTC0926
master ← Hwurzburg:qrtl-gradual-rtl-alt-descent
opened 06:04PM - 21 Jul 26 UTC
### Summary
Changes how QRTL's approach phase handles altitude when the vehicle… is well above
`RTL_ALTITUDE` when the return leg starts — the target altitude now ramps down gradually
instead of snapping straight to `RTL_ALTITUDE`.
### Classification & Testing (check all that apply and add your own)
- [ ] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
`./waf plane` builds cleanly. Added `QRTLGradualAltDescent` SITL autotest
(`Tools/autotest/quadplane.py`, run via `test.QuadPlane.QRTLGradualAltDescent`), which
flies out ~900m, triggers QRTL, and asserts the vehicle does not shed more than 15m of
altitude in the first 15 seconds, then completes a normal VTOL landing. Verified the test
fails without the fix (drop of 17m in 7s reverting `mode_qrtl.cpp`/`mode.h`) and passes
with it.
### Description
Previously, once QRTL's approach phase began, the target altitude snapped straight to
`RTL_ALTITUDE` regardless of how much higher the vehicle actually was, causing an
immediate steep descent while still far from home.
The target now ramps down gradually from the vehicle's actual altitude at the start of the
leg down to `RTL_ALTITUDE`, reaching it at the same distance-from-home threshold where the
existing `RTL_ALTITUDE -> Q_RTL_ALT` approach ramp already begins — so the two ramps join
continuously.
If the vehicle is at or below `RTL_ALTITUDE` at that point, behaviour is unchanged. This is
now the standard QRTL behaviour (no `Q_OPTIONS` bit needed).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
A : This changes behaviour in RTL, it will ramp down eventually. There is risk of hitting trees and Pete is the one who should decide.
I see in the description that the previous behaviour was actually to step the altitude down immediately.
Pete has approved.
Some of the AI comments are valid, though.
Let’s have Pete check it again.
UTC0937
master ← tridge:circuit-status
opened 11:04PM - 17 Jul 26 UTC
### Summary
Adds a lua driver for the DroneCAN uavcan.equipment.power.Circuit… Status message, mapping individual circuits onto ArduPilot battery monitor instances, with SITL support and an autotest.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [x] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [x] Tested manually, description below (e.g. SITL)
- [x] Tested on hardware
- [ ] Logs attached
- [x] Logs available on request
The new QuadPlane.CircuitStatusScript autotest boots the quadplane-can frame with the driver installed and checks that two scripting monitors fed from CircuitStatus match a DroneCAN reference monitor on the same periph battery for both voltage and current, which also covers the float16 decoding.
### Description
This allows per-circuit voltage and current from a CAN power distribution board to be monitored, logged and reported as batteries.
The number of circuits is set with DCS_NUM_CIRCUITS, which dynamically creates DCSx_CIRCUIT_ID and DCSx_BATT_IDX parameters mapping each circuit_id to a battery monitor instance with BATTn_MONITOR=29 (scripting). Circuit mappings are picked up at runtime, only DCS_NUM_CIRCUITS needs a reboot.
To enable testing, the SITL AP_Periph build now sends a CircuitStatus message per active battery backend, and the quadplane-can frame gained a periph_board entry so restart_SITL_frame() can spawn the periph companion in autotests (sim_vehicle.py already defaulted to sitl_periph_universal for this frame).
Tested in SITL and on a CubeOrangePlus with HFE engine which has 3 CircuitStatus messages
P : Approved!
Merged
UTC0940
master ← peterbarker:pr-claude2/dal-eas2tas-from-baro
opened 12:48PM - 05 Jul 26 UTC
### Summary
EAS2TAS is an *input* into the EKFs via the DAL. But `AP::AHRS()… .get_EAS2TAS()` may be an output from a backend. Stop that happening.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
Currently the `AP_AHRS_Backend::get_EAS2TAS` is static - no backend returns anything clever. But an external AHRS definitely could.
Make sure the DAL gets its information from sensor data, not from another backend by sourcing data from the Baro library. The Baro library moves to calculating the value once per update() call - there's some heavy maths behind `_get_EAS2TAS`
A : Initially we computed it in every baro update. That was too expensive.
Then we updated if the baro alt changed by more than a threshold. But it caused step-effects in things like TECS.
Then we changed it again and cached it in AHRS.
Did we come full circle now?
No, we’re not recalculating every call. It’s updating with baro, which is around 50Hz.
Okay, this looks sensible.
Merged!
A : In the future, let’s make sure that a baro failure is handled.
UTC0950
master ← FlyingRC-Official:pr-flyingrch7dpro-upstream
opened 05:47AM - 22 Jun 26 UTC
## Summary
Adds board support for the FlyingRC H7D Pro flight controller.
This… adds two ChibiOS board targets:
- `FlyingRCH7DPro`
- `FlyingRCH7DPro-bdshot`
The `-bdshot` variant follows the existing separate-target pattern used by boards such as `MatekH743-bdshot` and enables bi-directional DShot support for the motor timer groups.
## Hardware
- STM32H743 MCU
- Board ID: `AP_HW_FLYINGRCH7DPRO` / `1242`
- Dual ICM42688-P IMUs on SPI1 and SPI4
- DPS310/SPL06 barometer on I2C
- AT7456E OSD
- microSD
- CAN1
- 12 PWM outputs
- USB FS
## Validation
Built locally on macOS with GCC 10.2.1:
- `./waf configure --board FlyingRCH7DPro && ./waf copter -j8`
- Total flash used: 1,546,512 B
- Free flash: 157,420 B
- `./waf configure --board FlyingRCH7DPro-bdshot && ./waf copter -j8`
- Total flash used: 1,549,248 B
- Free flash: 154,684 B
Hardware validation completed on a real board:
- USB connection
- IMU orientation
- barometer
- OSD
- motor outputs
- bi-directional DShot telemetry
P : The robot points at a problem with the config.
UTC0952
master ← andyp1per:pr-nwblue-fc-squashed-v2
opened 08:21AM - 06 Jun 26 UTC
### Summary
Add board support for the NWBLUE_PROH757, a 30x30mm multirotor flig… ht controller built on the CubePilot CubeNode H757 module.
### Description
The NWBLUE_PROH757 (Metzler LLC) is a carrier board for the CubeNode H757 module: STM32H757, on-module ICM-45686 IMU and DPS368 baro on SPI3, on-board IIS2MDC magnetometer, microSD, 6 UARTs, 9 PWM/DShot outputs, CAN1, and MSP DisplayPort OSD (no analog OSD chip). Battery voltage/current monitoring is on by default; the current sense input comes from the ESC connector.
To build this carrier the CubeNode module pinout had to be shared rather than duplicated, so this PR also refactors the existing CubeNode hwdef:
- The module-fixed pins (MCU type, oscillator, USB, SWD, CAN1, RMII Ethernet PHY, on-module SPI3 IMU pads, CAN sleep/shutdown) move into `CubeNode/hwdef.inc` and `CubeNode/hwdef-bl.inc`.
- The existing CubeNode AP_Periph `hwdef.dat` / `hwdef-bl.dat` become thin wrappers that include the shared inc plus their AP_Periph-specific config; CubeNode-ETH is unchanged. This is a no-op for the CubeNode build, it only exposes the module pinout for reuse by NWBLUE_PROH757.
### Classification & Testing
- [x] Checked by a human programmer
- [ ] Tested on hardware
Builds cleanly for ArduCopter; the CubeNode and CubeNode-ETH AP_Periph targets are unaffected by the inc refactor. Not yet flight tested on hardware.
A : The AI comment re. not printing “USB connected” should be fixed.
P : It seems they are trying to modularize CubeNow into .inc files, then include them to this new board.
But it’s weird how they’re not modularizing the whole CubeNode.dat file.
UTC0959
master ← Georacer:feature/custom_plane_controller
opened 03:02PM - 29 May 26 UTC
### Summary
This PR adds support for custom Plane controllers, as `AC_CustomC… ontrol` [does for Copter](https://ardupilot.org/dev/docs/copter-adding-custom-controller.html).
### Description
A new library `AP_CustomControl` has been created, which roughly operates the same as the existing Copter counterpart.
Things that are the same:
- The overall flag is `AP_CUSTOMCONTROL_ENABLED`. The library is not part of the features list. It is meant to be explicitly, locally compiled in. SITL will compile it by default.
- Multiple custom controllers can be compiled-in and selected via `CC_TYPE`.
- An AUX switch enables or disables the controller (109).
- A basic PID example is given, which can fly a plane successfully.
Things that are different:
- The Copter custom controller is designed to return a strict control API, in the form of `Vector3f` for roll/pitch/yaw pre-mixer inputs. However this is not very useful for Plane. See below for the new API.
- Copter uses `CC_AXIS` to quickly enable/disable custom roll/pitch/yaw controllers. Since AP_CustomController now recommends unconstrained access to output functions and servos alike, The parameter has been replaced by `CP_MASK`. This is meant to be used by the developer to fence whatever function within the custom controller he pleases.
#### Recommended API
The developer has complete freedom to shape the custom controller code to his liking.
However, the following methods of `AP_CustomControl` are the recommended way to interact with the outputs:
```c++
// Write a scaled value to all channels with a function.
void set_output_scaled(SRV_Channel::Function function, float value);
// Write a pwm value to all channels with a function. Not min/max constrained. servos.cpp may overwrite it.
void set_output_pwm(SRV_Channel::Function function, uint16_t value);
// Write pwm values on a channel. Not min/max constrained. servos.cpp may overwrite it.
void set_output_pwm_chan(uint8_t chan, uint16_t value);
// Override pwm values on a channel for one loop. servos.cpp will not overwrite it.
void set_output_pwm_chan_override(uint8_t chan, uint16_t value);
```
These will reach into `SRV_Channels` and write the passed values.
This also means that **any** servo channel can be written to, even unconfigured ones. This is very useful for experimental control allocation schemes.
The euler angle targets are exposed to
```c++
float get_roll_target_deg() { return _frontend.roll_target_deg; }
float get_nav_pitch_target_deg() { return _frontend.pitch_target_deg; }
float get_pitch_target_deg() { return _frontend.pitch_target_deg + _frontend.pitch_trim_deg; }
```
which are filled with
```c++
custom_control.roll_target_deg = nav_roll_cd * 0.01f;
custom_control.pitch_target_deg = nav_pitch_cd * 0.01f;
custom_control.pitch_trim_deg = g.pitch_trim;
```
#### Servo overrides
The custom controller task will run after the `stabilize` task and before the `set_servos` task.
This means that by default the safety checks mixing which happens in `servos.cpp` will still apply and may override the custom controller.
However, a method `set_output_pwm_chan_override(uint8_t chan, uint16_t value)` is given, in order to block `set_servos` from modifying this channel. This can be useful for implementing experimental/custom mixers.
#### Known drawbacks
- The parameter namespace is also `CC`. I think this might cause conflicts in the wiki?
- Due to the implementation details, output functions of GPIO (-1 enum value) cannot be addressed. Not sure how to fix that.
- AFAIK, the Plane codebase doesn't do rate controller and/or control surface bumpless transfer upon mode switches (e.g. FBWA->MANUAL). That means that there will be a step in servo output upon switching out of the custom controller and into a rate-controlling mode. The integrators are being actively reset, but this is a perfect solution. Perhaps the upcoming #32743 will fix this.
- Upon exiting the custom controller, all the main controllers are reset. Since these controllers are individually, constantly reset while the custom controller is running, there might be no reason to reset them all anew, including controllers which might not have been overriden.
#### Known unknowns
- I suspect the current RC inputs API doesn't allow accessing channels >8. I have to verify this.
- If the custom controller writes onto unused output channels, their PWM value will go from 0 whatever is requested. However, when the custom controller is suspended, the servo value will not return to 0. I do not yet know how to restore this state.
<img width="1368" height="919" alt="image" src="https://github.com/user-attachments/assets/ae199adb-25e8-4e05-9302-a11d03f59833" />
### Classification & Testing (check all that apply and add your own)
- [X] Checked by a human programmer
- [ ] Non-functional change
- [ ] No-binary change
- [ ] Infrastructure change (e.g. unit tests, helper scripts)
- [X] Automated test(s) verify changes (e.g. unit test, autotest)
- [X] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [X] Logs attached
- [X] Logs available on request
Testing has been carried out in autotests as well as RealFlight.
The new autotest attempts to explore as much of the new functionality as possible. You need to read the PID example controller that is used in order to fully understand the test.
In RF, the test have been done with the FT3DXL aircraft. It is very clear when the controller banks are switched, the Custom Controller isn't tuned for this aircraft and it produces angle overshoots. Other than that, no bugs or side-effects have been observed.
Parameters and logs: [Dropbox](https://www.dropbox.com/scl/fo/i9wncuajxgpdtiocgg9p1/ACuCPd5g3Vrdy4cHC1xioi4?rlkey=ay0d4q8ha7o4haa9r8xxsjclt&st=5onxxaek&dl=0)
### Size comparison
```
./Tools/scripts/size_compare_branches.py --board=Durandal --vehicle=copter,plane --no-merge-base --master=ap_master
SCB: Running (git symbolic-ref --short HEAD) in (.)
SCB-GIT: feature/custom_plane_controller_us
SCB: Building Task(Durandal, ap_master, /tmp/tmppvd76dfa/out-master-Durandal, ['copter', 'plane'], [] arm-none-eabi)
SCB: Running (git checkout ap_master) in (.)
SCB: Running (git submodule update --recursive) in (.)
SCB: Running (./waf configure --board Durandal --consistent-builds) in (.)
SCB: Running (./waf copter) in (.)
SCB: Running (./waf plane) in (.)
SCB: Running (rsync -ap build/ /tmp/tmppvd76dfa/out-master-Durandal) in (.)
SCB: Building Task(Durandal, feature/custom_plane_controller_us, /tmp/tmppvd76dfa/out-branch-Durandal, ['copter', 'plane'], [] arm-none-eabi)
SCB: Running (git checkout feature/custom_plane_controller_us) in (.)
SCB: Running (git submodule update --recursive) in (.)
SCB: Running (./waf configure --board Durandal --consistent-builds) in (.)
SCB: Running (./waf copter) in (.)
SCB: Running (./waf plane) in (.)
SCB: Running (rsync -ap build/ /tmp/tmppvd76dfa/out-branch-Durandal) in (.)
Board,copter,plane
Durandal,*,0
```
A : There’s a serious bug found by AI re radian vs deg scaling.
UTC1008
master ← amilcarlucas:generate_pdef_xml
opened 04:37PM - 21 Oct 25 UTC
P : The robot points to some serious bugs.