Commit Graph
73839 Commits
Author SHA1 Message Date
Peter Barker 0d3e2aaa8e Plane: fail DO_REPOSITION if GUIDED cannot be entered
When DO_REPOSITION asked for a change into GUIDED and the mode change
was refused (for example GUIDED being blocked by FLTMODE_GCSBLOCK) the
result of set_mode() was ignored.  The requested location was still
loaded with set_guided_WP() and the command was ACCEPTED, so a vehicle
in AUTO stayed in AUTO but flew towards the reposition target.

Return MAV_RESULT_FAILED instead, leaving the current mode's navigation
alone.
2026-09-14 19:59:12 +10:00
Peter BarkerandClaude Opus 5 f47861a374 .github: test_coverage: keep going when a coverage test suite fails
run_coverage.py now exits on the first failing test suite by default;
keep running the remaining suites so we still get a coverage report.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 18:58:28 +10:00
Peter BarkerandClaude Opus 5 3f73e5ad1f Tools: make run_coverage.py stop at errors, add a flag to keep going on errors
use as a diagnostic tool was limited when it would exit on some failures but not on others.

Make it exit on failures by default, add a flag to allow a user to get consistent behaviour the other way

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 18:58:28 +10:00
Peter Barker 7dbc76fb1c Tools: enable math index checks for every build.Rover CI job
The rover workflow's build job primes ccache with
--enable-math-check-indexes, matching sitltest-rover and
sitltest-sailboat, which both pass "Rover" as the run_autotest name.
sitltest-balancebot passes "BalanceBot", so it configured without the
flag, missed the cache on 872 of 1382 compiles and spent 6m33s
building ardurover against 14s in the other two jobs.

Key the flag on the build step rather than the name, so BalanceBot
builds the same binary as the other build.Rover jobs.
2026-09-14 18:58:17 +10:00
Peter Barker 50ed390939 autotest: IE24: set failsafes so vehicle disarms on low/crit battery
this test was relaying on the vehicle disarming even with an action of NONE.  Since we're changing that behaviour, change the test to set the failsafe to a value which will disarm the vehicle
2026-09-14 12:44:42 +10:00
Peter Barker 22bd42f6c8 autotest: add test for battery instant-disarm on failsafe when fs-action-NONE 2026-09-14 12:44:42 +10:00
Peter Barker 2aeb8bf242 Copter: do not disarm the vehicle on battery fs if fs is none 2026-09-14 12:44:42 +10:00
Clyde McQueen acef45eb0f autotest: improve Sub.GuidedPosVelAccel test 2026-09-12 19:46:43 -03:00
Clyde McQueen 51cd2dd1c0 AP_Scripting: avoid divide by zero in Lua script 2026-09-12 19:46:43 -03:00
Clyde McQueen 29b250b476 ArduSub: reject force inputs 2026-09-12 19:46:43 -03:00
Peter Barker 37ea692edb autotest: check an entry which exactly fills a listing packet is sent
Lists a directory holding a file whose entry is exactly the 239 bytes a
listing payload carries, one a byte longer than that, and a short one.
The first has to be listed, the second cannot be and must not be, and the
third proves dropping the one which cannot be sent did not end the
listing.
2026-09-12 15:00:50 +10:00
Peter Barker 4cedc1e346 GCS_MAVLink: list an entry which exactly fills a listing packet
An entry needing exactly as many bytes as the payload holds was treated as
unsendable and dropped. It does fit: AP_HAL::Util::vsnprintf builds its
BufferPrinter with size-1 and then writes the terminator itself at
str[size-1], and the byte that overwrites is the entry's own trailing NUL,
so the encoding which lands in the buffer is the one intended.

Compare against the size rather than allowing it, in all three places, so
the two packing loops still agree on what can never be sent.
2026-09-12 15:00:50 +10:00
Peter Barker b4697f8189 autotest: check the root directory lists its files
Puts a file and a directory in the root, lists it both with and without
times, and checks both come back - and, with times, that they carry the
modification time they were given.
2026-09-12 15:00:50 +10:00
Peter Barker 2a18e59e96 GCS_MAVLink: do not double the separator when listing the root
The path of the directory being listed is put in front of each entry's
name in order to stat it, with a "/" between. The root's path is already
just "/", so that produced "//name".

Most filesystems collapse that - FatFs skips duplicated separators
(ff.c:3019) and so does littlefs (lfs.c:1503) - but SITL's map_filename()
strips exactly one leading "/", so "//name" escapes to the host root. The
stat then fails, and a failed stat drops the entry, so every file in the
root went missing and the listing came back with directories only.

