From 0f85cc5ff6d52b92d00d8da61a137e713df0c3b5 Mon Sep 17 00:00:00 2001 From: Martino Russi Date: Sat, 18 Jul 2026 19:03:14 +0200 Subject: [PATCH] fix(unitree_g1): unfreeze exo joysticks in onboard teleop client Without the robot->teleop feedback the normal loop provides, the RemoteController's wireless_active gate latched True after the first non-zero exo axis, skipping set_from_exo forever and freezing the sticks. Reset the latched axes each frame. Co-authored-by: Cursor --- src/lerobot/robots/unitree_g1/run_g1_teleop_client.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lerobot/robots/unitree_g1/run_g1_teleop_client.py b/src/lerobot/robots/unitree_g1/run_g1_teleop_client.py index 4855355dd..46f494ffb 100644 --- a/src/lerobot/robots/unitree_g1/run_g1_teleop_client.py +++ b/src/lerobot/robots/unitree_g1/run_g1_teleop_client.py @@ -90,11 +90,21 @@ def main() -> None: sock.connect(f"tcp://{args.robot_ip}:{args.action_port}") logger.info("Sending actions to %s:%d. Ctrl-C to stop.", args.robot_ip, args.action_port) + # The normal lerobot-teleoperate loop calls teleop.send_feedback(robot_obs) each + # iteration, which resets the RemoteController axes from the robot's (usually idle) + # wireless-remote bytes. That reset is what keeps `wireless_active` False so the exo + # thumb-sticks (set_from_exo) are read every frame. We have no robot feedback here, + # so without this reset the first non-zero exo axis latches `wireless_active` True + # and the sticks freeze. Reset the latched axes ourselves before every get_action. + rc = teleop.remote_controller + period = 1.0 / args.fps if args.fps > 0 else 0.0 n = 0 try: while True: t0 = time.time() + rc.lx = rc.ly = rc.rx = rc.ry = 0.0 + rc.button = [0] * 16 action = teleop.get_action() try: sock.send_json(_to_jsonable(action), zmq.NOBLOCK)