Skip to content

mavutil: add optional timeouts to the GPS fix and arm state waits - #1328

Open
zaccesss wants to merge 2 commits into
ArduPilot:masterfrom
zaccesss:mavutil-wait-timeouts
Open

zaccesss wants to merge 2 commits into
ArduPilot:masterfrom
zaccesss:mavutil-wait-timeouts

Conversation

@zaccesss

@zaccesss zaccesss commented Nov 5, 2026 •

Copy link
Copy Markdown

wait_gps_fix(), motors_armed_wait() and motors_disarmed_wait() block until their condition is met, so a script hangs for ever if the vehicle never gets a fix, never arms or the link drops.

I ran into this in a SITL mission script for a university team project. The first arm command is often refused while the EKF settles after the GPS fix, so I had to write my own arm and GPS fix loops with deadlines because motors_armed_wait() and wait_gps_fix() would otherwise wait for ever.

Each now takes an optional timeout in seconds:

  • wait_gps_fix(timeout=None) returns None on timeout and the GPS_RAW_INT message once there is a 3D fix
  • motors_armed_wait(timeout=None) and motors_disarmed_wait(timeout=None) return False on timeout and True once the arm state matches

With no timeout they still block exactly as before. The only difference for existing callers is that they now return a value (the message or True) instead of None. The one caller inside pymavlink, location(), ignores it.

The arm state waits only report a match from a real HEARTBEAT. If the timeout passes with no heartbeat at all they return False, rather than reading the default arm state (disarmed), which would otherwise make motors_disarmed_wait() report success with no vehicle connected. That is the second commit.

How I checked it

  • tests/test_mavutil_wait.py (8 tests) drives a real connection over local UDP. A second connection plays the vehicle and sends HEARTBEAT, VFR_HUD and GPS_RAW_INT messages. Each helper is tested for returning on time and for timing out. Both arm state waits are also tested with nothing on the other end of the link.
  • I ran the tests against the installed package (pip install ., run from outside the source tree so the installed copy is imported). They pass with this change. With the old mavutil.py swapped back in, the new tests fail, so they test the change and not something else.
  • The rest of the pytest suite passes locally, apart from four sysid32 generator tests that compile C with gcc and fail on macOS with or without this change.
  • flake8 is clean on the new test file. The changed mavutil.py lines pass the CI syntax check (--select=E9,F63,F7,F82).
  • timeout=None paths: recv_match() with blocking=True and no timeout never returns None, so the old blocking behaviour is unchanged.

wait_gps_fix(), motors_armed_wait() and motors_disarmed_wait() block
until the condition is met, so a script hangs for ever if the vehicle
never gets a fix, never arms or the link drops. Each now takes an
optional timeout in seconds. wait_gps_fix() returns None on timeout and
the GPS_RAW_INT message otherwise. The arm and disarm waits return
False on timeout and True otherwise. With no timeout they behave as
before.

The new tests drive a connection over local UDP with fake heartbeat,
VFR_HUD and GPS_RAW_INT messages and check both outcomes, including a
wait with nothing on the other end of the link.
@zaccesss

zaccesss commented Nov 5, 2026

Copy link
Copy Markdown
Author

Related to #1008: that script sends the arm command and then calls motors_armed_wait(), so when the vehicle refuses to arm it waits for ever with no message. This does not fix the refused arm itself, but with motors_armed_wait(timeout=...) the script would get False back and could report the failure instead of hanging.

With a timeout and no heartbeat at all, motors_disarmed_wait() checked
the default arm state. That default is disarmed, so it returned True.
The arm state waits now return False as soon as wait_heartbeat() times
out, so a match always comes from a real heartbeat. Added a test for a
disarmed wait with nothing on the other end of the link.
@zaccesss
zaccesss force-pushed the mavutil-wait-timeouts branch from 4e633da to 848a0b6 Compare November 5, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant