74072 Commits
Author SHA1 Message Date
yyzh 9de61c2614 AP_Bootloader: add board type for SVehicle-E2-mini 2026-09-22 10:28:26 +10:00
Pierre KancirandClaude Opus 5 22287496b9 .github: test_size_comment: post the size table on pull requests
"test size" runs pull request code, so its token is read-only and it
cannot comment.  This runs on workflow_run, from the default branch and
without a checkout, validates the data it is handed and builds the table
itself, so nothing the pull request wrote is posted under the bot's name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 07:55:09 +10:00
Pierre KancirandClaude Opus 5 c7aef45de0 .github: test_size: pin the base commit and upload the size data
Resolve the base branch once per run, so every board compares against the
same commit, and mark the legs that do not succeed.  size-summary.json
goes to test_size_comment.yml; the markdown stays on the run's page.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 07:55:09 +10:00
Pierre KancirandClaude Opus 5 08d11f1ca8 Tools: build_tests: name the commits and emit the table as json
The table says which commit it was built from and which it was compared
against, and --json-output writes the same as data for the workflow that
comments it on a pull request.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 07:55:09 +10:00
Peter Barker 98b155533c autotest: let the context remove SDCardWPTest's script
SDCardWPTest installed mission_spiral.lua with the non-context
install_example_script() and removed it with a bare
remove_installed_script() thirty lines later, with no try/finally
between them.  Every wait_text() and set_parameter() in that stretch can
raise, and any of them leaves the script installed: the removal is
simply skipped.

That matters more here than for a leaked trick file, because
mission_spiral.lua ends in .lua - lua_scripts.cpp loads every .lua in
scripts/ - so the leftover is picked up and run by the next test to
start a vehicle with scripting enabled.

The test already pushes a context, and the harness pops any the test
leaves behind when it fails, so install_example_script_context() cleans
up on both paths.  Every other install site in Tools/autotest already
uses the _context form.
2026-09-22 07:21:24 +10:00
Peter Barker 9256cd77c5 .github: raise ccache max_size for the macOS builds
pre-commit / ci (push) Canceled after 0s
test Renode / cubeorangeplus-quadplane (push) Canceled after 0s
test scripts / build (astyle-cleanliness) (push) Canceled after 0s
test scripts / build (check_autotest_options) (push) Canceled after 0s
test scripts / build (logger_metadata) (push) Canceled after 0s
test scripts / build (param-file-validation) (push) Canceled after 0s
test scripts / build (param_parse) (push) Canceled after 0s
test scripts / build (python-cleanliness) (push) Canceled after 0s
test scripts / build (shellcheck) (push) Canceled after 0s
test scripts / build (validate_board_list) (push) Canceled after 0s
workflows lint / lint (push) Canceled after 0s
The macOS jobs' working set is 480-560MB, so at ccache.env's 400M default
both evicted objects mid-build - 817 cleanups on sitl, 123 on CubeOrange -
and re-compiled them on the next run. Restoring a cache built from the same
source, they hit 42% (CubeOrange) and 19% (sitl); with the cache large
enough to hold the working set both hit 99.8%.

Add a max-size input to setup-ccache so this is per-job rather than global:
raising it for all jobs would waste the repository's shared 10GB cache
quota on the ~60 jobs that use well under 400M. The two macOS entries grow
by 208MB in total.
2026-09-21 19:25:22 +10:00
Peter Barker 69b3dc83c5 .github: only build copter for the macOS debug build
The macOS workflow built every vehicle twice, once normally and once
with --debug. The second pass doubled build time and, since debug and
non-debug objects don't share ccache entries, overflowed the 400M ccache
limit, so the cache thrashed even when warm.

A single vehicle is enough to check the debug build works on macOS.
Plane, Rover, Sub, Blimp, AntennaTracker and heli no longer get a
--debug (-O0) compile on macOS; each still gets one in its Linux SITL
test workflow.
2026-09-21 19:25:22 +10:00
Andrii Anoshyn e323725412 AP_Terrain: remove legacy terrain generator 2026-09-21 19:22:50 +10:00
Andy Piper 663fc09bb2 hwdef: all TBS_LUCID_H7 variants can contain DPS368 or BMP390 2026-09-21 10:25:35 +10:00
Thomas Watson d25c1668e3 Tools: fix size_compare_branches.py jobs argument
waf does not persist `-j` in the configuration, it's only used for the
command it's specified on. So specifying `-j` to this script never did
anything to limit the number of build processes because the job limit
was only given to configure commands.

