机器人

在配置中按键名选用内置机器人,或注册一个新的 Robot 子类。

先选定路径

情况动作章节
机器人是六款内置之一(见内置机器人列表把配置指向它,无需写代码。前置条件把配置接到机器人硬件侧
机器人是新型号、不在列表里编写一个 Robot 子类并注册。全部章节

前置条件

把配置接到内置机器人

配置写上机器人名字即可,EVA 启动时按名查找并构建对应机器人。这个名字就是机器人的注册键——内置机器人列表中的原样字符串(例如 ur5e)。

配置分层:基础文件设定机器人和传输层,其上的叶子文件补上策略和动作空间。从 configs/01_deploy/ur5e/_base.py 出发,改动几个值即可:

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.typezmq(多数场景)、ros1/ros2,或 dataset(回放)。通常用 zmq
transport.resize_pad是否把相机图像补成正方形。很少改。
transport.image_layout像素顺序:hwcchw仅图像显示异常时改。

其上的叶子文件——例如 configs/01_deploy/ur5e/openpi_qpos.py——补上策略服务器和动作空间,已随 EVA 自带。完整设置项与分层合并语义见配置页;动作空间的选择见动作空间页。

来自共享默认值的可选夹爪与参考系字段:gripper_threshold0.5)、gripper_open/gripper_close1.0/0.0)、eef_reference_framebase_link)。

硬件侧

EVA 不驱动电机。与电机、相机对话的实时控制环作为独立程序运行在机器人电脑上——即硬件节点。EVA 与硬件节点通过传输层(通常是 ZMQ)交换观测和动作。参考节点位于 examples/hardware/<robot>/;UR5e 这一份附带 run_hardware.sh

在 EVA 仓库根目录执行:

bash
# 在机器人电脑上、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 与实际接入硬件不符。

厂商 SDK 放在硬件节点中,不放进 EVA。EVA 本身只讲 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/

text
src/robots/zoo/<你的机器人>/
├── __init__.py                     # 你的 Robot 类 + 它的注册
└── assets/
    └── <你的机器人>_description/
        ├── urdf/
        │   └── <你的机器人>.urdf
        └── meshes/
            └── *.STL               # URDF 指向的 3D 形状文件
传输层不写进机器人类。ROS 话题、ZMQ 端点、数据集列归传输层后端,因此同一机器人类可不加改动地驱动任意传输层。

开发者:你要填写的部分

机器人类由几个描述对象在类上一次性声明。

执行器组

执行器组是一束逻辑上成组的关节(例如 "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 源码是完整参考范例。

src/robots/zoo/<你的机器人>/__init__.py
@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,导入即触发启动时注册:

src/robots/__init__.py
from robots.zoo import (
    agibot_g2, agilex_AGILEX, arx_r5, dual_franka, r1_lite, ur5e,
    your_robot,   # ← 在此加上你的目录名
)

之后机器人即与内置款一致:用户按上面把配置接到机器人那样以 robot.type='<你的键>' 选中。

开发者:该复制哪款内置机器人

更深入的公开 API 见开发