ArduPilot's own backend_by_path() also strips exactly one leading slash,
so a doubled separator would likewise miss a virtual backend.
2026-09-12 15:00:50 +10:00
Peter Barker f30be0bdea autotest: check a short FTP reply carries nothing past its size
Lists a directory to leave entries in the reply buffer, then asks past the
end of that listing, and checks the one byte NAK which comes back has
nothing but zeros behind the error code.
2026-09-12 15:00:50 +10:00
Peter Barker 94726509fc GCS_MAVLink: do not send FTP reply bytes which mean nothing
The whole reply buffer went out whatever the reply's size, so a short
reply was padded with bytes which are not part of it.

Those bytes come from the same reply, not an earlier one: setup_reply()
clears the whole transaction, but list_dir()'s offset-skip loop then
formats each entry it skips into response.data as scratch, and a listing
which ends in an EndOfFile NAK sets only data[0] - leaving the last
skipped entry sitting behind the error code.

Copy only the bytes the reply says it has. The rest of the packet is
already zero, and since MAVLink 2 trims trailing zeros from a payload, a
short reply now goes out shorter as well.

The scratch reuse behind it is left as it is; not sending the bytes is
what keeps them off the air.
2026-09-12 15:00:50 +10:00
Yves 14c871f273 AP_VideoTX: accept variable-length SmartAudio 2.1 settings
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
SmartAudio 2.1 reports a variable number of supported power levels. Validate the fixed fields, advertised level count, and CRC instead of requiring the maximum-size response struct.
2026-09-11 10:56:05 +01:00
rubikscube05 a5cd5f7981 AP_HAL_ChibiOS: fix bdshot_encoder bitwise shift bug
Fixes #34176
2026-09-11 10:29:57 +01:00
gradvizor b832113b10 bootloaders: ZenFC743 2026-09-10 14:38:28 +01:00
gradvizor 98e0837b5c hwdef: ZenFC743 2026-09-10 14:38:28 +01:00
Sharanie0612 5b6115d65d AP_OpenDroneID: preserve speed precision 2026-09-10 18:37:55 +10:00
Peter BarkerandClaude Opus 5 98cb21986d autotest: do not fire the simulated parachute while setting it up
SIM_Parachute deploys as soon as the PWM on SIM_PARA_PIN reads 1250 or
more, and it starts watching that pin the moment the pin number is set.
The parachute tests set the pin in the same set_parameters() call as the
release servo's function, which races the servo output: assigning
SERVO9_FUNCTION=27 leaves the channel at its previous value until
AP_Parachute drives it to CHUTE_SERVO_OFF (1100 by default, below the
trigger), and anything at or above 1250 in that window fires the chute
during setup.

The test then fails in a way which does not look like a setup problem at
all: "BANG!  Parachute deployed" arrives before the test starts waiting
for it, and the real release later in the mission is silent because the
chute has already gone, so the wait times out with "Failed to receive
text: bang".  Seen overnight in Parachute and in GCSFailsafe's parachute
subtest, one run in 26 each.

Configure the vehicle first, wait for the release channel to reach its
off position, and only then let the simulation watch the pin.  Done in
one helper, as four tests set this up the same way.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 18:32:45 +10:00
Michelle Rossouw 363235939d AP_InertialSensor: Correct VIBE message description 2026-09-10 12:46:52 +10:00
Pierre Kancir 4891432f35 .github: add actionlint CI check
Lints workflow syntax, action inputs, and runner labels/matrix on every
push and pull request touching the workflows or composite actions.

Fix the SC1090, SC2129 and SC2006 shellcheck findings actionlint
surfaces in esp32_build.yml, macos_build.yml and test_sitl_periph.yml
(group the summary-file appends, mark the non-constant `source
~/.bash_profile` as intentional, swap a backtick command substitution
for $(...)), and narrow the shellcheck suppression list to just
SC2086, the pre-existing quoting style across the build scripts that's
out of scope here.
2026-09-09 11:16:50 +10:00
Peter BarkerandClaude Opus 5 143f5aec12 autotest: budget FRSkyPassThroughStatustext in simulated time
The test waits for a statustext to reach it over the FRSky passthrough
link, and allowed "7 * self.speedup" simulated seconds for it.  That
scales the wrong way.  Measured, with an unlimited budget, the simulated
time needed to receive the wanted text is

    speedup    1     2     5    10    20   100
    needs    58.4  53.9  48.7  39.4  39.9   9.9 s
    allowed   7    14    35    70   140   700  s