Now the script passes the appropriate number of jobs to build as well
as configure commands, so the limit is actually applied.

It's unclear if passing the number of jobs to the configure command
accomplishes a lot, but it doesn't hurt so it's kept.
2026-09-21 10:23:57 +10:00
Peter Barker 0d38ef16d1 Tools: environment_install: add if clauses to avoid churn on add/remove OS
previously adding or removing support for an OS meant changing lines unrelated to that OS.

Add a bit of cruft to the file so that adds/removes are just clean line additions or removal
2026-09-20 14:27:13 -07:00
Clyde McQueen 368dc0c428 autotest: remove rangefinder noise in Sub autotests to eliminate a source of flakiness
pre-commit / ci (push) Canceled after 0s
test scripts / build (astyle-cleanliness) (push) Canceled after 0s
test scripts / build (check_autotest_options) (push) Canceled after 0s
test scripts / build (logger_metadata) (push) Canceled after 0s
test scripts / build (param-file-validation) (push) Canceled after 0s
test scripts / build (param_parse) (push) Canceled after 0s
test scripts / build (python-cleanliness) (push) Canceled after 0s
test scripts / build (shellcheck) (push) Canceled after 0s
test scripts / build (validate_board_list) (push) Canceled after 0s
2026-09-19 20:36:04 +10:00
Amrit kumar Mahto 9165d22419 SITL: use strncpy in SIM_XPlane 2026-09-18 11:23:30 +10:00
Amrit kumar Mahto f1412b0cda AP_HAL_ESP32: use strncpy_noterm in WiFi drivers 2026-09-18 11:23:30 +10:00
Peter Barker 665c0deeec SRV_Channel: remove zero_rc_outputs
superseded by prepare_for_reboot(), which its only caller now uses
2026-09-18 00:10:02 +10:00
Peter Barker 26809186b8 AP_Vehicle: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker 94f7e038b0 SRV_Channel: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker 94800d5ae6 AP_HAL_SITL: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker c05eb925b1 AP_HAL_ChibiOS: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker 06c6317934 AP_HAL: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker 985d2f6f6f AP_HAL_Linux: bounds-check channel number in RCOutput write methods
RCOutput_PRU, RCOutput_AioPRU_PB2 and RCOutput_AeroIO wrote into their
channel arrays without checking the channel number; every other Linux
RCOutput backend already does.  On PRU the overrun is particularly
unpleasant as pending[MAX_PWMS] aliases the corked flag, so a write to
channel 12 uncorks the backend and makes the subsequent push() a no-op.

SRV_Channels::output_ch_all() already sweeps 16 channels by default,
so these overruns are reachable today on pxf, erleboard and pocket2.
2026-09-18 00:10:02 +10:00
Peter Barker 8a6d5b2ef7 Sub: prepare for reboot at the HAL rc output level
ensures that the 0s get to the hardware

significantly reduces the race conditions which might allow a thread to write after values are zeroed
2026-09-18 00:10:02 +10:00
Peter Barker 5efdf54920 Revert "hwdef: keep PA15 pulled up in the YJUAV_A6SE_H743 bootloader"
This reverts commit 2f87db990f.

PR #34359 was merged by mistake.  On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default.  The ESC started to enter
throttle calibration.  Back the change out until the hold can be
chosen per output.
2026-09-18 00:04:45 +10:00
Peter Barker 90dcb1680f Revert "bootloaders: rebuild YJUAV_A6SE_H743 to keep PA15 pulled up"
This reverts commit 157d471fe4.

PR #34359 was merged by mistake.  On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default.  The ESC started to enter
throttle calibration.  Back the change out until the hold can be
chosen per output.
2026-09-18 00:04:45 +10:00
Peter Barker e4f836b315 Revert "AP_HAL_ChibiOS: add HOLD_HIGH PWM pins handed to their timer at first output"
This reverts commit 239f5c1f97.

PR #34359 was merged by mistake.  On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default.  The ESC started to enter
throttle calibration.  Back the change out until the hold can be
chosen per output.
2026-09-18 00:04:45 +10:00
Peter Barker 0fae5cc03b Revert "hwdef: hold YJUAV_A6SE_H743 PWM1 high until its first frame"
This reverts commit 67fd60ce26.

