From f001d06315a928463b44be3c8837ce73be7cfe49 Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Wed, 18 Feb 2026 22:14:02 -0600 Subject: [PATCH] Add connection status feedback via face LED and web badge - Robot face LED: red when VP not connected, blue when connected, off on shutdown. Uses AudioClient.LedControl() via DDS. - LED updates throttled to 1 Hz to avoid spamming. - Depends on televuer last_data_time timestamp for freshness detection. - Web page patch script updated with connection status badge (red/blue floating div) + unified pass-through patches. Co-Authored-By: Claude Opus 4.6 --- teleop/teleop_hand_and_arm.py | 39 +++++++++++++++++++++++++++++++++++ teleop/televuer | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/teleop/teleop_hand_and_arm.py b/teleop/teleop_hand_and_arm.py index 326cf78..2e3e2b2 100644 --- a/teleop/teleop_hand_and_arm.py +++ b/teleop/teleop_hand_and_arm.py @@ -174,6 +174,21 @@ if __name__ == '__main__': else: ChannelFactoryInitialize(0, networkInterface=args.network_interface) + # LED connection indicator (face RGB) + led_client = None + if not args.sim: + try: + from unitree_sdk2py.g1.audio.g1_audio_client import AudioClient + led_client = AudioClient() + led_client.SetTimeout(3.0) + led_client.Init() + led_client.LedControl(255, 0, 0) # Red = not connected + logger_mp.info("[LED] Face LED initialized (red = waiting for VP)") + except Exception as e: + logger_mp.warning(f"[LED] Face LED control unavailable: {e}") + led_is_blue = False + led_last_update = 0.0 + # ipc communication mode. client usage: see utils/ipc.py if args.ipc: ipc_server = IPC_Server(on_press=on_press,get_state=get_state) @@ -788,7 +803,24 @@ if __name__ == '__main__': else: recorder.add_item(colors=colors, depths=depths, states=states, actions=actions) + # --- LED connection status (throttled to ~1 Hz) --- current_time = time.time() + if led_client and (current_time - led_last_update > 1.0): + vp_connected = (current_time - tv_wrapper.tvuer.last_data_time) < 1.0 + if vp_connected and not led_is_blue: + try: + led_client.LedControl(0, 0, 255) # Blue = connected + led_is_blue = True + except: + pass + elif not vp_connected and led_is_blue: + try: + led_client.LedControl(255, 0, 0) # Red = disconnected + led_is_blue = False + except: + pass + led_last_update = current_time + time_elapsed = current_time - start_time sleep_time = max(0, (1 / args.frequency) - time_elapsed) time.sleep(sleep_time) @@ -824,6 +856,13 @@ if __name__ == '__main__': except Exception as e: logger_mp.error(f"Failed to close televuer wrapper: {e}") + if led_client: + try: + led_client.LedControl(0, 0, 0) # LED off on shutdown + logger_mp.info("[LED] Face LED off") + except: + pass + try: if not args.motion: pass diff --git a/teleop/televuer b/teleop/televuer index 59f8526..0ea96e5 160000 --- a/teleop/televuer +++ b/teleop/televuer @@ -1 +1 @@ -Subproject commit 59f8526ee8f4ebd86c9cf54ae4d85aceeba0e7f5 +Subproject commit 0ea96e5f51a1248036d902dcd9af2bb8a1eeebcb