机器人
在配置中按键名选用内置机器人,或注册一个新的 Robot 子类。
先选定路径
| 情况 | 动作 | 章节 |
|---|---|---|
| 机器人是六款内置之一(见内置机器人列表) | 把配置指向它,无需写代码。 | 前置条件、把配置接到机器人、硬件侧 |
| 机器人是新型号、不在列表里 | 编写一个 Robot 子类并注册。 | 全部章节 |
前置条件
把配置接到内置机器人
配置写上机器人名字即可,EVA 启动时按名查找并构建对应机器人。这个名字就是机器人的注册键——内置机器人列表中的原样字符串(例如 ur5e)。
配置分层:基础文件设定机器人和传输层,其上的叶子文件补上策略和动作空间。从 configs/01_deploy/ur5e/_base.py 出发,改动几个值即可:
# _base_ 用于继承共享默认值,这行保持原样即可。 _base_ = ['../../00_base/defaults.py'] robot = dict( type='<机器人键>', # ← 填入某个内置键,例如 'ur5e' ) transport = dict( type='zmq', # EVA 与机器人对话的方式:zmq / ros1 / ros2 / dataset resize_pad=False, # 除非相机图像需要补边,否则保持默认 image_layout='hwc', # 相机图像的通道顺序:'hwc' 或 'chw'(见传输层页) )
| 字段 | 含义 | 是否改? |
|---|---|---|
robot.type | 要运行的机器人注册键。 | 要。 |
transport.type | zmq(多数场景)、ros1/ros2,或 dataset(回放)。 | 通常用 zmq。 |
transport.resize_pad | 是否把相机图像补成正方形。 | 很少改。 |
transport.image_layout | 像素顺序:hwc 或 chw。 | 仅图像显示异常时改。 |
其上的叶子文件——例如 configs/01_deploy/ur5e/openpi_qpos.py——补上策略服务器和动作空间,已随 EVA 自带。完整设置项与分层合并语义见配置页;动作空间的选择见动作空间页。
gripper_threshold(0.5)、gripper_open/gripper_close(1.0/0.0)、eef_reference_frame(base_link)。硬件侧
EVA 不驱动电机。与电机、相机对话的实时控制环作为独立程序运行在机器人电脑上——即硬件节点。EVA 与硬件节点通过传输层(通常是 ZMQ)交换观测和动作。参考节点位于 examples/hardware/<robot>/;UR5e 这一份附带 run_hardware.sh。
在 EVA 仓库根目录执行:
# 在机器人电脑上、EVA 源码目录里: # 1) 安装 UR5e 硬件驱动(一次即可) uv pip install -e ".[ur5e]" # 2) 启动硬件节点(与电机、相机对话) bash examples/hardware/ur5e/run_hardware.sh # 3) 用现成的 UR5e 配置启动 EVA eva --config configs/01_deploy/ur5e/openpi_qpos.py
run_hardware.sh 从环境变量读取 UR5E_ROBOT_IP、夹爪串口、相机序号;默认值(如 192.168.31.123)是参考样机。两者都启动后,EVA 打印控制台网址(默认 http://localhost:8080)。DEBUG页显示实时相机画面与跟随真实姿态的 3D 模型。启动时报关节数或 shape 不匹配,表示 robot.type 与实际接入硬件不符。
zmq / ros1 / ros2 / dataset。URDF 与网格文件随 EVA 安装一同打包。内置机器人
键列即填进 robot.type 的字面值。
| 键 | 布局 | 动作维度·备注 |
|---|---|---|
agilex_AGILEX | 两条 6-DoF 臂 | 14 个值;夹爪在连杆 gripper_base |
arx_r5 | 两条 6-DoF 臂 | 14 个值;夹爪在连杆 link6 |
ur5e | 一条 6-DoF 臂 | 7 个值;夹爪在连杆 grasp_link |
dual_franka | 两条 7-DoF Panda 臂 | 16 个值;参考系 workcell/base_link |
r1_lite | 固定躯干上的两条 6-DoF 臂 | 14 个值;参考系 base_link/torso_link3 |
agibot_g2 | 人形:两条 7-DoF 臂 + 3-DoF 头 + 5-DoF 躯干 | 24 个值 |
列表中已有则到此为止,回到把配置接到机器人。下文面向接入不在列表里的机器人。
开发者:一个机器人由什么组成
接入新机器人,即写一个 Python 类向 EVA 描述它——关节、相机、绘制方式。实时电机控制环属于硬件节点,不在此类中。
每款内置机器人位于 src/robots/zoo/<name>/:一个 __init__.py 承载唯一的 Robot 子类,旁边是放 URDF 与网格的 assets/。
src/robots/zoo/<你的机器人>/ ├── __init__.py # 你的 Robot 类 + 它的注册 └── assets/ └── <你的机器人>_description/ ├── urdf/ │ └── <你的机器人>.urdf └── meshes/ └── *.STL # URDF 指向的 3D 形状文件
开发者:你要填写的部分
机器人类由几个描述对象在类上一次性声明。
执行器组
执行器组是一束逻辑上成组的关节(例如 "left_arm"),含固定数量和按 URDF 顺序排列的关节名。扁平动作向量按声明顺序切分到各组——双臂机器人即 [left_arm, right_arm]。
| 字段 | 含义 |
|---|---|
name | 组名,供类中其他位置引用。 |
dof | 该组消耗的动作数值数量。 |
joint_names | 按 URDF 顺序排列的关节名。 |
gripper_index | 组内夹爪值的索引,无则为空。 |
观测 schema
观测 schema 声明策略每一步看到什么:把相机的逻辑名映射到策略读取的键(传输层稍后再把逻辑名解析为话题或数据集列),并列出哪些执行器组的 qpos 拼接进状态向量。
3D 视图配置
3D 视图配置告诉控制台如何绘制机器人:每个 URDF 实例对应一个部件。每个部件记录其 URDF、世界中的摆放(位置 + 四元数),以及驱动它的关节位置切片。部件可共用 URDF——双臂机器人可把单臂 URDF 摆放两处。
开发者:把关节映射到 3D 视图
每个 3D 部件需要一份动作向量到所绘关节的映射,由一组有序的段给出:
| 段 | 作用 |
|---|---|
copy 一段范围 | 动作数值原样透传——手臂关节。 |
fixed 常量 | 把关节固定为常量——锁死的轮子、固定的躯干。 |
gripper 映射 | 把一个夹爪值展开为手指关节运动,按行程缩放。 |
这三类覆盖单臂、共用 URDF 的双臂以及全身布局。其它情形可直接提供映射函数。
开发者:手臂运动(build_kinematics)
若策略输出末端执行器位姿,EVA 需要 IK 反推关节角;EVA 使用 PyRoki,并以一整个 chunk 为单位批量求解。若策略直接输出关节角,类上报「无运动学」,EVA 跳过 IK。否则返回每条臂的 PyRoki 求解器:有序关节、末端连杆,以及可选的支持参考系。
eef_reference_frame 才被接受;不支持的取值在启动时报错。开发者:编写类并注册
继承 Robot,填入描述对象,并用 @ROBOT_REGISTRY.register("<你的键>") 注册。该键即用户填进 robot.type 的值。UR5e 源码是完整参考范例。
@ROBOT_REGISTRY.register('<你的键>') # ← 用户填进 robot.type 的名字 class YourRobot(Robot): def __init__(self): super().__init__( name='<你的键>', actuator_groups=..., # ← 你的关节组(见「你要填写的部分」) observation_schema=..., # ← 你的相机 + 状态 vis_config=..., # ← 你的 3D 视图部件 ) def build_kinematics(self, **kwargs): return ... # 一个 PyRoki 求解器;若无需 IK 则返回 None
src/robots/zoo/ur5e/__init__.py 把每个组、相机、关节表与初始姿态都写成了可用的值。把包加入 src/robots/__init__.py,导入即触发启动时注册:
from robots.zoo import ( agibot_g2, agilex_AGILEX, arx_r5, dual_franka, r1_lite, ur5e, your_robot, # ← 在此加上你的目录名 )
之后机器人即与内置款一致:用户按上面把配置接到机器人那样以 robot.type='<你的键>' 选中。
开发者:该复制哪款内置机器人
- 单臂 →
ur5e。 - 两臂共用同一把臂模型 →
agilex_AGILEX。 - 全身(臂装在躯干或底盘上) →
r1_lite。
更深入的公开 API 见开发。