PR #34359 was merged by mistake.  On the bench, with an ESC on
YJUAV_A6SE_H743 output 1, the hold presents a continuous high (full
throttle to a PWM ESC) for about 10.5s after every reset, and for as
long as safety is engaged when output 1 is a motor outside
BRD_SAFETY_MASK, which is Copter's default.  The ESC started to enter
throttle calibration.  Back the change out until the hold can be
chosen per output.
2026-09-18 00:04:45 +10:00
Peter Barker 67fd60ce26 hwdef: hold YJUAV_A6SE_H743 PWM1 high until its first frame
PWM1 is on PA15, the JTDI pin, whose reset and power-on pull-up gave the
M1 servo a short pulse on every boot. Declare it HOLD_HIGH so the
application keeps it a pulled-up input until RCOutput's first real
frame, matching the bootloader, which already keeps the pull-up.
2026-09-17 22:56:37 +10:00
Peter Barker 239f5c1f97 AP_HAL_ChibiOS: add HOLD_HIGH PWM pins handed to their timer at first output
The STM32 JTAG pins JTDI (PA15) and NJTRST (PB4) come out of every
reset, and out of power-on, with an internal pull-up enabled, and 84
hwdef directories in the tree route a PWM output through one of them:
61 through PA15, 38 through PB4, 15 through both.  A servo on such an
output sees the line pulled high from then until firmware reconfigures
the pin.  On the H743 that measured 692us to the bootloader's board init
on a warm reset, and 496us and 520us on two cold power-ons.  Each is a
pulse inside the range servos accept, so the servo drives to an endpoint
and holds it through the rest of the boot.  Nothing can shorten that
window, since no code runs during it.

Give hwdef a HOLD_HIGH keyword for PWM pins.  The generator emits such a
pin as a pulled-up input with its timer alternate function preset, and a
HAL_PWM_HOLD_HIGH_MASK of the channels concerned.  It rejects the keyword
on any pin RCOutput will never hand back to a timer: anything other than
a PWM(n) timer output in the main configuration, so also an RC input, the
alarm and an ALT(n) pin.  One predicate decides both that and which pins
get a mask bit, so the two cannot disagree.  The check is made when the
pin is parsed, which covers bootloader builds too.  STM32F1 is rejected
outright, since its pin setup does not honour the keyword at all.

RCOutput keeps each channel an input until the first non-zero value is
pushed to it, in the PWM and DShot output paths, and only then switches
the pin to the timer.  With the bootloader also keeping the pull-up, the
line is high continuously from the reset until the first real frame,
which for a channel outside BRD_SAFETY_MASK means until safety is
disarmed, so the servo sees a high far longer than any valid pulse
rather than a plausible short one followed by seconds of silence.  On
the bench the test servo did not move at all across ten reboots.

The mode switch is an unlocked read-modify-write of the port registers,
and other threads change the modes of other pins on the same port, so
a single write can be lost.  The channel is therefore not marked handed
over until a later output finds the pin already in alternate mode; until
then each output writes the mode again, so a lost write is repaired one
output later rather than leaving the pin an input until reboot.

Several other owners of a pad have to take it explicitly, because none
of them goes through the normal output path:

 - the alarm driver configures a timer and never the pad, and disables
   the group's channels first, so the hold on the alarm's own channel is
   released before that.  Only that channel: no real frame will ever
   arrive for the rest of the group, so a HOLD_HIGH pin among them is
   correctly left held;
 - soft serial saves and restores the pad's mode, so BLHeli passthrough
   hands the pin over when it selects it, or it would save "input" and
   transmit nothing;
 - neopixel and ProfiLED output is chosen at runtime by SERVOx_FUNCTION
   on an ordinary PWM(n) pin and is sent without push_local(), so the
   serial LED path releases its group's pads before driving them;
 - DShot commands such as beeps are sent before arming, when nothing has
   released the pad yet, so the command path releases every channel it
   transmits on;
 - bidirectional DShot, when enabled at runtime, takes the pads of a
   whole group during init, so it clears the pending bit there.  A pin
   merely declared BIDIR keeps its hold; one whose group has bidirectional
   DShot enabled gets no protection.  The hwdef allows HOLD_HIGH and BIDIR
   together deliberately.

