星海图A1Z
本章节介绍如何将Galaxea A1Z六轴机械臂(含G1Z夹爪)通过LeRobot插件路径经r2c_sdk端到端接入CloudRobo平台:上位机以r2c_sdk.cloudroboclient直驱硬件(观测上行、动作下行),云端策略服务订阅观测并下发推理动作,同时配合a1z-teleop项目完成遥操作数据采集,数据可直接用于LeRobot训练。与docs/a1z_cloudrobo_接入指南.md(hardware.type: a1z,A1Z SDK raw 直驱适配器)不同,本文基于通用LeRobot硬件适配器(hardware.type: lerobot)+ 第三方机器人插件lerobot_robot_galaxea_a1z(注册名 galaxea_a1z_follower)。该插件与数采项目共用同一份实现与标定文件,保证数采、训练、云端推理三者的动作坐标系与相机特征完全一致。
关键区别:插件以pip包形式安装,LeRobot 0.6.1的register_third_party_plugins()会自动发现并注册robot.type。
一、依赖组件版本速查表(务必核对)
| 组件 | 版本要求 | 说明 |
|---|---|---|
| 操作系统 | Ubuntu 22.04/24.04 | 内核 ≥ 6.8.0-124(SocketCAN 兼容),否则按 Galaxea 官方指引打补丁。 |
| Miniforge | 最新版(conda-forge) | 安装至~/miniforge3,自带mamba。 |
| Python | 3.12 | conda 环境lerobot061与 2c_sdk(requires-python >=3.12)一致。 |
| LeRobot | 0.6.1 | pip install lerobot==0.6.1;插件按0.6.x API编写。 |
| PyTorch | 随LeRobot安装(PyPI Linux wheel 自带 CUDA 12.x) | 如果GPU驱动仅支持旧CUDA,先按对应index装 torch再装lerobot。 |
| ffmpeg | conda-forge版 | LeRobot视频解码(TorchCodec)需要。 |
| A1Z SDK | GALAXEA-A1Z(包名 a1z) | 官方A1Z Python SDK,pip install -e 安装。 |
| a1z-teleop | git@github.com:xxxxxx/a1z-teleop.git | 数采工程,含从臂插件lerobot_robot_galaxea_a1z与主臂插件 lerobot_teleoperator_stararm102。 |
| hw-r2c-sdk | 最新版本 | Python ≥3.12;eclipse-zenoh 1.9.0、protobuf 7.35.0。 |
| USB-CANFD 适配器 | HHS Pro-II(a8fa:8598) | gs_usb内核驱动,1Mbps。 |
不要把LeRobot装在Python 3.13环境,也不要混用0.4.x/0.5.x时代的“拷贝插件进lerobot源码树”安装方式,0.6.1 的插件机制完全不同。
二、硬件清单与接线安装
| 硬件 | 型号/规格 | 用途 | 关键参数 |
|---|---|---|---|
| 机械臂 | Galaxea A1Z | 6自由度协作臂 | CAN 通信(CAN ID 1–6),MIT 力控电机,无制动器 |
| 夹爪 | Galaxea G1Z | 末端执行器 | CAN ID 7,力位混合控制,SDK 原生 Gripper类 |
| USB-CANFD 适配器 | HHS Pro-II(a8fa:8598) | 上位机与机械臂CAN通信 | SocketCAN / gs_usb 驱动,1 Mbps |
| 转接盒 | 随附 | 电源+CAN信号转接 | - |
| 电源适配器 | 随附(24V) | 机械臂供电 | 含电路开关按键 |
| G 夹 ×2 | 随附 | 机械臂固定于桌面 | - |
| 相机 ×2(可选) | USB UVC | 腕部 + 头部/全局视角 | 推荐 640×480@30(腕部)、960×540@30(全局) |
| 上位机 | Linux PC | 运行r2c_sdk | Python 3.12,内核 ≥6.8.0-124 |
| 主臂(仅数采) | Star-Arm-102 | 遥操作主臂 | 7 个 Fashionstar UART 伺服,/dev/ttyUSB0,12V 10A |
开机顺序(重要)
- 插USB-CANFD适配器。
- 初始化 CAN 总线。
- 从臂上电(打开电源开关,等待1~2秒自检)。
- 数采场景最后给主臂(Star-Arm-102)上电。
安全警告:
- A1Z关节电机无制动器,断电后机械臂会因重力下坠。
- 操作时保持工作空间清空;首次真实控制时人站在工作空间外、手靠近电源开关。
三、软件环境安装(安装Miniforge + LeRobot + r2c_sdk)
需要安装Miniforge、LeRobot、r2c_sdk。
安装Miniforge
- 执行如下命令,检查系统信息。
uname -r # 应 ≥ 6.8.0-124;低于此版本可能导致 CAN 通信异常(电机使能无反馈) python3 --version
- 执行如下命令,安装Miniforge。
wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" bash Miniforge3-$(uname)-$(uname -m).sh # 默认安装到 ~/miniforge3 # 安装脚本最后选择 yes 执行 conda init,然后重新打开终端 conda --version
- 执行以下命令,创建conda环境lerobot061(Python 3.12)。
conda create -y -n lerobot061 python=3.12 conda activate lerobot061 python -V # 应为 Python 3.12.x
conda activate lerobot061 # 视频解码依赖(TorchCodec 需要 ffmpeg) conda install ffmpeg -c conda-forge # LeRobot 0.6.1(PyPI Linux wheel 自动携带 CUDA 12.x 版 torch) pip install lerobot==0.6.1 # 验证版本(务必是 0.6.x) python -c "import lerobot; print(lerobot.__version__)" # 应输出 0.6.1
- 如果GPU驱动较旧(仅支持CUDA 11.x),执行以下命令先安装匹配的torch再安装lerobot。
pip install torch --index-url https://download.pytorch.org/whl/cu118。
- 编译报错时,执行以下命令补安装。
sudo apt-get install cmake build-essential python3-dev pkg-config libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libswresample-dev libavfilter-dev。
- 如果GPU驱动较旧(仅支持CUDA 11.x),执行以下命令先安装匹配的torch再安装lerobot。
安装A1Z SDK与LeRobot 插件(来自 a1z-teleop 工程)
a1z-teleop数采工程(GitHub:git@github.com:xxxxxx/a1z-teleop.git)同时提供从臂插件lerobot_robot_galaxea_a1z(注册名 galaxea_a1z_follower)与主臂插件lerobot_teleoperator_stararm102。
- 执行以下命令,云端接入只使用从臂插件,执行setup.sh脚本会一并安装,无需额外操作。
cd ~/project git clone git@github.com:xxxxxx/a1z-teleop.git cd a1z-teleop # 自动激活 lerobot061,安装 A1Z SDK + 主/从臂插件,并运行安装校验 # A1Z SDK 路径按实际指定(官方 GALAXEA-A1Z 仓库,包名 a1z) A1Z_SDK=/path/to/GALAXEA-A1Z bash setup.sh
- 执行setup.sh脚本,完成以下步骤(可重复执行)。
- 校验当前环境为lerobot061且LeRobot版本为0.6.x。
- pip install -e $A1Z_SDK:A1Z SDK(包名a1z,提供CAN 驱动/运动学/动力学)。
- pip install fashionstar_uart_sdk pyserial:主臂UART伺服SDK(数采用)。
- pip install -e plugins/teleoperator-stararm102:主臂插件(数采用)。
- pip install -e plugins/robot-galaxea-a1z :从臂插件(云端接入用)。
- 自动运行 scripts/verify_install.py 校验导入、ChoiceRegistry注册与CLI实例化路径。
- 插件不修改lerobot源码树:pip包名以lerobot_robot_ 开头即会被LeRobot 0.6.1的register_third_party_plugins() 自动发现,通过@RobotConfig.register_subclass("galaxea_a1z_follower") 注册robot.type。
安装r2c_sdk到lerobot061环境
机器人侧必须让r2c_sdk与LeRobot运行在同一个Python 环境里,hardware.type: lerobot的适配器在运行时需要 import lerobot、draccus并加载第三方插件。因此将r2c_sdk以editable方式装入lerobot061。
conda activate lerobot061
cd /path/to/r2c_sdk_python
pip install -e .
# 依赖自动安装:eclipse-zenoh==1.9.0、protobuf==7.35.1、opencv-python-headless 等
# lerobot / draccus 由 lerobot061 环境已提供,无需重复安装
python -c "from r2c_sdk import ClientConfig, SyncRobotClient; print('r2c_sdk OK')"
r2c_sdk要求Python ≥3.12(requires-python = ">=3.12"),这是必须用Python 3.12创建环境的原因,不要放宽。
四、CAN总线初始化与硬件链路验证
- 每次开机后执行一次(需sudo),加载gs_usb内核模块(内核缺失时自动insmod预编译gs_usb.ko),把HHS适配器(a8fa:8598)绑定到gs_usb,自动定位USB CAN接口(不一定叫can0,以脚本输出为准),以1 Mbps启动。
cd ~/project/a1z-teleop sudo bash setup_follower_can.sh
- 执行以下命令,验证硬件链路。
# ① 接口状态 ip -d link show can0 # 应显示 can state ERROR-ACTIVE, bitrate 1000000 # ② 给机械臂上电后扫描在线 CAN ID(1-6 = 手臂电机, 7 = 夹爪) cd ~/project/a1z-teleop python scripts/scan_can_ids.py can0 # ③ 可选:监听 CAN 帧 candump can0
接口名不是can0时:所有启动命令均可用CAN=canX环境变量覆盖,机器人配置中的 hardware.config.robot.can_channel也要改成实际接口名。
五、机械臂标定
标定是关键前置步骤:记录从臂零位 home_rad、各关节行程范围range_min_rad/range_max_rad 与夹爪行程 grip_min_norm/grip_max_norm。
交互式标定(首次使用必须)
conda activate lerobot061
cd ~/project/a1z-teleop
# 只标定从臂(云端接入只需从臂;主臂联标见 §10.2)
lerobot-calibrate \
--robot.type=galaxea_a1z_follower \
--robot.can_channel=can0 \
--robot.id=follower_a1z 标定流程(交互式,按Enter推进):
- 从臂进入柔顺模式(kp=0,可用手推动)。
- ① 零位:手动把从臂推到零位姿态(推荐自然操作姿态:臂前伸、肘微弯、夹爪半开),扶稳后按 Enter —— 记录 home_rad。
- ② 限位:按Enter开始,把每个关节缓慢转到两端极限来回扫一遍,扫完按Enter,记录range_min_rad / range_max_rad(与 SDK 硬件限位取交集)。
- ③ 夹爪:按Enter开始,把夹爪【完全张开】和【完全闭合】各做一次,按Enter,记录 grip_min_norm / grip_max_norm。
标定文件位置
~/.cache/huggingface/lerobot/calibration/robots/galaxea_a1z_follower/follower_a1z.json
文件包含home_rad、range_min_rad、range_max_rad、grip_min_norm、grip_max_norm五个字段。机器人配置中robot.id: follower_a1z与robot.calibration_dir: null(默认 HF 缓存目录)即指向此文件。
云端无人值守运行要点
- 云端/无人值守部署必须提前标定好,且配置中显式runtime.robot_connect.calibrate: false,否则robot.connect() 检测到缺标定文件时会进入交互式input()标定流程并卡死。
- 采集与推理同机时标定文件天然共享,无需重复标定;换臂或零位漂移后需重标。
- teleop_input: rad(云端推理模式)下数学上不依赖home_rad,仅钳到硬件限位,但return_to_zero_on_exit回零仍依赖标定,建议始终保留标定文件。
六、机器人配置文件详解
以config/robot_a1z_lerobot_v2_config.yaml为基准(v2相对v1的关键变更已写在文件头部注释中)。以下逐段说明。
runtime运行参数
runtime:
publish_hz: 15.0 # 观测发布/动作执行频率 (Hz),建议 10–30
max_duration_s: 0.0 # 0 = 一直运行,Ctrl+C 停止
dry_run: false # true = 只发观测不执行动作(安全调试)
action_response_timeout_s: 5.0 # 发布观测后等待 action 超时 (秒)
max_enqueue_actions_per_chunk: -1 # 每次 chunk 最多入队步数,-1 = 全部
enable_action_chunk_alignment: false
publish_trigger_threshold: 0
skip_initial_observations: 1 # 启动时跳过首帧观测,让动作队列预填充
async_request: {enabled: false} # 异步请求融合(默认关闭)
keyboard_control: {enabled: true} # 键盘控制(空格/暂停, h/回home, e/退出) - 未写 heartbeat 段时心跳默认开启(每 5 s 上报 status: ONLINE, mode: AUTO到 .../state/heartbeats),CloudRobo 平台据此判断设备在线;可按需显式配置heartbeat: {enabled: true, interval_ms: 1000, status: "ONLINE", mode: "AUTO"}。
- 首次接入务必先 dry_run: true 验证数据流,确认无误后再改回 false。
hardware:通用LeRobot适配器
hardware:
type: "lerobot" # r2c_sdk 内置通用适配器 (entry_point 名)
config:
runtime:
robot_connect:
calibrate: false # 无人值守必须 false(需已提前标定,见 §6.3)
robot:
type: galaxea_a1z_follower # 插件注册名
id: follower_a1z # 标定文件名 = calibration_dir/{id}.json
calibration_dir: null # null = 默认 HF 缓存目录
can_channel: can0 # 按 setup_follower_can.sh 实际输出修改
gravity_comp_factor: 1.0 # 重力补偿 (0=关, 1=全补偿)
control_freq_hz: 150 # 150 而非 250:降低 gs_usb CAN 负载
teleop_input: rad # 云端动作 = 绝对弧度,钳到硬件限位
joint_sign: [1,1,1,1,1,1] # 仅 leader_deg 模式生效;rad 模式不使用
scale: 1.0 # 仅 leader_deg 模式生效
max_step_rad: 0.06 # 每次 setpoint 变化硬上限 (rad)
max_joint_vel_deg_s: 50.0 # 最大关节速度 (deg/s)
max_joint_travel_deg: null # 相对零位 ±N° 软限位;null = 仅标定范围
return_to_zero_on_exit: true # 退出时平滑回零
return_speed_deg_s: 25.0
enable_gripper: true
gripper_sign: 1 # ★ 必须 +1,见下方说明
# 以下为独立 MotorB 夹爪驱动遗留参数,SDK 原生夹爪激活时不生效
gripper_can_id: 7
gripper_kp: 15.0
gripper_kd: 0.4
gripper_max_step_rad: 0.4
gripper_margin: 0.10
cameras:
cam_wrist: # 腕部相机(键名与 ACT 数据集 observation.images.* 一致)
type: opencv
index_or_path: 4 # 对应 /dev/video4,建议改用设备路径防漂移
width: 640
height: 480
fps: 30
cam_external: # 头部/全局相机
type: opencv
index_or_path: 13 # 对应 /dev/video13(RealSense 515 RGB 最低原生档)
width: 960
height: 540
fps: 30
commands:
go_home:
type: go_home
joint_names: [joint_1, joint_2, joint_3, joint_4, joint_5, joint_6]
joints: [...] # 6 个绝对关节角 (rad),取自 follower_a1z.json 的 home_rad
gripper: open 关键说明:
- gripper_sign: +1必须保持:SDK原生Gripper约定0=闭合,1=张开;插件配置默认 -1 是独立 MotorB 驱动时代的遗留值。若此处用 -1,云端推理的夹爪开合方向会与训练数据相反。
- 相机键名cam_wrist / cam_external必须与训练数据集的observation.images.cam_wrist / observation.images.cam_external完全一致,否则策略服务(config/cloud_a1z_act_config.yaml)的特征对齐会失败。
- /dev/videoN编号随重启漂移,推荐使用设备路径index_or_path: /dev/video13 或/dev/v4l/by-id/...稳定路径。
- go_home 只支持 joints(list + joint_names 或 dict),不支持pose_euler/pose_quat(LeRobot无IK)。
device_to_r2c:设备观测数据到R2C上行
A1Z get_observation() 输出键:joint_1..joint_6(rad)、gripper(归一化:0=闭合;1=张开)、相机名(RGB ndarray)。
device_to_r2c:
task: A1Z arm teleoperation
image_encoding: jpeg
mappings:
- target_key: "joint_states.names"
default: ["arm_joint1", ..., "arm_joint6", "gripper"]
- target_key: "joint_states.position" # [j1..j6 (rad), gripper (0~1)]
source_paths: ["joint_1", "joint_2", "joint_3", "joint_4", "joint_5", "joint_6", "gripper"]
- target_key: "images.color.front" # R2C 上行通道名
source_path: "cam_external"
transforms: [ndarray_to_jpeg]
- target_key: "images.color.wrist"
source_path: "cam_wrist"
transforms: [ndarray_to_jpeg] 注意区分两层命名:设备键名cam_external/cam_wrist(对齐训练数据集特征),R2C上行通道名images.color.front/images.color.wrist。
r2c_to_device:云端动作到设备指令
r2c_to_device:
mappings:
- target: "joint_1" # 6 个关节:source_index 0..5
source: "joint_states.position"
source_index: 0
required: true
# ... joint_2 .. joint_6 依次 source_index 1..5
- target: "gripper" # 夹爪:source_index 6
source: "joint_states.position"
source_index: 6
required: false # 云端只发 6 关节时夹爪保持当前位置 云端joint_states.position为7元素list:[j1..j6 (rad), gripper (0~1)]。teleop_input: rad模式下插件直接使用绝对弧度,与 gripper_sign: +1 配合,开合方向与训练数据一致。
七、执行r2c_sdk CLI(cloudroboclient)
执行r2c_sdk CLI(cloudroboclient)测试相关配置是否能正常连接机器人。
dry_run冒烟测试(不执行动作)
conda activate lerobot061 cd /path/to/r2c_sdk_python python -m r2c_sdk.cloudroboclient \ --robot-config config/robot_a1z_lerobot_v2_config.yaml \ --bundle config/配置文件名.zip \ --log-level DEBUG \ --duration 30
此时将robot_a1z_lerobot_v2_config.yaml 中的runtime.dry_run临时改为true。
预期日志:插件注册成功、RobotConfig 解码成功、观测正常发布、动作以[DRY_RUN]打印但不执行。
真实硬件启动
# 前置:CAN 已初始化(§5)、机械臂已上电、标定已完成(§6) # 将 dry_run 改回 false 后: python -m r2c_sdk.cloudroboclient \ --robot-config config/robot_a1z_lerobot_v2_config.yaml \ --bundle config/配置文件名.zip \ --log-level INFO \ --log-file /tmp/a1z_r2c.log
启动后预期日志:
Creating new robot instance from adapter config. Using robot config decoder: _default_robot_config_decoder Building robot instance via lerobot.robots.make_robot_from_config. Adapter connected successfully. Heartbeat auto publish started (interval_ms=5000, ...)
此时机械臂进入位置保持模式(重力补偿 + PD),锁定在当前姿态。
(可选)观测录制
python -m r2c_sdk.cloudroboclient \ --bundle config/配置文件名.zip \ --robot-config config/robot_a1z_lerobot_v2_config.yaml \ --record recordings/a1z_demo.r2cr
键盘控制
| 按键 | 功能 | 条件 |
|---|---|---|
| Space键 | 暂停/恢复。 | 任意时刻。 |
| h键 | 回Home位(执行go_home命令) | 暂停时。 |
| q键 | 优雅退出(回 Home > 断开连接 > 退出) | 暂停时。 |
| Ctrl+C键 | 强制终止(退出时按配置平滑回零) | 任意时刻。 |
键盘控制在非TTY终端(部分IDE内嵌终端)可能不响应,请在真实终端运行。
八、接入CloudRobo平台
参照如下步骤接入接入CloudRobo平台。
连接配置(三种方式)
- 方式一:ClientConfig YAML(推荐,便于版本管理)
config/client_config.yaml:
project_id: "<CloudRobo 平台分配的项目 ID>" device_id: "<设备 ID,项目内唯一>" client_id: "a1z-001" endpoints: ["tcp/<平台 Zenoh Router 地址>:7447"] # 由平台/管理员提供 mode: "client" # client = 仅经 Router 转发;peer = 支持 P2P 直连 protocol: "zenoh"
python -m r2c_sdk.cloudroboclient \ --client-config config/client_config.yaml \ --robot-config config/robot_a1z_lerobot_v2_config.yaml
- 方式二:显式CLI参数
python -m r2c_sdk.cloudroboclient \ --project-id "<project-id>" \ --device-id "<device-id>" \ --endpoints "tcp/<router-host>:7447" \ --mode client \ --robot-config config/robot_a1z_lerobot_v2_config.yaml
- 方式三:Bundle凭证包(生产环境推荐,含project_id、endpoints、TLS证书)
python -m r2c_sdk.cloudroboclient \ --bundle /path/to/credential_bundle.zip \ --robot-config config/robot_a1z_lerobot_v2_config.yaml
--bundle优先级最高;包含TLS证书时可用--private-key-password / --private-key-password-env / --prompt-password提供私钥密码。
平台侧验证
- 设备在线:CloudRobo 平台控制台应能看到设备在线(依赖心跳.../state/heartbeats,默认 5 s 一次,可在 config 中调快)。
- 观测上行:平台端能看到 .../inference/observations 的关节状态与两路图像。
- 动作闭环:策略服务启动后,动作经 .../inference/actions 下发,机械臂开始执行推理轨迹(日志中每步动作 send_action 有 DEBUG 记录)。
- 弱网/大模型场景:把 runtime.action_response_timeout_s 调到 ≥30 s,避免超时重发风暴。
九、数采安装与配置(a1z-teleop)
数据采集基于 a1z-teleop 工程(LeRobot 0.6.1 遥操作方案,GitHub:git@github.com:xxxxxx/a1z-teleop.git):用 Star-Arm-102 主臂(Leader,UART 伺服)驱动作 A1Z 从臂(Follower,CAN 电机),数据以LeRobot v3.0 格式(parquet + 视频)落盘,可直接 lerobot_train 训练。
数采硬件与权限
- 主臂Star-Arm-102:USB(CH340,/dev/ttyUSB0),12V 10A供电;
- 一次性安装串口udev规则(否则每次插拔后权限变回 root:dialout):
sudo bash ~/project/a1z-teleop/setup_leader_uart.sh
主从臂联合标定(首次使用必须)
cd ~/project/a1z-teleop bash calibrate.sh # LEADER_PORT=/dev/ttyUSB1 CAN=can1 bash calibrate.sh 可覆盖端口
依次完成:
- 从臂标定。
- 主臂标定:握着主臂摆出与从臂零位相同的姿态扶稳按 Enter记录homing_offset_deg,再逐关节扫限位。
标定文件:
~/.cache/huggingface/lerobot/calibration/robots/galaxea_a1z_follower/follower_a1z.json # 从臂 ~/.cache/huggingface/lerobot/calibration/teleoperators/stararm102_leader/leader1.json # 主臂
实时遥操作验证
bash scripts/teleop.sh # 更保守速度: bash scripts/teleop.sh --robot.max_joint_vel_deg_s=20 # Ctrl-C 停止,从臂自动回零
先用python scripts/test_teleop.py --dry-run检查各关节方向(观察 "target" 列),
方向反了用--flip N反转并同步到采集命令的 joint_sign。
数据采集(推荐 absolute_rad 模式)
cd ~/project/a1z-teleop
REPO_ID=my_user/my_dataset TASK="pick and place" bash scripts/record.sh \
--teleop.output_mode=absolute_rad \
--teleop.joint_sign='[-1, 1, 1, 1, -1, -1]' \
--teleop.gripper_sign=1 \
--robot.teleop_input=rad \
--robot.gripper_sign=1 \
--robot.cameras='{cam_external: {type: opencv, index_or_path: /dev/video13, width: 960, height: 540, fps: 30},
cam_wrist: {type: opencv, index_or_path: /dev/video4, width: 640, height: 480, fps: 30}}' \
--dataset.episode_time_s=300 --dataset.reset_time_s=5 --dataset.num_episodes=100 - 环境变量:REPO_ID(数据集名)、TASK(任务描述)、EPISODES(默认 10)。
- 操作键:→(右方向键) 结束当前 episode,←(左方向键) 重录上一个episode,Esc停止采集。
- 相机键名 cam_external/cam_wrist 与云端推理配置一致;/dev/video13(RealSense 515 RGB)最低原生档为 960×540(无 640×480 模式),比 1280×720 少约 44% 像素,降低 ACT 训练显存压力。
- 数据保存在本地 ~/.cache/huggingface/lerobot/<repo_id>/;加 --dataset.push_to_hub=true可上传Hub。
- 续录已有数据集:追加--resume=true。
为什么推荐absolute_rad:
- action 与 observation.state同坐标系同单位(绝对弧度),策略可利用"恒等先验"(action ≈ 当前状态即保持不动),冷启动稳定、收敛快。
- 推理侧 teleop_input="rad" 不依赖标定零位,换臂/零位漂移不破坏动作基准。
- 数据自包含可移植,与主流开源数据集惯例一致。
前提(务必确认):采集前必须完成从臂标定,主臂absolute_rad输出需要读follower_a1z.json的home_rad,文件缺失时只警告并静默退化为相对弧度,录出的数据坐标系错误。joint_sign也必须先用 test_teleop.py --dry-run验证。
数据集结构与训练
~/.cache/huggingface/lerobot/<repo_id>/ ├── meta/ # info.json (v3.0, fps, 特征定义)、episodes/、tasks.jsonl、stats.json ├── data/ # parquet 帧数据 └── videos/ # 视频帧
特征:observation.state(7维:joint_1..joint_6弧度+gripper 归一化)、
action(absolute_rad模式下同为弧度)、observation.images.*。
ACT训练示例:
conda activate lerobot061
cd ~/project/a1z-teleop
lerobot-train \
--policy.type=act \
--policy.push_to_hub=false \
--dataset.repo_id=<repo_id> \
--output_dir=outputs/train \
--job_name=act_a1z \
--steps=100000 --batch_size=16 --num_workers=8 \
--save_freq=20000 --eval_steps=10000 \
--wandb.enable=false 数采到云端推理衔接要点
| 要点 | 数采(record.sh) | 云端推理(v2 config + cloud config) |
|---|---|---|
| 动作坐标系 | absolute_rad + teleop_input=rad | teleop_input: rad(同一插件同一实现) |
| 夹爪方向 | --teleop.gripper_sign=1 --robot.gripper_sign=1 | gripper_sign: 1 |
| 相机键名 | cam_wrist / cam_external | cam_wrist / cam_external(R2C 通道名 images.color.wrist/front) |
| 观测 state | 7维[j1..j6, gripper] | 7维[j1..j6, gripper] |
| 标定文件 | follower_a1z.json | follower_a1z.json(rad 模式不依赖零位,但保留用于回零) |
三者共用同一份插件实现与标定文件,是“数采 > 训练 > 云端推理”闭环一致性的保证。
十、端到端上线检查清单
按顺序逐项打勾:
- 内核 ≥6.8.0-124;Miniforge安装完成。
- conda 环境 lerobot061(Python 3.12)已创建,LeRobot 0.6.1 + ffmpeg就绪。
- A1Z SDK、两个插件(bash setup.sh)安装并通过verify_install.py。
- r2c_sdk pip install -e . 完成,python -c "import r2c_sdk" 通过。
- CAN 适配器插入 → sudo bash setup_follower_can.sh → ip -d link show 为UP。
- 机械臂上电 → scan_can_ids.py 能扫到ID 1–7。
- 从臂标定完成,~/.cache/huggingface/lerobot/calibration/robots/galaxea_a1z_follower/follower_a1z.json存在。
- config/robot_a1z_lerobot_v2_config.yaml:can_channel与实际接口一致、calibrate: false、gripper_sign: 1、teleop_input: rad、相机索引/路径正确。
- dry_run 冒烟通过(观测发布、动作映射打印正常)。
- client_config.yaml 的 project_id/device_id/endpoints/mode与平台下发一致。
- 真实启动:平台可见设备在线、观测上行。
- 云端策略服务启动,动作闭环、机械臂按推理执行。
- (数采)主臂 udev 权限、联标、record.sh录制1~2个episode并抽查数据。
十一、常见问题
| 常见问题 | 可能原因 | 解决方法 |
|---|---|---|
| CAN接口未出现/ 无CAN帧 | 适配器未插、驱动未加载。 | sudo bash setup_follower_can.sh;dmesg | grep gs_usb |
| 电机使能无反馈 | 内核过旧。 | 升级内核到 ≥6.8.0-124 或按 Galaxea官方指引打补丁。 |
| invalid choice(lerobot CLI 不认识 galaxea_a1z_follower) | 插件未装或环境未激活。 | conda activate lerobot061 && bash setup.sh;lerobot-calibrate --help | grep galaxea。 |
| 启动时 Couldn't find a choice class / draccus解码失败 | 插件未注册(第三方插件未自动发现)。 | 确认pip show lerobot_robot_galaxea_a1z;确认环境内 lerobot为0.6.x。 |
| import插件报 (unknown location) | 同名无 __init__.py目录遮蔽已装包。 | 检查 PYTHONPATH 是否含空条目导致cwd入路径。 |
| 启动后卡在交互式标定 | robot_connect.calibrate未设false或标定文件缺失。 | 先标定(§6.1),再设 calibrate: false。 |
| 夹爪开合方向与训练数据相反 | gripper_sign用了遗留默认-1。 | 改为 +1。 |
| 云端动作被钳制/机械臂不动 | dry_run: true 未改回;teleop_input 与策略输出坐标系不符。 | 改回 false;确认策略输出为绝对弧度。 |
| 观测无图像 | 相机索引漂移. | v4l2-ctl --list-devices 确认,改用设备路径/dev/videoN或by-id。 |
| ModuleNotFoundError: No module named 'a1z' | A1Z SDK未装入当前环境。 | A1Z_SDK=/path/to/GALAXEA-A1Z bash setup.sh。 |
| 平台显示设备离线 | 心跳被禁或网络不通。 | 检查runtime.heartbeat配置与 endpoints连通性。 |
| 机械臂下坠/抖动 | 重力补偿异常或增益过高。 | 检查 gravity_comp_factor、max_joint_vel_deg_s,降低kp调试。 |
| 键盘控制无响应 | 非TTY终端。 | 在真实终端中运行。 |