Skip to main content
Install the package with uv sync (see Installation), then import from its submodules, such as almond_axol.robot and almond_axol.teleop. The Axol SDK is organized into focused modules:
The browser front-ends are outside the Python package, in web/. The VR teleop interface and the web control panel are both built to web/app/dist and served by axol serve. End-to-end data flow for teleoperation:
End-to-end data flow for LeRobot data collection:

Async context managers

Axol, Sim, VRTeleop and VRServer open and close hardware resources in __aenter__ and __aexit__. Always use them with async with.

Joint arrays

Every method that reads or writes joint state uses an np.ndarray of shape (8,) in Joint enum order: SHOULDER_1, SHOULDER_2, SHOULDER_3, ELBOW, WRIST_1, WRIST_2, WRIST_3, GRIPPER. Arm joints are in radians. The gripper runs from 0.0 (closed) to 1.0 (fully open).

Telemetry vs. one-shot reads

.positions and .torques are cached properties that don’t block. Read them in a tight control loop without await. While the robot is enabled, the realtime core keeps these caches filled, so you don’t need to start telemetry. On a robot that is connected but not enabled, start_telemetry(hz) starts a background polling loop that fills the same caches. The cache is empty until the first reply arrives, and a MyActuator motor rebooting after a control-mode change can take a moment to answer. Call await wait_for_telemetry() once after start_telemetry(), before the first .positions read. Without the core, direct calls such as await get_positions() send individual CAN reads. They suit diagnostics but are too slow for real-time control.