Verified under Renode on YJUAV_A6SE_H743 with ArduPlane: the
application's board init leaves PA15 an input, it stays one through
24.8s of init, and the mode write that puts it on TIM2 lands at the same
microsecond as the first non-zero CCR1 write.  With the first mode write
dropped on purpose, the next output found PA15 still an input and wrote
it; unmodified, the second output sees the mode has held and later
outputs no longer read the port.  MatekF405-TE and the IOMCU
firmware still build, and a no-mask board's firmware is byte-identical.
2026-09-17 22:56:37 +10:00
Peter Barker 157d471fe4 bootloaders: rebuild YJUAV_A6SE_H743 to keep PA15 pulled up
Built with Tools/scripts/build_bootloaders.py from the hwdef change that
holds the PWM1/JTDI pin high through the bootloader, so a servo on M1 no
longer receives a 500 to 700us pulse on every reset and power-on.
2026-09-17 22:56:37 +10:00
Peter Barker 2f87db990f hwdef: keep PA15 pulled up in the YJUAV_A6SE_H743 bootloader
PA15 drives PWM1 on this board and is also JTDI, which the STM32H743
brings out of every reset, and out of power-on, with its internal
pull-up enabled. The M1 servo line is therefore held high from then
until the bootloader's board init reconfigured the pin as a floating
input. On logic-analyser captures of the real board that is 692us on a
warm reset, and 496us and 520us on two cold power-ons, one over USB and
one at 12V. Each of those is a pulse inside the range most servos
accept, and it sent the servo to an extreme.

Configure PA15 as an input with pull-up in the bootloader instead, so
the line stays high continuously until the application switches the pin
to its timer, whose idle level is low. The servo then sees one high
lasting the whole bootloader, far outside any valid pulse width, rather
than a plausible command. Verified under Renode with the bootloader
held: PA15 reads input with pull-up while the bootloader owns the pins.
2026-09-17 22:56:37 +10:00
Mohamed Alaa Dewedar af8525911b AP_Bootloader: reserve board IDs 3136-3145 for MADpilot 2026-09-17 09:47:56 +10:00
Peter Barker b2b1b3d279 Tools: decode_devid.py: parse device types from the C++ headers
pre-commit / ci (push) Canceled after 0s
test Renode / cubeorangeplus-quadplane (push) Canceled after 0s
test scripts / build (astyle-cleanliness) (push) Canceled after 0s
test scripts / build (check_autotest_options) (push) Canceled after 0s
test scripts / build (logger_metadata) (push) Canceled after 0s
test scripts / build (param-file-validation) (push) Canceled after 0s
test scripts / build (param_parse) (push) Canceled after 0s
test scripts / build (python-cleanliness) (push) Canceled after 0s
test scripts / build (shellcheck) (push) Canceled after 0s
test scripts / build (validate_board_list) (push) Canceled after 0s
Rather than maintaining copies of the bus and device type tables,
decode_devid.py now parses the enums in AP_HAL/Device.h, AP_SerialManager.h
and the compass, IMU, baro and airspeed backend headers using
logger_metadata/enum_parse.py.  A small rename map keeps established
display names (DRONECAN, AK0991x), and the retired LIS2MDL ID, which is
in no enum, is listed explicitly.  Comments on enum entries are shown as
warnings when decoding.

--dump-json and --dump-json5 write the tables, with a format_version
and a content-hash data_version, for tools without a source tree;
--json reads such a file back.  A copy of the script outside an
ArduPilot tree (as synced by MethodicConfigurator) reads devid.json from
its own directory.  The files are published alongside LogMessages.* by
build_log_message_documentation.sh, and CI dumps them in the
logger_metadata step so that header changes which break parsing are
caught.

