Skip to content

Mission instructions, instruction updates and mission rules - #321

Draft
jp-pino wants to merge 11 commits into
masterfrom
jp-pino/mission-instructions-and-rules
Draft

jp-pino wants to merge 11 commits into
masterfrom
jp-pino/mission-instructions-and-rules

Conversation

@jp-pino

@jp-pino jp-pino commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

New mission instructions, a way to run one instruction outside a mission, changes to a loaded mission, and mission rules that run instructions when their triggers are satisfied.

New instruction commands

New Instruction oneof fields, each with a matching InstructionType value:

Field Command InstructionType
15 MultibeamRecordCommand { enable, storage_location } 14 MULTIBEAM_RECORD
16 MultibeamDriverCommand { activate, config, expected_device_id } 15 MULTIBEAM_DRIVER
17 SetMultibeamConfigCommand { config, expected_device_id } 16 SET_MULTIBEAM_CONFIG
18 SetLightsCommand { intensity, target } 17 SET_LIGHTS
19 SetLaserCommand { laser } 18 SET_LASER
20 SetTiltStabilizationCommand { enabled } 19 SET_TILT_STABILIZATION
21 SetCvModelCommand { package_id, running } 20 SET_CV_MODEL
22 AnnotationCommand { annotation } 21 ANNOTATION
23 SetHeadingCommand { heading, relative } 22 SET_HEADING
24 TransectCommand { course, distance, speed, depth_set_point, circle_of_acceptance } 23 TRANSECT
25 RelativeDepthCommand { depth_change, speed } 24 RELATIVE_DEPTH
26 SetSpeedCommand { cruise_speed } 25 SET_SPEED

Also:

  • LightTarget enum (MAIN, GUESTPORT) for SetLightsCommand.target.
  • CameraCommand: Camera camera = 3 and StorageLocation storage_location = 4.
  • ControlModeHorizontal: CONTROL_MODE_HORIZONTAL_WEATHER_VANING = 4.
  • Instruction.auto_continue (3) is renamed pause_on_completion, with the same number and type. Clients never set the field, so under proto3's default the old meaning would have paused after every instruction. With the new name, true pauses after the instruction and missions that leave it unset keep running.

Running one instruction

  • RunInstructionCtrl { Instruction instruction = 1; uint32 request_id = 2 } runs one instruction right away, outside any mission.
  • CancelInstructionCtrl { uint32 request_id = 1 } cancels it.
  • InstructionResultTel { InstructionResult result = 1 }, with InstructionResult { request_id, instruction_id, state, reason } and InstructionResultState (ACCEPTED, REJECTED, COMPLETED, FAILED, CANCELLED).
  • control.proto now imports mission_planning.proto.

Instruction updates

SetInstructionUpdateReq has no clients yet, so it is redesigned to cover replace, insert and remove. Field 1 keeps its number and type:

message SetInstructionUpdateReq {
  oneof operation {
    Instruction replace = 1;
    InsertInstruction insert = 2;
    uint32 remove_id = 3;
  }
}
message InsertInstruction { Instruction instruction = 1; uint32 before_id = 2; bool append = 3; }
message SetInstructionUpdateRep { bool accepted = 1; string reason = 2; uint32 revision = 3; }

Mission revision and status

  • Mission.revision = 10, set by the drone and increased with every accepted update.
  • MissionStatus: int32 active_instruction_id = 10 (-1 when none), uint32 revision = 11, string failure_reason = 12.

SetMissionRep

  • SetMissionRep { bool accepted = 1; string reason = 2 }. A drone without these fields answers an empty message, so "not accepted" with no reason means the mission was loaded the old way.

Mission rules and triggers

  • MissionRule { id = 1, name = 2, disabled = 3, enter_instructions = 5, exit_instructions = 6, triggers = 7, hold_ms = 8, release_ms = 9, cooldown_ms = 10 }. The enter instructions run once all triggers have been satisfied together for hold_ms. The exit instructions run once one has been unsatisfied for release_ms, then cooldown_ms must pass before the rule fires again. Instructions that move the drone are refused in rules.
  • Trigger { oneof condition } with detection_trigger = 1, depth_trigger = 2, altitude_trigger = 3 and location_trigger = 4. The TriggerKind enum's values are those field numbers.
  • DetectionTrigger { class_names, model_name, camera, min_confidence, min_area_fraction }.
  • DepthTrigger { min_depth, max_depth } and AltitudeTrigger { min_altitude, max_altitude } define a band, where a maximum of zero means no upper bound.
  • LocationTrigger { position, circle_of_acceptance }.
  • MissionRulesTel { repeated MissionRuleStatus rules = 1 }, with these types:
    • MissionRuleStatus { id, state, episodes, last_fired, last_result, last_reason, triggers }
    • MissionRuleState (IDLE, ACTIVE, COOLDOWN, DISABLED)
    • TriggerStatus { kind, satisfied, sensor_unavailable }, one per trigger. A trigger whose sensor reading is missing is not satisfied.
  • SetMissionRulesReq { rules } / SetMissionRulesRep { accepted, reason }, GetMissionRulesReq / GetMissionRulesRep { rules }, ClearMissionRulesCtrl.
  • MissionRule reserves 4 and DetectionTrigger reserves 6–8. Pre-release builds used those numbers for a single detection trigger and its timings, which now live on MissionRule.
  • mission_planning.proto now imports google/protobuf/timestamp.proto.

