Connect your controller
Subclassservo.RecoveryController with local acquisition, queue replacement, hardware writes and readiness checks.
Route policy rows through send_policy, recovery commands through send_recovery, and manual commands through send_operator.
These methods arbitrate ownership at dispatch; calling your hardware directly bypasses that protection.
Your capture_inputs returns servo.RecoveryObservation(inputs, captured_at_ns, ready).
Use the oldest required sample’s local monotonic acquisition timestamp.
ready covers all required sensors; validate_resume checks current readiness and first-action limits.
Choose max_observation_age_s for your controller.
Register the handler
Pass your controller, local recovery routine and async execution loop to this function.robot computer
registration.notify_starvation(queue=...).
Do not report initial readiness or deliberate pauses as starvation.
Run synchronous prediction calls on bounded workers so recovery callbacks remain responsive.
Resume explicitly
Returning from the handler leaves recovery in control.resume requires fresh observations and a new action chunk before transferring ownership.
Old queued or late predictions cannot regain authority.
A failed resume leaves recovery active; your code chooses whether to retry.
Use recovery.hold(reason) for manual intervention.
Only its token authorizes send_operator; automated recovery writes remain blocked while held.
Release the token with release_hold(token), then explicitly resume.
The robot’s watchdog owns physical behavior when commands stop.
This API does not choose a retract, torque or gripper policy.
Use it with your controller loop; a configured session refuses the separate session.run execution owner.
You now have
- Local recovery that works without cloud connectivity.
- Explicit handback with fresh inputs and exclusive action ownership.