The tables had drifted from the headers: ACC_LSM9DS1,
INS_ZEROONE_FPGA_SCH16T and INS_ICM56686 were missing, MMC5883 is now
MMC5983, AK8963/BMM150 had trailing spaces, and several names now
follow the headers.
2026-09-16 17:18:56 +10:00
Peter Barker 8392566e2b AP_Compass: document when the mistaken RM3100 device type was used
DEVTYPE_RM3100_2 (0x12) was introduced by dd4cf6ccdd and reverted by
a0cf4e158a; no release firmware used it.  Tools/scripts/decode_devid.py
shows this comment as a warning when decoding such an ID.
2026-09-16 17:18:56 +10:00
Peter Barker a4e55aa914 AC_AttitudeControl: place PosControl parameter conversion tables in rodata 2026-09-16 17:07:48 +10:00
Peter Barker a526f304a5 AP_Camera: place parameter conversion table in rodata 2026-09-16 17:07:48 +10:00
Peter Barker 19629454ea AP_GPS: place parameter conversion table in rodata 2026-09-16 17:07:48 +10:00
Peter Barker 0bc73575cd AP_Param: allow conversion tables to omit a shared old key
Parameter conversion tables whose entries all share an old key found at
runtime (e.g. via find_top_level_key_by_pointer()) cannot be constant
if the key is stored in each entry, so a static table is initialised at
runtime and kept in RAM.  Adding a ConversionInfoNoKey table type plus
convert_old_parameters() and convert_old_parameters_scaled() overloads
which take the key separately allows these tables to be placed in
.rodata.
2026-09-16 17:07:48 +10:00
Peter Barker 73a936a702 waf: make dangling-pointer warnings errors on gcc 16.1 and later 2026-09-16 17:07:48 +10:00
Pierre KancirandClaude Opus 5 2ecf55b847 Tools: completion: complete autotest.py's newer options
--check-parameter-leaks, --no-check-parameter-leaks and
--unix-domain-socket with its --uds alias are accepted by autotest.py but
were not offered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 e04d2022e4 Tools: Completion bash: complete waf away from the checkout root
waf runs from the root of the checkout, but the completion ran ./waf in
whatever directory it was typed in, so BUILD.md's suggested
alias waf="<ardupilot>/modules/waf/waf-light" proposed nothing at all
from a subdirectory.  Ask git for the root, run waf there, and key the
cache on it rather than on the current directory.

Recognise the help by its "Main commands" heading rather than by being
non-empty: a clone whose waf submodule is still missing prints a notice
and exits 0, which passed the old check and cached the handful of
hardcoded words for that directory.

Read the cache variables with ${var-} so a shell with set -u does not
abort on the first tab press.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 b451aa24ad Tools: completion: complete the SITL binaries' newer options
--net-device, --sim-periph-lockstep and --use_sim_time are accepted by
the binaries but were not offered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 29e9bd47d7 Tools: completion: complete sim_vehicle.py --unix-domain-socket
Added to sim_vehicle.py without the completion scripts following.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 9638d0419c Tools: completion: survive tools that cannot run here
autotest.py --help needs pymavlink installed; without it the checker
stopped on a traceback and never reached the checks after it, which is
how the SITL binary ones stayed unnoticed.  A tool that cannot run is a
fact about the machine, not about the completion scripts, so warn and
skip it, as the missing SITL binary already did.

A long option may contain an underscore -- the SITL binaries have
--use_sim_time -- and stopping at it reported a missing --use that no
completion script could ever satisfy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 f8fbaf1c4b Tools: completion: stop checking bash/_waf against waf's help
bash/_waf declares no options of its own any more -- it scrapes ./waf
--help when it completes -- so there is nothing left to fall out of sync.
What the checker still found there was its own case patterns: it read
--enable-*|--disable-*|--embed-* as three options waf does not accept and
reported them as stale.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Pierre KancirandClaude Opus 5 c16c715ce4 Tools: Completion bash: remove hardcoded help, filter main output, add cache
The options are scraped from ./waf --help instead of being written out
here, the ~900 generated --enable-/--disable-/--embed- options are held
back until the word being completed asks for one, and the result is
cached for the shell session because ./waf --help costs ~0.2s and this
runs on every tab press.

The caches are per checkout and are not filled unless the help was read:
a tab press outside a checkout would otherwise cache the handful of
hardcoded words and disable completion for the rest of the session, and
a second checkout would inherit the first one's options and boards.

list_boards is cached the same way and its errors are discarded, so
--board no longer costs a waf run per tab press or complains outside a
checkout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 12:38:48 +10:00
Eric Katzfey 7bcd289189 waf: enable warnings as errors for QURT
Enable -Werror by default for the QURT C and C++ compiler flags now that the outstanding absolute-value warnings have been addressed. Keep the existing --disable-Werror option available for development builds.
2026-09-16 09:48:38 +10:00
Andy Piper bf08027404 AP_NavEKF3: do not treat a never-written terrain timestamp as fresh
terrain_srtm_alt_ms is zero until the first writeTerrainData, and
imuSampleTime_ms counts from boot, so for the first five seconds of uptime
the age test passes against a terrain altitude that is still zero.
terrain_srtm_alt_valid then reports a terrain height the core has never
received: FuseOptFlow scales flow from it, getHeightControlLimit drops the
optical flow altitude cap, and getFilterStatus counts it towards relative
position validity.

On the ground at boot that costs little, since the value it invents is the
height above an origin the vehicle is sitting on. It matters after an
in-flight watchdog reset, where millis() restarts at zero and the vehicle
comes back armed and flying.