Sonar id on multibeam commands

  • MultibeamDriverCommand.expected_device_id = 3 and SetMultibeamConfigCommand.expected_device_id = 2 (GuestPortDeviceID) give the sonar the configuration was made for. If the connected sonar is a different one, the configuration is skipped with NOTIFICATION_TYPE_MULTIBEAM_SONAR_MISMATCH. Unspecified applies the configuration to whichever sonar is connected.

Notifications

New NotificationType values:

  • 35 INSTRUCTION_STARTED
  • 36 MISSION_PAUSED_BY_INSTRUCTION
  • 37 MISSION_UPDATED
  • 38 MISSION_RULE_FIRED
  • 39 MISSION_RULE_RELEASED
  • 40 MULTIBEAM_SONAR_MISMATCH

Compatibility

Every change is additive on the wire. Two fields are renamed with the same number and type, which changes their generated and JSON names:

  • Instruction.auto_continue becomes pause_on_completion, which also inverts its meaning (see above).
  • SetInstructionUpdateReq.instruction becomes replace.

🤖 Generated with Claude Code

jp-pino and others added 10 commits September 9, 2026 21:18
Lets a client execute one mission Instruction right away, outside any
mission, and learn its outcome by request id. Non-motion instructions run
in any mission state; motion instructions only while no mission is
running. Phase 2 of the MissionSupervisor restructuring:
https://claude.ai/code/artifact/951a11c6-e492-436f-90bc-aa61f3b0d05c

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…, laser, tilt stabilization, CV model, annotation

Phase 3a of the MissionSupervisor restructuring:
https://claude.ai/code/artifact/951a11c6-e492-436f-90bc-aa61f3b0d05c

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…h, set speed

Phase 3b of the MissionSupervisor restructuring:
https://claude.ai/code/artifact/951a11c6-e492-436f-90bc-aa61f3b0d05c

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s and pause_on_completion

Instruction.auto_continue (never set by clients, so proto3's default would
have paused after every instruction) becomes pause_on_completion with the
same number and type, so old missions keep running throughout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… telemetry

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rules run unless disabled; MissionStatus.active_instruction_id is -1 when
none (instruction ids may be 0); InsertInstruction.append instead of
before_id 0; comments attach to the right messages again; the limits of
rules, the commands that move the drone, the notification payloads and
the meaning of an empty SetMissionRep are written down.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add DepthTrigger, AltitudeTrigger and LocationTrigger next to DetectionTrigger
and wrap the four in a Trigger message with a oneof. MissionRule now carries a
repeated list of triggers that must all be satisfied at once, and hold_ms,
release_ms and cooldown_ms move from DetectionTrigger to the rule, where they
apply to the combination. MissionRuleStatus gains a TriggerStatus per trigger
so a client can show which condition is holding a rule back and whether the
sensor for it is missing.

SetMultibeamConfigCommand and MultibeamDriverCommand carry the
GuestPortDeviceID the configuration was made for, and the drone skips the
configuration with NOTIFICATION_TYPE_MULTIBEAM_SONAR_MISMATCH when the
multibeam driver reports a different sonar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Say what the drone actually does with a trigger band and with a multibeam
configuration:

- DepthTrigger and AltitudeTrigger: neither bound may be negative and a
  maximum that is set has to be above the minimum, so a band with no width
  is refused rather than accepted as a rule that never fires. A depth
  trigger reports sensor_unavailable while no depth has reached the mission
  at all, rather than never.
- MissionRule: a rule needs at least one instruction in one of its lists.
- SetMultibeamConfigCommand and MultibeamDriverCommand: the configuration is
  also measured against the range, frequency modes and beam count of the
  sonar, and a configuration outside them skips the instruction rather than
  being clamped. For the driver command that means the driver is not started.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tructions-and-rules

No conflicts. Master added no field number, enum value or type name that
the mission changes use, so nothing is renumbered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request new message New message definition

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant