🚚 WIA Delivery Robot Standard Ebook | Chapter 6 of 8
A single delivery robot that follows the Phase 3 navigation protocol can complete a trip on its own. A business, however, does not run one robot; it runs a fleet across a campus, a building complex or a city district, and the value of the standard only shows when robots from different vendors can be observed, dispatched, charged and updated by one cloud platform. Phase 4 of WIA ROB-010 (Fleet Integration) describes that platform: the services it contains, the telemetry channel that feeds it, the way tasks are assigned and conflicts are resolved, the charging and maintenance workflows, and the security and recovery expectations around all of it.
This chapter reads Phase 4 as an engineer who has to build it. For each topic it states what the specification actually says, where the text is only a sketch, and what an implementation has to decide on its own. REST endpoint details (authentication, fleet listing, statistics and the error envelope) were covered in Chapter 4 and are not repeated here; fleet KPIs and conformance evidence are treated in Chapter 7. The running example uses the same robot as the rest of the book, 550e8400-e29b-41d4-a716-446655440000.
Phase 4 §1.1 draws the fleet as a cloud platform with four services sitting on a shared message broker, and any number of robots connected underneath. The broker is named as “MQTT/Kafka”, which is a useful hint about roles rather than a product choice: MQTT is a lightweight publish/subscribe protocol suited to many small devices on unreliable links, while Kafka is a durable log suited to high-volume processing inside the data centre. A common pattern is to terminate robot connections on an MQTT broker and bridge the resulting stream into a log for the back-end consumers, but the standard does not require that split.
The division of responsibility in §2.1 is worth restating as interfaces, because each service consumes and produces different data:
| Service | Responsibilities in Phase 4 §2.1 | Main inputs | Main outputs |
|---|---|---|---|
| Fleet Manager | Robot registration and lifecycle, task assignment and load balancing, health monitoring and alerting, configuration management | RobotState stream, new delivery tasks (Package + Route from Phase 1) | Assignments, commands, configuration, alerts |
| Route Optimizer | Multi-robot route planning, traffic prediction and avoidance, dynamic re-routing, charging schedule optimization | Planned paths, map and zone data, station availability | Route objects, deconfliction decisions, charging plans |
| Analytics Engine | Real-time dashboards, historical analysis, anomaly detection, predictive maintenance | Time-series telemetry, delivery outcomes | Metrics, maintenance alerts, reports |
| Operator Dashboard | Live visualization, manual intervention, incident management, reporting | Current fleet state, alerts | Operator commands (via the Phase 2 API), incident records |
Two properties of this architecture shape everything that follows. First, the robot is the authority on its own safety: the cloud assigns work and offers advice, but the emergency stop, obstacle response and failure-mode handling defined in Phase 3 run on board and must keep working when the cloud is gone (§8.1, “robots operate autonomously if cloud unreachable”). Second, the only data contract the architecture assumes between robot and cloud is the Phase 1 RobotState. Anything else a vendor sends — raw diagnostics, proprietary logs — is outside the standard and should not be something the Fleet Manager depends on for dispatch decisions.
Phase 4 §2.2 fixes three things about robot telemetry: robots publish state updates every 1–5 seconds; the MQTT topic is fleet/robots/{robot_id}/state; and messages use QoS 1 with a JSON-encoded RobotState as payload. Everything else in the pipeline — broker product, stream processor, database — is left to the implementer. The flow from §2.2 is: robot → MQTT/HTTP → broker → stream processor → time-series database, with branches to the real-time dashboard, alerting and the analytics engine.
A telemetry message for the running example looks like this. It is a valid Phase 1 document: all five required fields are present, version matches the SemVer pattern and mode uses the Phase 1 enum.
Topic: fleet/robots/550e8400-e29b-41d4-a716-446655440000/state
QoS: 1
Payload:
{
"robot_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2025-12-26T10:30:02.000Z",
"version": "1.0.0",
"position": {
"latitude": 37.5665,
"longitude": 126.9780,
"accuracy": 0.4,
"source": "fused"
},
"heading": 92.5,
"speed": 1.2,
"battery_level": 64,
"mode": "autonomous"
}
Note that the robot_id appears twice, once in the topic and once in the body. Consumers should check that the two agree and reject the message if they do not; otherwise a misconfigured or compromised client can publish state that looks like it comes from another robot. The topic-level identifier is what the broker's access control can enforce (see 6.7), so it is the stronger of the two.
MQTT QoS 1 is “at least once”: the broker keeps resending a message until the receiver acknowledges it, so a message can arrive more than once, for example after a reconnect in the middle of an acknowledgement. The standard chose QoS 1 over QoS 0 (at most once, may be lost) and QoS 2 (exactly once, more round trips). The consequence is a hard requirement for every consumer: processing must be idempotent. The natural key is the pair (robot_id, timestamp). A time-series store should upsert on that key instead of appending; an alerting rule that counts events should count distinct keys; and a “current state” cache should only replace its entry when the incoming timestamp is newer than the one it holds, because after a reconnect older buffered messages can arrive after newer ones.
The following Python sketch uses the paho-mqtt client (version 2 API) to show both sides. The publisher sends one RobotState per interval; the subscriber listens on the wildcard fleet/robots/+/state, cross-checks the identifier, drops duplicates and ignores stale updates for the live view.
import json, ssl, time
import paho.mqtt.client as mqtt
BROKER = "broker.example.net" # illustrative host
ROBOT_ID = "550e8400-e29b-41d4-a716-446655440000"
# ---- robot side: publish RobotState every PUBLISH_S seconds ----
PUBLISH_S = 2 # Phase 4 §2.2 allows 1–5 s
def run_publisher(read_state):
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=ROBOT_ID,
clean_session=False) # keep session across reconnects
c.tls_set(certfile="robot.crt", keyfile="robot.key",
cert_reqs=ssl.CERT_REQUIRED)
c.connect(BROKER, 8883)
c.loop_start()
topic = f"fleet/robots/{ROBOT_ID}/state"
while True:
state = read_state() # dict that validates against Phase 1
c.publish(topic, json.dumps(state), qos=1)
time.sleep(PUBLISH_S)
# ---- cloud side: subscribe to all robots, dedupe, keep latest ----
seen = set() # use a TTL cache in production
latest = {} # robot_id -> last timestamp
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe("fleet/robots/+/state", qos=1)
def on_message(client, userdata, msg):
topic_id = msg.topic.split("/")[2]
state = json.loads(msg.payload)
if state.get("robot_id") != topic_id:
return # identifier mismatch: reject and log
key = (topic_id, state["timestamp"])
if key in seen:
return # QoS 1 duplicate
seen.add(key)
store_timeseries(state) # upsert on (robot_id, timestamp)
if latest.get(topic_id, "") < state["timestamp"]:
latest[topic_id] = state["timestamp"] # safe only if all robots use
update_live_view(state) # the same UTC "Z" format
The string comparison of timestamps in the last lines only works because all timestamps are written in one fixed UTC format. Phase 1 allows any ISO 8601 date-time, including offsets such as +09:00; a robust consumer parses them into instants before comparing. This is a small example of a larger rule: normalize at the edge of the pipeline, once, rather than in every consumer.
The 1–5 second window is a trade-off between freshness and load. A shorter interval makes the dashboard smoother and lets the Fleet Manager notice a stuck robot sooner, but it multiplies broker traffic and storage by the number of robots. A practical approach is to vary the interval within the permitted window by state: publish at the fast end while mode is autonomous or while an error is active, and at the slow end while idle or charging. Events that matter immediately — an emergency stop, a failure-mode transition from Phase 3 — should not wait for the next tick; publish an extra state message at once. Phase 1 §6.3 also suggests Protocol Buffers and delta updates for high-frequency telemetry. If you adopt a binary encoding, keep the field names and semantics identical to the JSON schema so that the Phase 1 schema remains the single definition, and state the encoding in the deployment documentation because the MQTT topic alone does not reveal it.
§2.2 lists what the stream processor does: compute aggregations such as average speed and battery, store history in a time-series database, feed the dashboard and drive anomaly alerts. Three practical decisions follow:
robot_id so that one robot's messages are processed in order by one worker. Cross-robot aggregates (zone occupancy, fleet battery distribution) are then computed from the per-robot latest state.Idempotency keys, ordering and every latency figure in the book depend on clocks that agree. Annex E of Phase 4, which is explicitly non-normative, notes that NTPv4 against stratum-2 servers is sufficient for most deadlines in the phase and recommends PTP (IEEE 1588) for sites that need deterministic interlocks. NTPv4 is specified in IETF RFC 5905. In practice, synchronize the robot's clock before it starts publishing, record the synchronization status in the vendor diagnostics, and let the stream processor flag messages whose timestamp is far in the future relative to broker receive time — a symptom of a robot that booted without time sync.
Phase 4 §3.1 gives a centralized algorithm in pseudocode: for each new task, skip robots whose battery is below a threshold and robots already at capacity, compute a cost for each remaining robot as the sum of distance to pickup, estimated delivery time and impact on existing tasks, and assign the task to the cheapest robot. The algorithm is short and correct in spirit, but it leaves four decisions to the implementer.
weight_kg, dimensions_cm) and temperature control (temperature_controlled) are more realistic constraints. Document the measure you use.urgent or express packages (the Phase 1 priority enum).def assign(task, robots, v_nominal=1.5, reserve_pct=25, w_impact=1.0):
"""Return the robot_id with minimum cost, or None.
Units: seconds. v_nominal (m/s) and reserve_pct are deployment parameters."""
best, best_cost = None, float("inf")
for r in robots:
if r.telemetry_stale or r.mode in ("error", "manual"):
continue
if r.load + task.load > r.capacity:
continue
need_pct = energy_pct(r, task) + energy_pct_to_nearest_charger(r, task.dropoff)
if r.battery_level - need_pct < reserve_pct:
continue
cost = (distance_m(r.position, task.pickup) / v_nominal
+ eta_delivery_s(task)
+ w_impact * added_delay_s(r, task))
if cost < best_cost:
best, best_cost = r.robot_id, cost
return best
Consider one new task and three robots. All numbers below are illustrative: a nominal speed of 1.5 m/s, a delivery leg of 720 s after pickup for every robot, and a reserve of 25 %.
| Robot | Battery | Distance to pickup | Queued work | Filter | Cost (s) |
|---|---|---|---|---|---|
| R1 | 64 % | 900 m | 2 deliveries; inserting the pickup delays them by 240 s | passes | 600 + 720 + 240 = 1,560 |
| R2 | 91 % | 1,400 m | none | passes | 933 + 720 + 0 = 1,653 |
| R3 | 31 % | 300 m | none | fails: task plus return to charger needs about 9 %, leaving 22 % < 25 % | — |
R1 wins by about 90 seconds. The margin is small, and it depends entirely on how much the 240 s delay to R1's existing customers is worth. If those two deliveries are marked urgent and the operator sets w_impact to 1.5, R1's cost becomes 1,680 s and R2 wins. This sensitivity is the real content of the algorithm: the formula is simple, but the weights encode business policy, and they should be configuration, recorded with every assignment decision so that an operator can later explain why a particular robot was chosen. R3 is also instructive. It is the closest robot and would win on distance alone; the energy filter prevents a dispatch that would strand it below the charging reserve.
The alternative in §3.1 is a distributed auction: the manager broadcasts the task, each robot computes a bid equal to its own cost to complete it, robots submit bids, the manager awards the task to the lowest bidder, and the winner confirms. The auction moves the cost calculation onto the robot, where the most current information lives — its exact queue, its own energy model, the local obstacles it has just seen. It also lets vendors keep their energy models private: they publish a number, not the model behind it.
The five steps are not a complete protocol. An implementation must add at least the following, and the choices should be documented because they are not in the standard:
robot_id) so that repeated runs give the same result;Phase 4 does not name topics for auction messages. If you run the auction over MQTT, a layout such as fleet/tasks/{task_id}/offer, .../bid and .../award works; treat it as a deployment convention, not as part of WIA ROB-010.
| Aspect | Centralized minimum cost | Auction |
|---|---|---|
| Where cost is computed | Cloud, from telemetry | Each robot, from local state |
| Freshness of inputs | As old as the last telemetry message (1–5 s) | Current at bid time |
| Decision latency | One computation | At least one broadcast plus the bid deadline |
| Behaviour with poor connectivity | Works from last known state | Robots that cannot hear the offer simply do not bid |
| Vendor model privacy | Cloud needs an energy model per vendor | Vendors publish only the bid |
| Explaining a decision | Straightforward: all inputs are logged centrally | Requires logging every bid received |
Many fleets end up with a hybrid: the manager filters and ranks centrally, then asks the top two or three candidates to confirm with a fresh cost before awarding. Either way, the assignment should be written back into the Phase 1 data — the package status moves from pending to assigned, and the robot's route reflects the new plan — so that every consumer sees one version of the truth.
Phase 3 already teaches each robot to avoid obstacles it can sense, including other robots, through local planning (Chapter 5). Fleet-level deconfliction deals with the conflicts a single robot cannot see coming: two robots about to enter the same one-way corridor from opposite ends, or three robots converging on one elevator. §3.2 gives two mechanisms.
A coordination zone is a restricted area — a narrow doorway, a lift, a ramp — that only one robot may occupy at a time. Access is token based: a robot requests the zone's token, waits if another robot holds it, enters when granted and releases on exit. This is a distributed mutual-exclusion problem, and the standard's three sentences need three safeguards to be safe in the field:
Elevators deserve a note of their own. Phase 1's navigation_constraints.elevator_allowed tells the planner whether a route may use one, but Phase 4 says nothing about how a robot calls the car or tells the building which floor it wants. That integration is building-specific today; treat the lift as a coordination zone with a long lease and handle the building interface outside the standard.
The second mechanism is dynamic deconfliction: robots share planned paths with the fleet manager, the manager looks for paths that intersect within a time window, assigns priorities by urgency and battery, and the lower-priority robot yields by stopping or re-routing. A workable conflict check treats each planned path as a sequence of timed points and flags a conflict when two robots are predicted to be closer than a separation distance at overlapping times:
def conflicts(path_a, path_b, sep_m=2.0, window_s=30, dt=1.0):
"""path(t) -> (x, y) in a local metric frame; returns first conflict time or None."""
t = 0.0
while t <= window_s:
ax, ay = path_a(t)
bx, by = path_b(t)
if (ax - bx) ** 2 + (ay - by) ** 2 < sep_m ** 2:
return t
t += dt
return None
def who_yields(a, b):
# Higher delivery priority wins, then lower battery (it can least afford a detour),
# then a deterministic tie-break so that every node reaches the same answer.
rank = {"urgent": 2, "express": 1, "normal": 0}
ka = (rank[a.priority], -a.battery_level, a.robot_id)
kb = (rank[b.priority], -b.battery_level, b.robot_id)
return b if ka > kb else a
The separation distance, prediction window and time step are parameters, not values from the standard. The prediction window is bounded by how far ahead a path is trustworthy: in dense pedestrian areas the local planner will deviate from the global path often, so predictions beyond a few tens of seconds add false alarms rather than safety. Two further details matter. Compute distances in a local metric frame, not by subtracting latitudes and longitudes (Chapter 2 covers the conversion). And make the tie-break deterministic, because deconfliction decisions may be computed on more than one node and must agree.
Yielding should be expressed as a normal command to the robot, not as a new kind of safety stop. The yielding robot decelerates, waits or re-plans through its ordinary Phase 3 behaviour (the WAITING state in the behaviour state machine), while its own obstacle detection stays fully in charge of what happens in the next metre.
Phase 4 §4.1 describes charging in four stages. The table adds, for each stage, what the robot should report in its Phase 1 state and what can go wrong.
| Stage | What happens (§4.1) | RobotState reported | Typical failure to handle |
|---|---|---|---|
| 1. Navigation | Travel to the station's coordinates; fine positioning with visual markers (AprilTags) | mode: autonomous, route to a waypoint of type charging_station | Marker not visible (occlusion, glare); approach blocked |
| 2. Docking | Align using camera feedback, make contact with the charging pads, verify that charging started from voltage/current sensors | mode: charging only after current is confirmed | Contact made but no current: retry alignment a bounded number of times, then report an error |
| 3. Charging | Monitor battery level and rate, estimate time to full, update the fleet manager | mode: charging, rising battery_level | Charge rate far below expected: possible pad wear or battery fault; raise a maintenance alert |
| 4. Completion | Detect full charge, undock, return to service, report availability | mode: idle until assigned | Undocking obstructed; station slot not released |
Two refinements are worth making to the text. First, the standard says full charge is detected by a “voltage plateau”. For lithium-ion packs charged with the usual constant-current / constant-voltage method, voltage reaches the set point early in the constant-voltage phase and it is the current that then tapers; the reliable end-of-charge signal is the battery management system's own status rather than the robot's voltage reading. Second, do not report charging merely because the robot is parked on the dock. The Fleet Manager uses that mode to plan availability, and a robot that is docked but not receiving current is a fault, not a charging robot.
The standard defines three station operations — list stations with status, check a station's availability, reserve a slot — whose HTTP form is listed in Chapter 4. At the fleet level the important question is the semantics of a reservation. The text does not say how long a reservation lasts or what happens if the robot never arrives. A sensible policy is a reservation that expires at the robot's estimated arrival time plus a grace period, is extended when fresh telemetry shows the robot still approaching, and is released immediately when the robot's plan changes. Without expiry, a single robot that breaks down on the way to a station quietly removes that slot from the fleet.
| Strategy (§4.2) | Trigger | Benefit | Implementation note |
|---|---|---|---|
| Proactive | Battery at 20–30 % | Avoids emergency low-battery situations; the fleet manager reserves slots in advance | Should be well above the Phase 3 failure-mode threshold of 15 %, which is the emergency case |
| Opportunistic | Idle periods | Partial top-ups keep robots available without long charge sessions | Only worthwhile when a station is close; count the trip energy |
| Dynamic scheduling | Fleet-wide plan | Keeps enough robots available at peak demand; can shift charging to off-peak electricity tariffs | Needs a demand forecast; see the analytics techniques in §6.2 of the phase |
The three strategies interact with task assignment. The energy filter in 6.3 and the proactive threshold should use the same reserve value, otherwise the dispatcher will keep assigning work to robots that the charging planner is trying to send home. Keep both in one configuration and log the value with every decision.
§5.1 lists the wear indicators to monitor: battery charge cycles and capacity degradation; motor runtime and current-draw anomalies; wheel odometry and, where fitted, tyre pressure; and sensor calibration drift and data-quality degradation. Most of these are not in the Phase 1 RobotState, which carries operating state rather than component health. A fleet therefore needs a second, lower-rate diagnostic channel, and the vendor has to map its internal counters onto the indicators the analytics engine expects. The standard's alert format is the common output:
{
"alert_id": "maint-2025-12-26-001",
"robot_id": "550e8400-e29b-41d4-a716-446655440000",
"severity": "warning",
"component": "battery",
"issue": "Capacity degraded to 75% of original",
"recommendation": "Schedule battery replacement within 30 days",
"timestamp": "2025-12-26T10:30:00Z"
}
This example comes from §5.1, and its values are illustrative. The standard does not publish a schema for the alert, so the allowed values of severity and component are not fixed. If you exchange alerts between systems, define an enum for each (for example info/warning/critical, and one entry per monitored component), version that schema the way Phase 1 versions its own, and link the alert to the telemetry window that triggered it so that a technician can see the evidence.
§5.2 describes updates to firmware, software and maps as a staged rollout: prepare the package, deploy it to a subset of the fleet (a canary), monitor, roll out to everyone if successful, roll back affected robots if not. The safety rules are that packages are cryptographically signed, the signature is verified before installation, the previous version is kept for rollback, and a robot is never updated while navigating.
“Never while navigating” has to become a concrete gate on the robot, evaluated by the robot itself, because the cloud's view of the robot can be seconds old. A reasonable gate combines Phase 1 fields with the charging reserve:
def may_install_update(state, has_cargo, pkg):
return (
state["mode"] in ("idle", "charging") # not autonomous or manual
and not has_cargo # no customer package on board
and state["battery_level"] >= 50 # example floor; set per platform
and verify_signature(pkg) # before anything is written
and pkg.target_version != current_version()
)
Beyond the gate, three practices make rollback real rather than aspirational. Install to an inactive slot (an A/B layout) and switch only after the new image has booted and passed a self-test, so that a failed update leaves the old version untouched. Report the installed software version in your diagnostics channel, so that analytics can compare canary and control groups. And define the canary's success criteria before the rollout — for example the emergency-stop rate, failure-mode events and task success over a fixed number of trips — instead of deciding afterwards whether the numbers “look fine”.
The standard requires signing but does not name a format. Established options include The Update Framework (TUF), which protects against compromised repositories and rollback attacks, and its automotive adaptation Uptane. Chapter 7 discusses Sigstore, which WIA uses for signing conformance evidence; the same tooling can sign update manifests, but that is an implementation choice.
§7.1 requires TLS 1.3 for all cloud communication (TLS 1.3 is IETF RFC 8446), AES-256 for data at rest, role-based access control for the operator dashboard and audit logging of all API calls and operator actions. For the telemetry channel, three additions turn these requirements into a defensible design:
fleet/robots/{its own id}/state and subscribe only to its own command topics. This is what makes the topic identifier in 6.2.1 trustworthy.Delivery robots film public space. §7.2 requires blurring faces before video is uploaded to the cloud, collecting only necessary data, retention policies that auto-delete old telemetry (the standard gives 90 days as an example) and compliance with GDPR, CCPA and local privacy law. Two points need care in implementation.
The first is where blurring happens. “Before uploading” means on the robot, which requires on-board compute for face detection and a policy for what happens when detection fails: uploading an unblurred frame by default defeats the rule. Phase 1 already recommends sending detections and image URLs rather than raw frames; for most fleet functions the detection list is all the cloud needs.
The second is that retention has two clocks. Routine telemetry can be deleted on a short schedule such as the 90-day example. Audit logs, incident records and conformance evidence serve a different purpose and usually need to be kept longer. Phase 4 Annex E states that a seven-year window satisfies ISO/IEC 17065 audit expectations in most jurisdictions; that note is non-normative and gives no source, so do not rely on it. Set each retention period from the legal and contractual requirements that actually apply to your deployment, and keep personal data out of the long-retention store wherever possible.
§8.1 lists four fault-tolerance measures: multi-region deployment, real-time database replication, graceful degradation in which robots operate autonomously if the cloud is unreachable, and durable storage for in-flight messages. §8.2 gives a six-step recovery procedure: detection, failover, data synchronization, robot reconnection, validation and post-mortem.
The robot side of that procedure is where fleets most often fail in practice. When the cloud disappears, the Phase 3 communication-loss rule applies: after 60 seconds without cloud contact the robot continues its current task and logs locally. It should not accept a new task it cannot report on, and it must not depend on the cloud for any safety function. When the endpoint changes during failover, every robot will try to reconnect at once; exponential back-off with random jitter spreads that load so the new region is not knocked over by its own fleet. With persistent MQTT sessions (a fixed client ID and a non-clean session), the broker can hold QoS 1 messages addressed to a robot while it is away — provided the broker's own storage is replicated, which is what “message queue durability” in §8.1 asks for.
| Event | Robot behaviour | Cloud behaviour |
|---|---|---|
| Link lost, under 60 s | Continue normally, buffer telemetry | Mark robot stale after several missed intervals; do not reassign yet |
| Link lost, 60 s or more | Phase 3 rule: continue current task, log locally; accept no new work | Hold the robot's tasks; alert operators if a delivery deadline is at risk |
| Region failover | Reconnect to new endpoint with back-off and jitter | Promote replica, verify data consistency, accept reconnections |
| Reconnection | Upload buffered state labelled as backfill | Deduplicate, rebuild live view from the newest timestamps, validate fleet state before resuming dispatch |
Annex E also recommends a monthly error-budget summary covering p95 latency, error rate and violation hours. Recovery events are the main input to that report; Chapter 7 shows how it fits into the conformance evidence, together with the Phase 4 KPI targets.
The items below are the decisions this chapter has shown Phase 4 leaves open. Recording an answer to each in the deployment documentation is what turns the phase from a description into an integration that another vendor's robot can join.
| # | Decision | Where the standard stops |
|---|---|---|
| 1 | Broker product, TLS configuration, per-robot credentials and topic ACLs | Names MQTT/Kafka and TLS 1.3 only |
| 2 | Publish interval policy within 1–5 s, and event-driven extra messages | Gives the window, not the policy |
| 3 | Deduplication key and handling of out-of-order and backfilled messages | Implied by QoS 1, not stated |
| 4 | Assignment weights, battery reserve, capacity measure, units | Pseudocode without values |
| 5 | Auction deadlines, confirmation timeout, tie-break, message topics | Five steps, no timing |
| 6 | Coordination-zone leases, waiting positions, acquisition order | Token idea only |
| 7 | Station reservation expiry and end-of-charge signal | Operations named, semantics open |
| 8 | Maintenance alert schema and enums | One example, no schema |
| 9 | OTA signing format, install gate, A/B layout, canary criteria | Requires signing and rollback only |
| 10 | Retention periods for telemetry and for audit evidence, set separately | 90-day example; Annex E note is non-normative |
With these answers in place, the fleet has a complete loop: robots publish Phase 1 state over the Phase 4 channel, the cloud assigns and deconflicts work, charging and updates happen without interrupting deliveries, and the whole system degrades safely when the network does. Chapter 7 turns to proving it — the test vectors, evidence package and field metrics by which a deployment claims a WIA ROB-010 conformance tier.
← Chapter 5: Phase 3 Navigation Protocol — Planning, Traffic Rules and Emergency Response | Back to Index | Chapter 7: Testing, Conformance and Certification — Surface, Verified, Anchored →