gndHgtValidTime_ms is guarded against exactly this one expression away, so
this is the same idiom rather than a new one. The 5 s is named while it is
being touched, because it is about to have a second user.

No autotest: the window is the first five seconds of uptime and closes
before healthy() opens, so SITL cannot enter it from a cold boot, and the
in-flight reset that reaches it is not something the harness can stage.
2026-09-15 16:33:29 +09:00
Andy Piper a2b6d4e693 autotest: cover the optical flow terrain scale height over slopes
EK3_OptflowTerrainScaleHeight flies above the rangefinder range with
EK3_OPTIONS bit 2, so the flow scale height comes from the terrain
database, and off the Kalaupapa cliffs where the ground falls about 160 m
below the EKF origin. Where the terrain sits at the origin altitude both
sign conventions agree, so a flat field would discriminate nothing.

GPS navigates, which keeps flow out of the velocity solution and makes the
trajectory independent of the scale height, so the two builds fly the same
path. The scale height reaches the innovation only through vehicle
velocity, so the window read is the traverse rather than a hover at the end
of it: over a stationary hold the signal is absent whichever expression is
in use. Measured across the traverse, the XKF5 consistency ratio is 0 with
the height right and 255 - the logged ceiling - with it inverted.

It flies at 60 m rather than 40 m because the terrain 50 m north of home
rises to 185.8 m AMSL against a 165.25 m home. At 40 m the margin over that
ridge is 19.5 m, and any lower would put the rangefinder back in range and
bypass the branch under test.

The test does not prove the database rather than the terrain offset state
supplied the height. With the option cleared the frozen terrain state gives
a scale height about 3.7x low, which measures a ratio of 3 - inside the
gate, and indistinguishable from a pass. A negative leg on this signal
would not discriminate, so none is claimed.
2026-09-15 16:33:29 +09:00
Andy Piper 09c48d855f AP_NavEKF3: fix the sign of the SRTM height used for flow scaling
terrain_srtm_alt is the terrain height above the EKF origin, positive up:
AP_AHRS::writeTerrainAMSL() converts the AMSL height AP_Terrain supplies
with alt_amsl_m - origin.alt, and the core stores it verbatim. pd is the
vehicle's position.z, positive down. Height above ground is therefore (-pd)
minus the terrain height, not the terrain height minus pd. The neighbouring
terrainState expression is right because terrainState is itself a D
coordinate, built as position.z + rngOnGnd, so the two branches of one
variable were being differenced in opposite conventions.

Where the AHRS and core origins coincide the old error is 2 x
terrain_srtm_alt, so it is smallest where the origin sits at field
elevation and grows with relief - and it moves the wrong way, reading high
over ground that is above the origin. AP_AHRS subtracts the one public
origin and hands the same figure to every core, which then differences it
against its own position.z, so where a core's own origin altitude has moved
- ekfGpsRefHgt drift, or lanes aligning against different receivers under
EK3_AFFINITY - the corrected form still carries that difference. The trace
here is complete only for the default EK3_OGN_HGT_MASK.

A terrain height that disagrees with the datum still collapses the scale
height to the on-ground range through the MAX, exactly as it does today.
The old expression could go negative too - over ground that sits further
below the origin than the vehicle sits above it - so this is pre-existing,
and the sign fix moves which geometry triggers it rather than closing it.
Falling back to terrainState there is the obvious repair and it does not
work: the enclosing condition has already declared that state stale.

Measured in SITL off the Kalaupapa cliffs, holding 60 m above an origin the
ground falls to 160 m below, so the true height above ground reaches 220 m.
GPS navigates, so flow is not fused into velocity and both builds fly the
same trajectory; only the scale height differs. Across the traverse the
logged flow innovation consistency ratio saturates its 255 ceiling - at
least 2.55, so flow at that geometry is rejected outright - against a peak
of 0 with this change. The raw innovation is deliberately not quoted: XKF5
logs it as an int16 scaled by 1000, and the old expression drives it past
the wrap point, so the logged figure there is an aliased value rather than
the real one.
2026-09-15 16:33:29 +09:00
Brown 4b84bc3bb3 AP_HAL_ChibiOS: update hwdef for Holybro Pixhawk6X Rev8
Use the Rev8 board type for the pin-compatible ICM45686 and LSM6DSV-family IMUs that share the same buses, chip selects, and rotations.
2026-09-15 16:59:33 +10:00