move gello control frequecy args to teleop
This commit is contained in:
parent
b2875851ae
commit
70b30fe307
@ -72,6 +72,7 @@ Predefined configs are provided under `config/`:
|
||||
- `teleop.joint_ids` / `teleop.joint_signs` — per-arm servo mapping and direction
|
||||
- `teleop.start_joints` — GELLO calibration reference, should match the xArm SDK initial point (degrees)
|
||||
- `teleop.gripper_id` — GELLO gripper servo ID (`8`; `-1` disables it)
|
||||
- `teleop.realtime_control_fps` — independent GELLO-to-xArm command loop rate; it is separate from `dataset.fps`
|
||||
- `dataset.root` / `dataset.repo_id` — where the dataset is stored
|
||||
- `dataset.single_task` — task description saved with each frame
|
||||
- `dataset.fps` / `episode_time_s` / `reset_time_s` — recording timing
|
||||
|
||||
@ -72,6 +72,7 @@ ls /dev/serial/by-id/
|
||||
- `teleop.joint_ids` / `teleop.joint_signs` — 各型号机械臂的舵机映射与方向
|
||||
- `teleop.start_joints` — GELLO 校准参考值(角度),应与 xArm SDK 初始点一致
|
||||
- `teleop.gripper_id` — GELLO 夹爪舵机 ID(`8`;`-1` 表示无夹爪)
|
||||
- `teleop.realtime_control_fps` — GELLO 到 xArm 的独立实时控制频率,与 `dataset.fps` 分开
|
||||
- `dataset.root` / `dataset.repo_id` — 数据集保存位置
|
||||
- `dataset.single_task` — 随每一帧保存的任务描述
|
||||
- `dataset.fps` / `episode_time_s` / `reset_time_s` — 录制时序参数
|
||||
|
||||
@ -10,6 +10,7 @@ robot:
|
||||
# make sure to edit with your correct configurations!
|
||||
teleop:
|
||||
type: uf::gello_teleop
|
||||
realtime_control_fps: 60
|
||||
port: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_FTAJZYC7-if00-port0"
|
||||
joint_ids: [1, 2, 4, 6, 7]
|
||||
joint_signs: [1, 1, -1, 1, 1]
|
||||
|
||||
@ -10,6 +10,7 @@ robot:
|
||||
# make sure to edit with your correct configurations!
|
||||
teleop:
|
||||
type: uf::gello_teleop
|
||||
realtime_control_fps: 60
|
||||
port: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_FTAJZYC7-if00-port0"
|
||||
joint_ids: [1, 2, 4, 5, 6, 7]
|
||||
joint_signs: [1, 1, -1, 1, 1, 1]
|
||||
|
||||
42
config/gello/xarm7_gello_cartesian_record_config.yaml
Normal file
42
config/gello/xarm7_gello_cartesian_record_config.yaml
Normal file
@ -0,0 +1,42 @@
|
||||
robot:
|
||||
type: uf::robot
|
||||
id: "uf_robot_cartesian"
|
||||
robot_dof: 7
|
||||
control_space: "cartesian"
|
||||
robot_ip: "192.168.1.245"
|
||||
gripper_type: 1
|
||||
max_linear_velocity: 200
|
||||
min_tcp_z_mm: -2.0
|
||||
gripper_error_log_path: "logs/xarm7_gripper_errors.log"
|
||||
cameras:
|
||||
camera:
|
||||
type: intelrealsense
|
||||
serial_number_or_name: "242622070583"
|
||||
width: 640
|
||||
height: 480
|
||||
fps: 30
|
||||
camera2:
|
||||
type: intelrealsense
|
||||
serial_number_or_name: "148522072685"
|
||||
width: 640
|
||||
height: 480
|
||||
fps: 30
|
||||
|
||||
teleop:
|
||||
type: uf::gello_teleop
|
||||
id: "gello_teleop"
|
||||
port: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_FTB9HYVD-if00-port0"
|
||||
joint_ids: [1, 2, 3, 4, 5, 6, 7]
|
||||
joint_signs: [1, 1, 1, 1, 1, 1, 1]
|
||||
gripper_id: 8
|
||||
gripper_open_deg: 198.28125
|
||||
gripper_close_deg: 155.75
|
||||
|
||||
dataset:
|
||||
root: "datasets/xarm7_gello_cartesian_datas"
|
||||
repo_id: "ufactory/xarm7_gello_cartesian_datas"
|
||||
single_task: "Pick up the purple grape and drop into the box on the left."
|
||||
fps: 60
|
||||
episode_time_s: 60
|
||||
reset_time_s: 20
|
||||
push_to_hub: False
|
||||
@ -13,10 +13,9 @@ robot:
|
||||
gripper_speed: 1500
|
||||
# Use the high-frequency servo interface for lower-latency GELLO tracking.
|
||||
joint_command_mode: 1
|
||||
realtime_control_fps: 60
|
||||
max_joint_velocity: 120
|
||||
# TCP z floor in the xArm base coordinate system (mm).
|
||||
min_tcp_z_mm: 70.0
|
||||
min_tcp_z_mm: -2.0
|
||||
# CPU-local FK/Jacobian projection keeps ServoJ free of synchronous SDK queries.
|
||||
tcp_z_guard_backend: "local_projection"
|
||||
tcp_z_soft_margin_mm: 5.0
|
||||
@ -43,6 +42,8 @@ robot:
|
||||
teleop:
|
||||
type: uf::gello_teleop
|
||||
id: "gello_teleop"
|
||||
# Independent GELLO -> xArm command loop; dataset.fps remains the recording rate.
|
||||
realtime_control_fps: 60
|
||||
port: "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_FTB9HYVD-if00-port0"
|
||||
joint_ids: [1, 2, 3, 4, 5, 6, 7]
|
||||
joint_signs: [1, 1, 1, 1, 1, 1, 1]
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
robot:
|
||||
control_space: "joint"
|
||||
joint_command_mode: 1
|
||||
realtime_control_fps: 60
|
||||
|
||||
min_tcp_z_mm: 70.0
|
||||
tcp_z_guard_backend: "local_projection"
|
||||
@ -31,6 +30,9 @@ robot:
|
||||
gripper_command_threshold: 0.01
|
||||
gripper_speed: 1500
|
||||
|
||||
teleop:
|
||||
realtime_control_fps: 60
|
||||
|
||||
dataset:
|
||||
fps: 30
|
||||
```
|
||||
|
||||
@ -26,7 +26,6 @@ class UFRobotConfig(RobotConfig):
|
||||
manual_gripper_speed: float = 0.5 # normalized gripper position per second in manual mode
|
||||
teach_sensitivity: int | None = None # xArm teaching sensitivity, valid range: 1-5
|
||||
joint_command_mode: int = 6 # 1: servo-angle-j, 6: online trajectory planning
|
||||
realtime_control_fps: int = 60 # independent of camera/dataset sampling fps
|
||||
# start_joints and start_tcp_pose are intentionally disabled.
|
||||
# Reset uses the xArm SDK initial_point instead of configuration poses.
|
||||
max_joint_velocity: int = 90 # °/s, only effective in joint control mode
|
||||
@ -62,8 +61,6 @@ class UFRobotConfig(RobotConfig):
|
||||
raise ValueError("gripper_command_interval_s must be finite and non-negative")
|
||||
if self.control_space == "joint" and self.joint_command_mode not in (1, 6):
|
||||
raise ValueError("joint_command_mode must be 1 or 6 for joint control")
|
||||
if self.realtime_control_fps <= 0:
|
||||
raise ValueError("realtime_control_fps must be positive")
|
||||
if self.min_tcp_z_mm is not None and not math.isfinite(self.min_tcp_z_mm):
|
||||
raise ValueError("min_tcp_z_mm must be finite when provided")
|
||||
if (
|
||||
|
||||
@ -380,7 +380,7 @@ def record_loop(
|
||||
teleop=teleop,
|
||||
teleop_action_processor=teleop_action_processor,
|
||||
robot_action_processor=robot_action_processor,
|
||||
fps=getattr(robot.config, "realtime_control_fps", fps),
|
||||
fps=int(teleop.config.realtime_control_fps),
|
||||
initial_observation=last_robot_cmd,
|
||||
)
|
||||
realtime_controller.start()
|
||||
|
||||
@ -288,6 +288,7 @@ def teleop_loop(cfg: TeleopConfig):
|
||||
experiment_start_t = None
|
||||
previous_command_t = None
|
||||
realtime_controller = None
|
||||
realtime_control_fps = int(teleop.config.realtime_control_fps)
|
||||
|
||||
def start_realtime_controller():
|
||||
nonlocal realtime_controller
|
||||
@ -303,7 +304,7 @@ def teleop_loop(cfg: TeleopConfig):
|
||||
teleop,
|
||||
teleop_action_processor,
|
||||
robot_action_processor,
|
||||
cfg.fps,
|
||||
realtime_control_fps,
|
||||
obs,
|
||||
)
|
||||
realtime_controller.start()
|
||||
@ -410,7 +411,9 @@ def teleop_loop(cfg: TeleopConfig):
|
||||
print("\n********** Teleop Control Loop Exit **********")
|
||||
stop_realtime_controller()
|
||||
if latency_samples:
|
||||
output_path = _write_guard_latency_timings(latency_samples, cfg.timing_log_dir, cfg.fps)
|
||||
output_path = _write_guard_latency_timings(
|
||||
latency_samples, cfg.timing_log_dir, realtime_control_fps
|
||||
)
|
||||
print(f"Guard latency timing log: {output_path}")
|
||||
cleanup_connections()
|
||||
atexit.unregister(cleanup_connections)
|
||||
|
||||
@ -8,6 +8,8 @@ from lerobot.teleoperators import TeleoperatorConfig
|
||||
@TeleoperatorConfig.register_subclass("uf::gello_teleop")
|
||||
@dataclass
|
||||
class GelloTeleopConfig(TeleoperatorConfig):
|
||||
# Frequency of the independent GELLO -> xArm realtime control loop.
|
||||
realtime_control_fps: int = 60
|
||||
# Port to connect to the gello dummy arm
|
||||
port: str = "/dev/serial/by-id/usb-FTDI_USB__-__Serial_Converter_FTAJZYC7-if00-port0"
|
||||
|
||||
@ -27,6 +29,8 @@ class GelloTeleopConfig(TeleoperatorConfig):
|
||||
|
||||
def __post_init__(self):
|
||||
self.id = 'gello_teleop' if self.id is None else self.id
|
||||
if self.realtime_control_fps <= 0:
|
||||
raise ValueError("realtime_control_fps must be positive")
|
||||
if len(self.joint_ids) != len(self.joint_signs):
|
||||
raise ValueError("joint_ids and joint_signs must have the same length")
|
||||
if len(self.joint_ids) != len(self.start_joints):
|
||||
|
||||
@ -2,6 +2,9 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from lerobot_robot_ufactory.teleoperators.gello_teleop.gello_teleop_config import (
|
||||
GelloTeleopConfig,
|
||||
)
|
||||
from lerobot_robot_ufactory.utils.realtime_teleop import RealtimeTeleopController
|
||||
|
||||
|
||||
@ -27,6 +30,15 @@ def identity_action_processor(value):
|
||||
return value[0]
|
||||
|
||||
|
||||
def test_gello_realtime_control_fps_defaults_to_60():
|
||||
assert GelloTeleopConfig().realtime_control_fps == 60
|
||||
|
||||
|
||||
def test_gello_realtime_control_fps_must_be_positive():
|
||||
with pytest.raises(ValueError, match="realtime_control_fps"):
|
||||
GelloTeleopConfig(realtime_control_fps=0)
|
||||
|
||||
|
||||
def test_realtime_controller_sends_without_waiting_for_observation_owner():
|
||||
robot = FakeRobot()
|
||||
controller = RealtimeTeleopController(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user