The requirement falls as the speedup rises, because what has to happen
first is that the queue ahead of our text drains, and at a high speedup
far less simulated time passes while that happens in wall clock.  The
budget rose instead, so it handed out 71 times what was needed at the
default speedup - no assertion at all - and less than was needed at
anything below about 7.  It failed every time at --speedup=5, three
passes out of three in an overnight sweep, and had only 1.8x margin at
--speedup=10.

Allow a fixed 150 simulated seconds: 2.6x the slowest measured, and
still a real bound at the default speedup.  Passes at speedups 1, 5, 10
and 100.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 11:15:24 +10:00
dependabot[bot] 8b9ea70045 .github: Bump actions/setup-python
Bumps the github-actions group with 1 update in the / directory: [actions/setup-python](https://github.com/actions/setup-python).


Updates `actions/setup-python` from 6 to 7
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-09 08:49:45 +10:00
Pierre Kancir 9ed7c5564f Tools: bullseye is EOL 2026-09-09 06:45:16 +10:00
Pierre Kancir 88157d6a28 .github: bullseye is EOL 2026-09-09 06:45:16 +10:00
Willian GalvaniandCursor 2023e51a87 AP_Baro: fix MS5837 stamping BARO_DEVID with devtype 0
AP_Baro_MS56XX::_init() fills in the device ID from devtype() before
AP_Baro_MS5837::_init() gets a chance to assign _subtype, so the
devtype byte of BARO*_DEVID was taken from an uninitialised member.
In practice it read back as 0, which ground stations decode as an
UNKNOWN sensor. Pressure was unaffected because _calculate() only runs
once _subtype has been set.

Pick the variant in devtype() from _cal_reg.c1, which the parent has
already read out of PROM by the time it stamps the ID, and drop
_subtype so there is only one source of truth.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 06:34:01 +10:00
olliw42 7cf7aa9d48 AP_Logger: add dBm unit to log structure 2026-09-08 21:13:26 +10:00
Peter Barker f7b5cc7ddc Tools: size_compare_branches.py: do not emit 'missing build product' when creating progress files
this output is only useful at the end of a run, not during it
2026-09-08 21:12:02 +10:00
Pierre Kancir 58d8655190 .github: qurt_build: stop ignoring the QURT HAL 2026-09-08 19:44:19 +10:00
Pierre Kancir b20b5193ba .github: harden workflow permissions and small fixs
Add an explicit `permissions: contents: read` to the workflows that were
still relying on the (broader) default token permissions.
2026-09-08 19:44:17 +10:00
Pierre Kancir 795f76b1b6 .github: run the workflows that use problem matchers when those change
test_sitl_copter, test_sitl_rover and test_sitl_sub register four
matchers from .github/problem-matchers/ but ignored all of .github/
bar actions and their own file, so a matcher edit never reached the
workflow it was written for.  They gain the negation esp32_build.yml
already carries.  test_scripting.yml filters on an allowlist instead,
so Lua.json has to be named there.
2026-09-08 19:44:09 +10:00
Pierre Kancir be33a004c5 .github: test_location_ratchet: run on changes to itself
Its allowlist named the ratchet script and Tools/autotest but not the
workflow file, so an edit to the workflow was never exercised by the
workflow.
2026-09-08 19:44:02 +10:00
Pierre Kancir 91a2194ff9 .github: fix two path filters left stale by renames
'Tools/autotest/location.txt' never existed -- the file has been
locations.txt since f13e6079bc -- and common.py became
vehicle_test_suite.py in 00bbb61411.  Both patterns had been matching
nothing, so the files they were meant to ignore were in fact triggering
the workflows.
2026-09-08 19:43:42 +10:00
Pierre Kancir fb896efc40 .github: drop the dead .pydevproject path filter
The file went away with b0a961ce17 ("waf: Delete .pydevproject with
legacy Python 2"); the ignore entry has matched nothing since, in all 17
workflows that carried it.
2026-09-08 19:43:38 +10:00
Andy Piper 99d4933d58 AP_InertialSensor: bound the non-primary beat on Invensense v1
Unlike the v3 IMUs, where the sensor ODR is programmed to the backend
rate, the v1 FIFO fills at the 8kHz sensor rate when fast sampling and
the backend rate is a software decimation. Reading a non-primary at 2x
loop rate left 20 samples in the FIFO between beats, and with bus
latency on top it reached the depth at which _read_fifo() already
expects corrupt samples: an MPU6000 in the second slot gave a
continuous stream of "stop at 8 of 48" and temperature resets.

Hold a fast-sampling non-primary at 1kHz, one read buffer of samples
per beat, so the FIFO stays well clear of that depth. The 2x loop rate
scaling now only applies without fast sampling, where the FIFO fills at
the backend rate as it does on v3.
2026-09-08 10:30:49 +01:00
Andy Piper cca21b0833 AP_InertialSensor: scale the Invensense v1 beat with primary status
Mirror the v3 driver's set_primary(): with the fast rate loop's dynamic
FIFO enabled a non-primary IMU is read at 2x loop rate, bounded to
400..1000Hz, and the primary at the full backend rate. Without the
override the v1 driver ignored primary changes and read every IMU at
the full backend rate.
2026-09-08 10:30:49 +01:00
James HarveyandClaude Fable 5.1 736a2d547c tests: cover the scan-build archive step
The bug this guards against is a silent mis-report: a second local run
of process_scan_build_output.py moved its reports beneath the previous
run's tmp/scan-build and then read the previous run's findings.  Check
that outside GitHub Actions the reports stay where scan-build put them
and a repeat run reads its own findings, that under GitHub Actions they
are archived beneath the workspace, and that an existing archive or a
workspace that is not an absolute path fails the run rather than
losing the reports.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 18:39:30 +10:00
James Harvey bec13ec1d9 .github: use workspace paths for clang-scan-build
autotest sets TMPDIR to the checkout tmp directory, but the workflow
creates and uploads reports through a path containing the canonical
repository name. Forks with another name therefore point scan-build at
a directory that does not exist.

Use GitHub's workspace path so the job is independent of repository
name.

AI-assisted: root cause analysis and patch drafted with OpenAI Codex.
2026-09-08 18:39:30 +10:00
James HarveyandClaude Fable 5.1 3fbb2d250d Tools: make scan-build archive path portable
Derive the fixed archive destination from GitHub's workspace instead of
a path containing the canonical repository name, so the reports stay
inside the checkout when a fork is renamed.

Archive only under GitHub Actions.  The old path doubled as the CI
check: /__w/ardupilot/ardupilot/tmp never exists on a developer
machine, so archive_rename() was a no-op there by accident.  A path
derived from the checkout passes that check on any Linux developer
machine that has run scan-build, because autotest.py points TMPDIR at
the checkout's tmp directory, and a second local run would then move
its reports beneath the first run's tmp/scan-build, where the
non-recursive plist glob does not find them.  The check is now the
GITHUB_ACTIONS variable, as elsewhere in Tools/, and an existing
destination is refused rather than nested under.

GITHUB_WORKSPACE must be absolute.  An empty value would put the
archive relative to the current directory, where the upload step only
warns that it found nothing; an unset one now fails the same way
instead of raising KeyError.

AI-assisted: root cause analysis and patch drafted with OpenAI Codex;
archive gating reviewed and drafted with Claude.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 18:39:30 +10:00
Peter BarkerandClaude Fable 5 a3b190a800 autotest: pace CommonOriginExternalAHRSReceives's prearm polling
The wait loop sent MAV_CMD_RUN_PREARM_CHECKS on every iteration, and
the loop fed itself: each run emits several PreArm statustexts, so
the recv_match never blocked and the sends never paused.  At parallel
speedups this reached ~1150 commands per wall second - the vehicle's
main loop dropped to 200Hz answering them, 291k MSG records (22MB)
went into the session log, and the logger io thread was driven to
drop 11562 messages - the only non-zero drop count in a 907-log
audit of parallel-run file-backend logs.

Send at most one prearm run per simulated second, as
assert_prearm_failure already does.  Validated: two commands per run
(was ~15000), zero dropped messages, test passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-08 13:09:37 +10:00
Peter Barker 4673c008c1 AP_AHRS: move synthetic-airspeed estimation up from DCM
Reparent airspeed_EAS and get_unconstrained_airspeed_EAS from
AP_AHRS_DCM to AP_AHRS_Backend so backends other than DCM can supply a
synthetic airspeed without DCM compiled in.  As with the wind
estimation, the bodies are left in place in AP_AHRS_DCM.cpp - only the
class qualifier and the surrounding guard (AP_AHRS_DCM_ENABLED ->
AP_AHRS_ENABLED) change.  _last_airspeed_TAS moves to the base class;
DCM still updates it from drift_correction.

The synthetic estimate is gated on the backend having a ground
velocity from a source independent of airspeed.  Callers pass the
backend's published Estimates::have_velocity_source down through
airspeed_TAS/airspeed_EAS; DCM-internal callers pass have_gps()
directly, which is the same fact and the same value the old code
read.  The AP::gps() test the base class would otherwise have needed
would be wrong for e.g. ExternalAHRS, which sources velocity from
its own device rather than the autopilot's GPS.

As with the wind-estimation move, the airspeed_sensor_enabled helpers
are now DCM's own (9ed23d57e1), so the moved code tests the airspeed
sensor directly - the same nullptr/use/healthy test, written the way
the frontend's _should_use_airspeed_sensor now does.
2026-09-08 13:09:20 +10:00
Peter Barker d7c19195fe AP_AHRS: publish have_velocity_source in the backend estimates
Add have_velocity_source to AP_AHRS_Backend::Estimates: true if the
backend has a ground-velocity source that is independent of airspeed
(e.g. GPS), so the value may be used for synthetic airspeed without
circularity.  DCM publishes have_gps().  It may be true while
velocity_NED_valid is false (e.g. DCM with a 2D GPS fix).
2026-09-08 13:09:20 +10:00
Peter Barker b7602169e1 AP_AHRS: remove unused ExternalAHRS estimate_wind declaration
This method has never had a definition.
2026-09-08 13:09:20 +10:00
Peter Barker 3b1875c7d3 AP_AHRS: move wind estimation up from DCM
Reparent the wind-triangle estimator (estimate_wind and
set_external_wind_estimate) from AP_AHRS_DCM to AP_AHRS_Backend so any
backend can run it without DCM compiled in.  The method bodies are left
exactly where they are in AP_AHRS_DCM.cpp to preserve their history -
only the class qualifier changes and the surrounding guard switches
from AP_AHRS_DCM_ENABLED to AP_AHRS_ENABLED so they are compiled
whenever AHRS is.  Supporting state moves to the base class; DCM keeps
its no-argument estimate_wind wrapper, which passes
_body_dcm_matrix.colx().

One adaptation: the airspeed_sensor_enabled helpers are now DCM's own
(9ed23d57e1), so the straight-flight branch tests the airspeed sensor
directly - the same nullptr/use/healthy test, written the way the
frontend's _should_use_airspeed_sensor now does.
2026-09-08 13:09:20 +10:00
Peter Barker c7e4b105ac AP_AHRS: pass velocity and fuselage direction into estimate_wind
Split estimate_wind into a no-argument wrapper and an implementation
taking the velocity and the fuselage forward direction.  The matrix was
only ever used for _body_dcm_matrix.colx() (the trim-corrected body
forward axis in the earth frame), so pass that unit vector in directly
rather than the full attitude matrix.  Callers pass
_body_dcm_matrix.colx(); the vector must be a unit vector and is not
normalised here.
2026-09-08 13:09:20 +10:00
Peter Barker de3ff6d01a AP_Baro: read bmp581 thrice to get corrected data
original read-twice suffers from beat frequencies where the 50Hz update on the device and the 50Hz update rate of the backend drift relative to one another.  The device appears dead when that happens.
2026-09-08 10:51:50 +10:00
Peter BarkerandClaude Opus 5 805fa9f8d0 AP_Scripting: integrate the elapsed time in the GAT example
guided_above_terrain_posvelaccel_sub.lua integrates its position target
forward by the time since the last callback.  When a callback arrived
later than 2/RUN_HZ it substituted 1/RUN_HZ for the real interval:

    if (dt > 2.0 / RUN_HZ) then
        dt = 1.0 / RUN_HZ
    end

so a callback 243ms late advanced the target by 50ms and the remaining
193ms was discarded.  The position target then falls behind the clock,
and the vehicle - which tracks that target accurately - covers less
ground than the commanded speed implies.

Measured from a failing Sub.GuidedAboveTerrain run under autotest at
--parallel=16, over the 60 simulated seconds the test watches:

    GUIP updates      1047 at 17.2Hz (nominal 20Hz)
    late callbacks    76 of 1047 (7.3%), worst 243ms
    time discarded    5.82s, so 55.08s integrated of 60.90s elapsed
    distance          27.90m of an expected 30.00m, +-1.00m -> failed

The dataflash shows the loss is upstream of the controller, not in it:
the script commanded 0.495m/s and the position controller achieved
0.442m/s against a desired 0.443m/s - it tracked what it was given to
within 0.001m/s, and what it was given was slow.

Cap the step at a fixed MAX_DT instead, so ordinary jitter is
integrated honestly and only a real stall is bounded.  Pinning the
simulation speedup was tried first and is not a fix: at
context_set_speedup(10) the run still lost ground, reaching 28.93m,
because it reduces how often callbacks are late without changing what
happens when they are.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 10:34:59 +10:00