Attendees (unique) : 8
UTC0704
master ← pr-chibios-h7-xy
opened 03:10PM - 20 Jul 26 UTC
The 21.11.x merge dropped the rev X/Y conditionals from the H7 port. ArduPilot s… till defines STM32_ENFORCE_H7_REV_XY for every H7 board that does not ask for a 480MHz core clock, so the define became a no-op and rev X/Y parts silently picked up rev V settings.
Restores:
- errata 2.2.15 AXI SRAM read corruption workaround in stm32_clock_init
- suppression of the ODEN and CSICFGR writes, neither of which applies to rev X/Y
- rev X/Y clock ceilings (SYSCLK 400MHz, ADCCLK 36MHz, SPI and PLLVCO limits)
- rev X/Y ADC boost threshold and CFGR RES encoding
The ADC clock formula is deliberately left alone. Upstream's current rev V form is already identical to what the rev X/Y branch used before, so re-adding the conditional there would only revert an upstream change for rev V parts.
Verified on CubeOrange (rev X/Y path) and MambaH743v4 (MCU_CLOCKRATE_MHZ 480, rev V path). Both build clean. stm32_clock_init on CubeOrange now opens with the write of 1 to 0x51008108, and MambaH743v4 has no such write.
Andy : It has been removed from upstream.
Andrew : We have some old boards which use it, so we have to keep it.
Approved!
UTC0712
stable-21.11.5 ← pr-480mhz-vco
opened 03:58PM - 20 Jul 26 UTC
stm32_clock_init() sets ODEN in SYSCFG_PWRCR to enter overdrive, which is requir… ed to run above STM32_SYSCLK_MAX_NOBOOST (400 MHz on H743). hal_lld_init() then resets every APB4 peripheral, and SYSCFG is on APB4, so ODEN is cleared while the PLL keeps running at the configured rate. The core is left above its VOS1 rating with nothing to indicate it.
The exclusion looks like it was always intended: the AHB4 reset immediately above masks off RCC_APB4RSTR_SYSCFGRST, but SYSCFG is not on AHB4 so it has no effect there. That line is left alone, since on AHB4 the same bit is GPIOBRST, which STM32_GPIO_EN_MASK already covers.
Measured on an STM32H743 rev V configured for 480 MHz, reading SYSCFG_PWRCR after boot: 0x00 before this change, 0x81 after.
Setting ODEN by hand after boot also takes effect. That ruled out the alternative explanation, that the write in init_pwr() was being rejected during the voltage-scaling transition - adding a VOSRDY wait there changes nothing.
This affects any H7 configured above STM32_SYSCLK_MAX_NOBOOST; in ArduPilot that is 26 boards.
Approved, it has already gone in upstream.
UTC0713
ArduPilot-4.7 ← pr-h7-overdrive-4.7
opened 09:57AM - 21 Jul 26 UTC
4.7 backport of #107 - the fix is identical.
stm32_clock_init() sets the ODEN b… it in SYSCFG_PWRCR to put the core into overdrive, which is required above STM32_SYSCLK_MAX_NOBOOST (400 MHz on H743). hal_lld_init() then resets every APB4 peripheral, and SYSCFG is on APB4, so ODEN is cleared while the PLL keeps running at the configured rate. The core is left above its VOS1 rating with nothing to indicate it. This affects any H7 configured above STM32_SYSCLK_MAX_NOBOOST.
The bug is present on this branch identically to master: hal_lld_init has the same __rccResetAPB4(~0), and init_pwr() sets ODEN for 480 MHz boards (STM32_ENFORCE_H7_REV_XY is not defined when HAL_CUSTOM_MCU_CLOCKRATE is 480000000).
The exclusion was already intended: the AHB4 reset above masks off RCC_APB4RSTR_SYSCFGRST, but SYSCFG is not on AHB4 so it had no effect there. On AHB4 that bit is GPIOBRST, which STM32_GPIO_EN_MASK already covers, so that line is left alone.
Measured on an STM32H743 rev V at 480 MHz (on master ChibiOS, same code path): SYSCFG_PWRCR reads 0x00 after boot without this change and 0x81 with it. The fix line here is byte-identical to the verified #107 change.
Backport of the same, approved!
UTC0713
master ← andyp1per:pr-msp-power
opened 07:15PM - 12 Apr 25 UTC
### Summary
Control an MSP video transmitter (HDZero, ~~Walksnail~~, ELRS bac… kpack) from the flight controller — band/channel/frequency, power and pitmode — and report status to HD goggles.
### Classification & Testing
- [x] Checked by a human programmer
- [x] Automated test(s) verify changes (autotest `MSPVTXConfig`, `MSPDisplayPortVTXConfig`)
- [x] Tested manually, description below (SITL)
- [x] Tested on HDZero hardware (also tested on Walksnail and DJI but these appear not to support control)
Tested on an HDZero air unit + goggles on a TBS_LUCID_H7: band/channel, power and pitmode are all settable from the FC and confirmed by retuning the VRX; goggle-side channel changes coexist (push-on-change).
### Description
Adds MSP as a VTX control transport alongside CRSF/SmartAudio/Tramp, selected per-transport via the new `VTX_TYPES` parameter.
Two MSP VTX models are handled:
- **ELRS-backpack style** — the FC sends `MSP_SET_VTX_CONFIG` to the VTX.
- **HDZero/betaflight style** — the VTX is the MSP master. It polls the FC and, on finding a `"BTFL"` FC reporting `deviceIsReady=0`, uploads its own config and power table, then stops polling and expects the FC to push `MSP_VTX_CONFIG` on change. The FC reports not-ready until that handshake completes, then pushes changes (repeated for delivery, as the air unit doesn't report state back to confirm).
The FC identifier now matches the selected OSD symbol set (`BTFL`/`INAV`/`ARDU`); selecting `DISPLAYPORT_BTFL_SYMBOLS` is what enables HDZero VTX control. `MSP_OSD_CANVAS` is answered so HD goggles size their grid, and an `MSP_OPTIONS` bit holds the VTX at high power when disarmed.
Andy : We will probably enable this only in FPV H7 boards. It’s about +1.5k.
Peter : It would be great if we had a consolidated FPV H7 target.
UTC0730
master ← andyp1per:pr-scripting-osd
opened 03:31PM - 29 Jan 26 UTC
This is a rebase of https://github.com/ArduPilot/ardupilot/pull/18000
## Summ… ary
Adds Lua scripting bindings for OSD, allowing scripts to write custom content to OSD displays.
### Features
- `osd:write(col, row, text)` - Write text at position
- `osd:clear()` - Clear OSD buffer
- `osd:flush()` - Push buffer to display
- `osd:draw_screen()` - Request screen redraw
- `osd:get_backend_count()` - Get number of backends
- `osd:get_backend_type(i)` - Get backend type
### Example Script
See `libraries/AP_Scripting/examples/osd.lua` for a full example demonstrating:
- Flight mode display
- Battery status with symbol
- Altitude and ground speed
- GPS status
- Waypoint navigation info (when in AUTO mode with mission)
- Support for both MAX7456 and MSP DisplayPort symbol tables
## Testing
### Running the autotest with SFML OSD display
To see the OSD window during testing, build SITL with SFML support:
```bash
# Configure with SFML OSD enabled
./waf configure --board sitl --enable-sfml --sitl-osd
# Build copter
./waf copter
# Run the ScriptingOSD test at slow speed (SIM_SPEEDUP=5 for visibility)
Tools/autotest/autotest.py test.Copter.ScriptingOSD
```
The test will:
1. Enable scripting and OSD
2. Install the example OSD script
3. Load a waypoint mission
4. Arm and fly the mission in AUTO mode
5. Display custom OSD content including waypoint distance
The SFML window shows the OSD output in real-time.
### Manual testing
```bash
# Start SITL with OSD
Tools/autotest/sim_vehicle.py -v ArduCopter --osd
# In MAVProxy console:
param set SCR_ENABLE 1
reboot
# Copy the example script
# scripts/osd.lua -> APM/scripts/osd.lua
# Reboot to load script
reboot
```
<img width="796" height="672" alt="image" src="https://github.com/user-attachments/assets/4641ed49-a99e-4b69-afcd-906525ebe251" />
Writing on the OSD via Lua!
Andy : Tested on the SITL OSD.
A : Why are we changing the .Lua generator?
Andy : It refers to the new get string method.
A : Oh, it returns a pointer. Not a string, my bad.
Andy : It fetches the OSD backend.
A : I don’t understand why this new binding was necessary, but I trust Pete Hall.
UTC0742
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 : Flies great! But the _PID backend doesn’t support inverted flight. Let’s try to fix that.
Plus some other LLM review points.
UTC0752
master ← Georacer:bugfix/extins_temp_heater
opened 11:10AM - 15 Jul 26 UTC
### Summary
Fixes a bug where the external IMU would inject itself at the fir… st instance and it would publish temperatures for the wrong heater target. Now the correct INS instance is used.
### 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)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
When using an external IMU, its backend gets loaded as the first INS instance due to https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_InertialSensor/AP_InertialSensor.cpp#L1210-L1210.
Then, when the INSs send their temperatures to be used as heater feedback, the value of [AP_HEATER_IMU_INSTANCE](https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_InertialSensor/AP_InertialSensor_Backend.cpp#L786-L786) would be wrong.
This PR will check if an external INS has been registered, and will increase an offset by 1, so that AP_HEATER_IMU_INSTANCE is now correctly aligned with the desired onboard IMU.
### Assumptions
I assume that `_first_onboard_imu_instance` will be initialized to 0.
### Alternatives
I thought about adding a parameter allowing the user to specify the IMU to be used as a temperature source for the heater, but that sounds like a footgun to me. I prefer trusting the board manufacturer to set `AP_HEATER_IMU_INSTANCE` correctly.
Approved!
A : I thinkj you could test with any board by declaring an EAHRS, not plugging it in and observing the heater.
UTC0800
master ← andyp1per:pr-ground-effect
opened 02:25PM - 17 Mar 26 UTC
### Summary
Adds parameters to delay release of baro ground-effect compensation… and to gate touchdown ground effect on altitude, plus a SITL parameter that injects a simulated baro error so the autotest has something to compensate against. The altitude threshold keeps its prior 0.5m default; the new minimum-hold timeout defaults to 2s, so the takeoff compensation window is now held for at least 2s (bounded by the existing 5s hard cap) rather than releasing purely on altitude. Set `GNDEFF_TMO` to 0 for the pre-PR release behaviour.
### Classification & Testing
- [x] Checked by a human programmer
- [x] Automated test(s) verify changes (e.g. unit test, autotest)
- [x] Tested manually, description below (e.g. SITL)
### Description
On airframes with strong baro ground effect, the EKF altitude estimate can cross the hard-coded 0.5m exit threshold within a few hundred ms of takeoff and release compensation before the vehicle is clear of the disturbance.
The detection logic moves into a new vehicle-agnostic `AP_GroundEffect` library. New parameters:
- `GNDEFF_ALT` (default 0.5m): altitude above which takeoff ground-effect compensation is cleared. Touchdown ground-effect compensation is only signalled to the EKF when the vehicle is below this altitude. Zero keeps compensation enabled but drops the touchdown altitude gate (legacy "any gentle descent counts" behaviour); negative disables the feature entirely.
- `GNDEFF_TMO` (default 2s): minimum hold time after takeoff before the altitude check is allowed to release. The 5s hard timeout still applies unconditionally. Set to 0 for the pre-PR behaviour where the altitude check alone releases the window.
- `SIM_BARO_GEFF_M` (SITL, default 0): amplitude in metres of a simulated rotor-downwash baro error. Decays linearly to zero at 2m AGL and is gated on motor throttle, so the baro reads truth with the motors idle.
An earlier revision also re-set `takeoff_expected` on descent below the threshold. That overloaded a flag whose contract is "we are about to leave the ground"; the EKF's landing-side response lives on `touchdown_expected`, which is now what `GNDEFF_ALT` gates. Tightening the EKF's response to `touchdown_expected` is left as a follow-up.
The luminousbee5 board previously pinned `GND_EFFECT_COMP,0`; that override is dropped, so the board now runs with ground-effect compensation enabled by default.
Autotests `TakeoffGroundEffectAlt` and `TouchdownGroundEffectAlt` cover the altitude and timeout gating and assert comparative durations so they survive SITL jitter.
A : It’s not a good idea to rely on the EKF HAGL. Lidar isn’t reliable enough at high altitudes. The terrain database is the more reliable source.
We’ll let Randy comment on the background.
UTC0807
master ← andyp1per:pr-chibios-h7-xy
opened 03:13PM - 20 Jul 26 UTC
### Summary
Submodule bump to restore STM32_ENFORCE_H7_REV_XY, which the ChibiO… S 21.11.x upgrade silently turned into a no-op on every H7 board.
### Classification & Testing (check all that apply and add your own)
- [x] Checked by a human programmer
- [x] Tested manually, description below
- [ ] Tested on hardware
Built CubeOrange (rev X/Y path) and MambaH743v4 (MCU_CLOCKRATE_MHZ 480, so rev V path); both clean. Confirmed from the disassembly that stm32_clock_init on CubeOrange now opens with the errata write of 1 to 0x51008108, and that MambaH743v4 correctly has no such write. No SITL coverage is possible here - this is STM32 clock and ADC register init.
Hardware testing on an actual rev X/Y H743 is still wanted before merge.
### Description
hwdef/common/stm32h7_mcuconf.h defines STM32_ENFORCE_H7_REV_XY for every H7 board that does not set MCU_CLOCKRATE_MHZ 480. Upstream ChibiOS deleted the conditionals that consumed it when moving to 21.11.x, so since the upgrade the define has done nothing and all rev X/Y parts have been running rev V settings.
The practical effect was that the errata 2.2.15 workaround for AXI SRAM read corruption stopped being applied, and that ODEN, CSICFGR and the rev V ADC boost thresholds were being programmed on silicon they do not apply to.
Depends on ArduPilot/ChibiOS#106. The submodule currently points at that PR's branch commit, so this needs repointing at the merged ChibiOS master commit before it can go in.
Andy : I don’t have a board to test this anymore.
A : I do, I can test it.
It boots! Master booted as well, but it may have had errors, especially in the ADC.
Randy : I wonder why ChibiOS are not willing to keep support for these very old boards.
UTC0816
master ← tridge:pr-mavlink32bitsysid
opened 06:45AM - 15 Jul 26 UTC
### Summary
Implements 32 bit system IDs
See also:
- https://github.com/… ArduPilot/pymavlink/pull/1229
- https://github.com/ArduPilot/MAVProxy/pull/1704
- https://github.com/ArduPilot/mavlink/pull/515
- https://github.com/mavlink/rfcs/pull/20
### 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)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
This implements https://github.com/mavlink/rfcs/pull/20 but with 32 bit system IDs to allow for IPv4 addresses to be used for system IDs. This should make large drone light shows easier.
I also plan on making full 32 bit integers work with mavlink parameters to make this more practical for real IPv4 addresses. That will be a separate effort
Some open questions:
- should we put target_system&0xff in the uint8_t target_system field in messages or should we put in 0? This PR uses 0
- the lua script changes are tricky as the mavlink receiver gets the raw C structure which is now 3 bytes larger. Should we add compatibility code so the new lua script handles both forms? UPDATE: I've added compat code
A : This was flight tested successfully, so it’s ready for wider review.
Relies on a PR for 32-bit parameters.
UTC0818
master ← LupusTheCanine:RPMBuffer
opened 07:32PM - 13 Jul 26 UTC
### Summary
Make pin-based RPM sensors use ring buffer to hold samples, this … allows updating at 400Hz or every sample (at less than 400 pulses per second) while averaging over 14 samples or 1s whichever is shorter.
It is (intended to be) stacked on #33363
### 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)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
Adds ring buffer to pin-based RPM sensors.
A : ERPM-based interrupts are indeed sensible to check at a faster rate.
Is the new filter and the faster rate linked with each other?
Lupus the Canine : No.
A : What’s the advantage of the Hampel filter?
L : Discord
A Apparently it’s better for oulier rejection. Should we be using it in more places?
It employs an insertion sort, which might be intensive CPU-wise.
But we probably do inertion sort in the classic Mode filter too.
Let’s measure the CPU cost. You can loop back a PWM output at 400Hz into the RPM pin.
Then comment the class with the cost. Mention the hardware under test.
UTC0840
master ← peterbarker:pr-claude2/sitl-buzzer-singleton
opened 02:09AM - 13 Jul 26 UTC
### Summary
Stop passing pointers into the aircraft when it already knows eve… rything around them.
### 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
Tidies up the setup of these devices. It was needlessly complex.
We're throwing a lot more into the base aircraft model than was intended to be there. But this is the way things seem to be moving...
Also adds defines around these things (compiling for SoH can be tight!)
A : Merged!
UTC0846
master ← peterbarker:pr-claude2/sitl-atomic-watchdog-save
opened 01:50AM - 14 Jul 26 UTC
### Summary
Fixes flake due to race condition writing persistent.dat file in … SITL
### 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
watchdog_save() rewrote persistent.dat in place with O_TRUNC+write every 100ms. The simulated watchdog reset (SIGALRM) execv()s from the signal handler, so a reset arriving between the truncate and the write left a short file behind; the re-exec'd process then failed to load its persistent data and booted with home/attitude zeroed, seen in CI as WatchdogHome failing with "Failed to poll home position" and "Restored watchdog attitude 0 0 0".
Write to persistent.dat.tmp and rename() it into place so a complete persistent.dat always exists.
A : Merged!
UTC0848
master ← peterbarker:pr-claude/ms5611-prom-uninit
opened 07:30AM - 14 Jul 26 UTC
### Summary
Stop returning success while not initialising a buffer in simulat… ed baro driver
### 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
ArduSub sets BARO_EXT_BUS 1, so AP_Baro::init probes for an MS5611 at address 0x77 on bus 1 - where the SITL I2C bus places the simulated TSYS01. The MS5611 driver reads eight PROM words (commands 0xA0..0xAE) but the simulator only understands 0xA0..0xAA; commands 0xAC and 0xAE fell through the switch without filling the response buffer and the transfer was reported as successful, so the driver ran its PROM CRC check over uninitialised stack bytes. Valgrind reports this and fails any --valgrind autotest run; worse, roughly one boot in sixteen the garbage passes the CRC-4 check and a phantom MS5611 barometer is registered using TSYS01 PROM data as calibration.
Fail the transfer instead, as a real device would NAK. The driver then sees zeroes for words 6 and 7 and the CRC check fails deterministically, so the MS5611 probe is always cleanly rejected.
A : Merged!
UTC0849
master ← peterbarker:pr-claude2/fgets-full-buflen
opened 08:58AM - 21 Jul 26 UTC
### Summary
Follow-on from https://github.com/ArduPilot/ardupilot/pull/33744 … - fixes potential (and in one case real) buffer overflow.
### 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)
- [ ] Tested manually, description below (e.g. SITL)
- [ ] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
buflen now includes the space required for the null terminator, so up to buflen-1 characters are returned. Previously fgets could write buf[buflen], one byte beyond the caller-nominated length. All in-tree callers passed sizeof(buf)-1 to compensate, but posix_compat's apfs_fgets forwards its C-style size argument directly, so a caller supplying a size-byte buffer could have that buffer overrun by one byte on an over-long line.
Update callers to pass the full buffer size; usable capacity is unchanged.
A : The “general” fgets reads up to -1 byte w.r.t. the buffer size.
And yes, this PR brings our fgets inline with that.
Approved!
UTC0853
master ← peterbarker:pr-claude/dynamic-fft-notches
opened 02:04AM - 09 Jul 26 UTC
### Summary
Fix flakey DynamicRpmNotches test
### 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 octacopter single-notch FFT checks searched from 50Hz. The high INS_GYRO_FILTER this test uses (so the motor noise is observable) lets the rate loop sustain a closed-loop oscillation near half the motor frequency (~90Hz). That subharmonic is real vehicle motion, not motor noise the harmonic notch is meant to remove, and it intermittently pushed the reverse check over its threshold (~10% of runs).
Search from 150Hz instead, so the check only covers the ~190-200Hz motor fundamental the notch actually targets. Confirmed with Tools/autotest/autotest.py --repeat 25 (25/25 pass).
autotest: hover longer for octacopter dynamic-notch FFT checks
The single-notch octacopter checks in DynamicRpmNotches measure a 15s hover, which gives the post-filter batch-sampler FFT only ~4 Welch segments. That is too few: the ~95Hz octa motor fundamental's estimated level occasionally spikes several dB, tripping the -10dB gate even with a settled hover. Hover for 30s on those two checks to roughly double the averaging and stop the false failures.
I'm not an expert on this stuff. claude pretends to be:
```
1. Where ~200 Hz comes from. It's the per-motor rotation frequency at hover: rpm/60. For this octa at hover the motors turn near ~12,000 rpm → ~200 Hz (the measured average ESC frequency
was ~193–198 Hz). SITL injects a sinusoid at that frequency straight onto the simulated gyro (lines 253/272) to emulate airframe vibration coupling into the IMU — this is the noise the
harmonic notch exists to remove.
2. Why it reaches the PID at all — INS_GYRO_FILTER. DynamicRpmNotches deliberately sets a high gyro low-pass cutoff (300 Hz) so the motor tone is observable for the notch test. A ~200 Hz
component sits inside a 300 Hz passband, so it arrives at the rate PID only mildly attenuated. (Drop the cutoff to 20 Hz and ~200 Hz is crushed before the PID — which is exactly why the
subharmonic vanished ~24 dB in the left-hand graph.)
3. Why the controller re-emits it onto the motors — the D term. The rate controller's derivative path is a differentiator: its gain rises with frequency. So high-frequency gyro ripple
isn't attenuated by the controller, it's amplified and pushed straight onto the motor command. The P term passes it ~1:1; D makes it worse. That's why the OUTPUT (motor-torque demand)
spectrum carries a peak at the motor frequency. The controller isn't "trying" to command ~200 Hz — its D term just faithfully (over-)reproduces whatever the gyro filter let through. This
is the entire reason gyro LPF + harmonic notches exist: to keep vibration out of the D term.
…and why that births the ~99 Hz feature (the thing the patch actually skips)
Because motor command → RPM → injected vibration → gyro is a closed loop (step-by-step above), it's not just a passive echo. Going around that loop you accumulate phase lag: gyro-filter
group delay + one control-loop compute delay + the motor time constant. At the frequency where the total loop phase hits −360° with loop gain ≥ 1, the loop self-sustains an oscillation — a
limit cycle. That lands near ~99 Hz here (~half the ~200 Hz motor tone).
One honest caveat specific to the octa: on this frame the ratio came out very close to exactly 0.5 (99/198), closer than the quad's 0.43. I wouldn't over-read that as true period-doubling
— it's still a loop-phase limit cycle that happens to sit near half the fundamental, and at the test's default vibration amplitude it's a marginal, intermittent (~10%-of-runs) effect (I
had to raise SIM_VIB_MOT_MULT to 8 to make it show reliably in one capture).
```
<img width="1650" height="594" alt="image" src="https://github.com/user-attachments/assets/a0517eac-6fef-49a9-ae8e-afdcc1e8acd7" />
P : Apparently the control bandwidth falls within the range where FFT looks for a noise peak.
Andy : Okay, this test is meant to just ensure Octa flies somewhat correctly.
Merged!
UTC0856
master ← dopelion:master
opened 01:03AM - 18 May 26 UTC
### Summary
Add a board support for CyberX-v10 high‑performance custom fl… ight controller with STM32H743IIK6 main MCU, STM32F103 IOMCU, triple synchronized IMUs, dual barometers and built‑in magnetometer.
### 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)
- [x] Tested on hardware
- [x] Logs attached
- [ ] Logs available on request
## Hardware Features
- Separate flight control core architecture
- Main MCU: STM32H743IIK6, 400MHz, 2MB Flash, 1MB RAM
- IO MCU: STM32F103, 72MHz, 128KB Flash, 20KB SRAM
- IMU System: Triple synchronized IMUs with BalancedGyro technology, low noise & high shock resistance
- IMU1: BMI088 (with vibration isolation + constant‑temperature heating, 1W heating power)
- IMU2: ICM42688‑P (with vibration isolation + constant‑temperature heating, 1W heating power)
- IMU3: ICM20689 (without vibration isolation)
- Barometer: Dual redundant barometers
- Baro1: BMP581
- Baro2: ICP20100
- Magnetometer: On‑board IST8310 magnetometer
### Description
## Testing Result
- Successfully compiled Copter / Plane / Rover firmware
- Ground station verification: All 3 IMUs, dual barometers and magnetometer detected normally
- RC input, PWM output, power monitoring and heating function work correctly
- Hardware bench test completed, real‑flight validated with stable attitude performance
- Flight log attached for further [validation]([url](url))
[2026-05-16 15-18-07.zip](https://github.com/user-attachments/files/27939015/2026-05-16.15-18-07.zip)
[
<img width="3280" height="2460" alt="CyberX-v10-back" src="https://github.com/user-attachments/assets/9018b960-a4e0-4a81-a336-46327f1aef00" />
<img width="3280" height="2460" alt="CyberX-v10-front" src="https://github.com/user-attachments/assets/3a5f8c51-2417-42d5-bea2-5b44cbcd98f9" />
](url)
MergeOnCIPass!
UTC0857
master ← Juergen-Fahlbusch:Juergen-Fahlbusch-patch-1
opened 11:40AM - 03 Jul 26 UTC
### Summary
AP_FlashStorage: set current_sector during init
Related discus… sion https://discuss.ardupilot.org/t/potential-incomplete-initialization-on-ap-flashstorage/144440
Perhaps resolves: https://github.com/ArduPilot/ardupilot/issues/33538
### 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)
- [x] Tested on hardware
- [ ] Logs attached
- [ ] Logs available on request
### Description
While troubleshooting aninternal error 0x200000 I noticed that parameters could no longer be saved permanently. Notably, the parameters STAT_BOOTCNT and STAT_RUNTIME—which usually increment automatically—kept reverting to their previous values after a restart. Further analysis revealed that:
Sector 0 was marked with status [SECTOR_STATE_AVAILABLE] Sector 1 was marked with status [SECTOR_STATE_IN_USE] Consequently, the current parameters were being loaded from Sector 1. However, when writing new parameters, the system attempted to write to Sector 0. In my opinion, the cause of this is that the variable current_sector is not set to the active sector during initialization.
I was able to resolve the issue—at least for testing purposes—by inserting the initialization of the current_sector variable after the following code block:
// work out the first sector to read from using sector states
enum SectorState states[2] {header[0].get_state(), header[1].get_state()};
uint8_t first_sector;
if (states[0] == states[1]) {
if (states[0] != SECTOR_STATE_AVAILABLE) {
return erase_all();
}
first_sector = 0;
} else if (states[0] == SECTOR_STATE_FULL) {
first_sector = 0;
} else if (states[1] == SECTOR_STATE_FULL) {
first_sector = 1;
} else if (states[0] == SECTOR_STATE_IN_USE) {
first_sector = 0;
} else if (states[1] == SECTOR_STATE_IN_USE) {
first_sector = 1;
} else {
// doesn't matter which is first
first_sector = 0;
}
//added initialization current_sector
current_sector = first_sector;
Merged!