Skip to content

Fly a manoeuvre as one step program

Flown one wait_until per step, a manoeuvre costs a round trip per step, and at speedup N each round trip is N times its length in sim seconds. fly_steps takes the round trips out: each step applies its actions in the tick it starts, waits on one condition, and the next step starts in the tick that one settled.

A program cannot arm or upload a mission, because both need round trips with retries. Arm with the arm tool first:

arm(session_id, mode="QLOITER")
fly_steps(session_id, steps=[
{"label": "climb", "rc": {3: 2000}, "until": "altitude", "value": 5},
{"label": "hover", "rc": {3: 1500}, "until": "sim_time", "value": 20, "relative": True},
{"label": "land", "mode": "QLAND", "until": "disarmed", "timeout_s": 120},
])

The result, from the stock quadplane in a steady 6 m/s wind, snapshots trimmed:

{
"status": "done",
"current": null,
"error": null,
"steps": [
{ "index": 0, "label": "climb", "reason": "met", "t_start_s": 50.723, "t_end_s": 54.072,
"snapshot": { "height_m": 5.01, "mode": "QLOITER" } },
{ "index": 1, "label": "hover", "reason": "met", "t_start_s": 54.072, "t_end_s": 74.121,
"snapshot": { "height_m": 7.33, "mode": "QLOITER" } },
{ "index": 2, "label": "land", "reason": "met", "t_start_s": 74.121, "t_end_s": 94.922,
"snapshot": { "height_m": 0.0, "mode": "QLAND", "armed": false } }
]
}

Each step’s t_start_s is the previous step’s t_end_s to the millisecond: no gap, no matter how slowly the caller reads. The hover’s relative: true counts from the tick the climb ended, so it is exactly 20 sim seconds long.

  • Validate first, fly second. Every step is checked before anything runs: mode names against the vehicle’s mode table, channels, PWM, values, the speedup range. One bad step rejects the program with its index and nothing was run.
  • A step without until ends in the tick its actions apply. Use it to set several things at once, then wait in the next step.
  • Modes are not confirmed. A step’s mode is sent once. If the rest of the program depends on it, make the next step {"until": "mode", "value": "QLAND"}.
  • Timeouts default to 60 sim seconds, or the wait plus 60 for time and relative sim_time. A landing usually needs more; set timeout_s.
  • on_timeout: "continue" turns a timeout into a recorded result instead of a failure, for a step you only want to bound.
  • wind is an action too. {"wind": {"speed_mps": 8, "gusts": "dryden", "seed": 3}} starts a gust front as a step begins; {"wind": {"speed_mps": 0}} calms it.

The full field list is on Step, wind and mission fields.

fly_steps returns within about 85 s. A longer program keeps flying in the server, and the call comes back with status: "running", the steps settled so far and the index of the current one:

steps_status(session_id) # waits up to about 85 s for the program to end
steps_status(session_id, wait=False) # answers at once

Loop on steps_status until status is done, failed or aborted. On a session opened with idle_speedup, a running program keeps the sim at full speed whether or not a call is waiting on it, and the idle speed applies once it ends.

failed means a step timed out with on_timeout: "stop" or SITL died; error says which, and the last step result carries the snapshot from that tick.

abort_steps(session_id)

The program stops after the current tick. RC stays as the last step left it, so a climbing vehicle keeps climbing. Set the throttle or a mode next:

abort_steps(session_id)
set_mode(session_id, "QLAND")