Skip to main content
Launches a VR teleoperation session. On start it prints the robot’s hostname (.local) and local IP address. Enter either one in the VR app at axol.almond.bot to connect. Teleop runs on the real robot by default. Pass --sim to use the browser visualizer instead. On hardware, the axol-rt realtime core runs the arms at 240 Hz with the default impedance controller. With --axol.controller position it runs at 400 Hz, and each joint uses its motor’s firmware position loop (see controller in the robot config). The table below lists the common flags. Every field of the nested axol, teleop, kinematics, vr_server and cart configs is listed with its default in Teleoperation Config Parameters. See Command configuration for the syntax.
For a step-by-step walkthrough, including the VR controller layout, see the Teleoperation guide.
Before opening the VR app, accept the self-signed HTTPS certificate in the VR browser. Go to https://<hostname>.local:8000 or https://<local-ip>:8000 and proceed past the security warning.
Network tip: If VR tracking feels jittery or packets arrive in bursts, set these on your router or access point:
  • DTIM interval: 1
  • Beacon interval: 100 ms
  • WMM APSD (U-APSD): disabled
With these settings the access point stops holding packets between beacons, which delays VR traffic.
To check the real control loop rate while teleop runs, open the Diagnostics dashboard. Its CAN timing graph shows command and feedback rate, jitter, response latency and missed 240 Hz deadlines.

Engaging

With the default toggle scheme (--teleop.hold_to_engage false):
  • From rest, squeeze both grips to engage.
  • After that, each grip toggles its arm between tracking and frozen.
With --teleop.hold_to_engage true:
  • Each arm moves only while you hold its grip. Either grip alone engages its arm, including from rest.
  • Releasing a grip freezes that arm, pose and grasp, where it is.
  • After a forced disengage (a reset, a dropped link or a contact stop), release a held grip once before it engages again.
--teleop.reengage sets what happens when an arm re-engages after a freeze, a walk-away or being moved by hand:
  • clutch (default): the arm stays put, and your controller’s current pose becomes its new origin. You match the arm.
  • ramp: the arm eases out to where your controller is, using the mapping from its last engage. The arm matches you. --teleop.reengage_ramp_speed sets the pace (default 0.15 m/s), and --teleop.reengage_ramp_min_s sets the shortest ramp (default 0.75 s).
You can also switch it live with the headset’s Ramp button or the control panel’s Session settings card. A reset clears the saved mapping. Engaging in box mode ignores this setting. Leaving box mode in ramp blends both arms back to the mapping from before box mode. --teleop.absolute_mode true doesn’t select a Mantis source or its mount transform, so it is not a test of physical alignment. To check alignment, run collect-data --mantis.

Contact stops

Two torque watchdogs stop the arms when they hit something. Each compares every joint’s measured torque with the gravity model. When the difference stays above the limit, the move stops and the arms go limp in a gravity-compensation hold. Both work on hardware only.
  • Return to rest (--teleop.reset_torque_threshold, on by default): guards the startup move and every X reset. Free the arms by hand, then press X to plan the return from where they are.
  • Tracking (--teleop.teleop_torque_threshold, off by default): guards the arms while you drive them. A stop disengages tracking. Press X to return to rest, then engage again. The same setting applies to collect-data.
Raise a limit if normal moves trip it. Set it to 0 to turn the watchdog off.

Mantis grippers

axol teleop --mantis drives only the two handheld grippers, from the rig triggers. It doesn’t start tracking, the VR server, the tracker bridge, cameras or transforms. To record tracked Mantis data, use collect-data --mantis.
  • The grippers use the Mantis CAN channels saved in Mantis settings (default can_mantis_l and can_mantis_r).
  • Both triggers must be reading and released before the grippers turn on. Each gripper then opens fully to find its end stop.
  • If the trigger stream goes stale, the run stops.

Box mode settings

Box mode needs the parcel gripper (--axol.gripper parcel). With the parallel gripper, box mode and its settings don’t exist, and --teleop.box_mode is ignored with a warning. In box mode the grippers clamp a box between their flat faces, like two hands. One grip drives both arms as a pair, by position and by heading about the vertical. The other grip takes over the lead. While a grip leads, the thumbsticks set the grip width. Freeze the pair and the thumbsticks drive Jelly again (see Driving with the box). To switch box mode on or off during a session, press the headset’s Box button, click both thumbsticks together, or use the control panel’s Session settings card. The switch engages right away. The wrist and shoulder torque caps work on hardware only.

Camera streaming to the headset

With --cameras set, teleop opens the ZED cameras attached to the robot by serial number and streams them to the headset over WebRTC. All feeds show at once, and you can move and resize each one with the controllers. See the VR Interface guide for the layout.
  • Streaming needs pyzed (zed.install) and the GStreamer hardware encoder stack (gst.install). The hosted installer sets up both.
  • The headset stream runs at 30 fps. Cameras can capture faster for recording or policies.
  • Stereo ZED X cameras are detected from their serial number. A stereo overhead camera streams both eyes and shows each eye to its own lens. A stereo wrist camera streams one eye, like a mono camera. Use --camera_eyes to change this.
  • Without the GStreamer stack, teleop falls back to the ZED SDK.
  • If no hardware encoder is present, the video is encoded in software. Use --resolution SVGA in that case.
The video runs in a separate process, so it doesn’t slow the control loop. axol provision pins the Jetson’s encoder clocks to their maximum for low latency.

Jelly

When Axol is on Jelly (an omni-wheel base with a telescoping lift), you can drive it from the headset thumbsticks. The left stick moves, the right stick turns, and the stick clicks run the lift. For the full controls see the VR interface guide. Teleop finds Jelly from the attached CAN devices:
  • It drives the wheels when their interface (can_alm_axol_b) exists.
  • It runs the lift when its bus exists (can_alm_axol_c, or the shared wheel bus). If the lift bus is down at start, the lift is disabled with a warning and the wheels still drive.
  • can.setup and the control panel’s CAN discovery set these names. Teleop brings Jelly’s CAN up on start, so you don’t need can.enable.
To leave attached hardware off, pass --jelly.wheels false or --jelly.lift false (the control panel’s Jelly wheels and Jelly lift switches). Jelly motion is never recorded into a dataset, and a policy never drives it. --arms false drives only Jelly. Teleop doesn’t start the arms or open the Axol hub’s CAN bus, so the arms don’t need to be connected. Teleop does the same, with a warning, when the arms’ CAN interfaces are missing and Jelly’s are present.
This command takes its config through draccus. Field names use underscores, nested fields are separated by dots, None is null, and lists use [a,b,c]. See Command configuration.