Xarm-DataCollection/ufactory_lerobot/utils/utils.py
Vinman d959d82dbe refactor(teleop): 重命名 set_ctrl_status 为 set_teleop_enabled
启用时支持传入机械臂观测数据以同步初始位姿映射,
重构 Pika/UMI 遥操作内部状态管理。
2026-06-12 18:37:53 +08:00

75 lines
3.3 KiB
Python

import logging
import importlib
from lerobot.utils.control_utils import is_headless
# recursive call, inspired from gello_software:
def instantiate_from_dict(cfg, ignore_cameras=False):
"""Instantiate objects from configuration."""
if isinstance(cfg, dict) and "_target_" in cfg:
module_path, class_name = cfg["_target_"].rsplit(".", 1)
cls = getattr(importlib.import_module(module_path), class_name)
kwargs = {k: v for k, v in cfg.items() if k != "_target_"}
# pp_dict ={k: instantiate_from_dict(v, ignore_cameras) for k, v in kwargs.items()}
# print(pp_dict)
return cls(**{k: {} if ignore_cameras and k == 'cameras' else instantiate_from_dict(v, ignore_cameras) for k, v in kwargs.items()})
elif isinstance(cfg, dict):
return {k: {} if ignore_cameras and k == 'cameras' else instantiate_from_dict(v, ignore_cameras) for k, v in cfg.items()}
elif isinstance(cfg, list):
return [instantiate_from_dict(v, ignore_cameras) for v in cfg]
else:
return cfg
def init_keyboard_listener(events: dict = None, on_press: callable = None, on_release: callable = None):
"""
Initializes a non-blocking keyboard listener for real-time user interaction.
This function sets up a listener for specific keys (right arrow, left arrow, escape) to control
the program flow during execution, such as stopping recording or exiting loops. It gracefully
handles headless environments where keyboard listening is not possible.
Returns:
A tuple containing:
- The `pynput.keyboard.Listener` instance, or `None` if in a headless environment.
- A dictionary of event flags (e.g., `exit_early`) that are set by key presses.
"""
# Allow to exit early while recording an episode or resetting the environment,
# by tapping the right arrow key '->'. This might require a sudo permission
# to allow your terminal to monitor keyboard events.
if events is None:
events = {}
events["exit_early"] = False
events["rerecord_episode"] = False
events["stop_recording"] = False
if is_headless():
logging.warning(
"Headless environment detected. On-screen cameras display and keyboard inputs will not be available."
)
listener = None
return listener, events
# Only import pynput if not in a headless environment
from pynput import keyboard
if on_press is None:
def on_press(key):
try:
if key == keyboard.Key.right:
print("Right arrow key pressed. Exiting loop...")
events["exit_early"] = True
elif key == keyboard.Key.left:
print("Left arrow key pressed. Exiting loop and rerecord the last episode...")
events["rerecord_episode"] = True
events["exit_early"] = True
elif key == keyboard.Key.esc:
print("Escape key pressed. Stopping data recording...")
events["stop_recording"] = True
events["exit_early"] = True
except Exception as e:
print(f"Error handling key press: {e}")
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()
return listener, events