动作空间

策略输出可为关节角(JointState)或末端执行器位姿(EEFPose);EVA始终以关节角命令机器人,位姿由IK逐帧转换。

两种空间

观测与动作各由inference_cfg下的一个type字符串描述。切换只需改配置。

空间(type 字符串)承载适用场景
JointState扁平的关节角列表,即机器人直接读写的原始值。默认。策略输出关节角。
EEFPose每条臂的手部位姿。EVA跑IK转为关节角。策略输出末端执行器位姿。

两者均默认为JointState

python
inference_cfg = dict(
    obs_space=dict(type='JointState'),     # 策略输入
    action_space=dict(type='JointState'),  # 策略输出
    publish_rate=30,                          # 每秒下发的关节命令数(Hz)
)
publish_rate是EVA下发关节命令的频率。默认30 Hz;按机器人控制环要求调整。

切换到末端执行器模式

把两个type都改成EEFPose,并在部署配置里声明位姿布局——复制一个部署预设作为起点,如configs/01_deploy/<你的机器人>/openpi_eef.py,再用eva --config <该文件>启动。机器人必须自带IK求解器(见本节末提示框)。

python — 部署配置
inference_cfg = dict(
    obs_space=dict(
        type='EEFPose',
        n_arms=<臂数>,            # 1 或 2
        rotation='<旋转类型>',    # 见下表
        include_gripper=True,
    ),
    action_space=dict(
        type='EEFPose',
        n_arms=<臂数>,            # 与 obs_space 一致
        rotation='<旋转类型>',    # 与 obs_space 一致
        include_gripper=True,
    ),
)

rotation声明朝向的编码方式;末列数字为其占用值数。

rotation含义占用值数
quat四元数。默认。4
euler横滚/俯仰/偏航。3
rotvec旋转向量。3
rot6d六数表示。6

每臂块为3(位置)+旋转占用值数+ 1(夹爪),按n_arms重复。策略不输出夹爪值时设include_gripper=False。带夹爪的双臂quat(3+4+1) × 2 = 16个值。

必须自带IK。内置支持IK的机器人:agilex_AGILEXdual_frankaagibot_g2r1_liteur5e。在无IK的机器人上请求EEF模式会报错"EEF mode requires an IK solver but the robot does not provide one"。改用JointState模式,或在添加机器人时补上运动学。

统一的每臂布局

EVA在后续处理前,会把所有EEF动作改写为单一统一布局,使下游只面对一种形状。

统一的每臂布局
位置 (3)  +  以四元数表示的朝向 (4)  +  夹爪 (1)  =  每臂 8 个值

所配置的rotation会被转成四元数,位置和夹爪原样不动。action_space设为EEFPose后自动完成。EEF模式下,录制器写入的也是这种每臂8值布局。

从位姿到关节命令

机器人始终以关节角被命令。分发路径取决于action_space

IK求解器由机器人运动学构建一次后复用,按publish_rate运行。反方向以FK把测得的关节角换算为位姿,用于在请求EEF观测但无位姿传感器时填充观测与录制的位姿值。

IK轨迹跟踪

EVA的IK求解器(PyRoki,构建于JAXjaxls之上)逐帧转换一个块,每帧为一个小型优化问题,并串接到前一帧。

每帧目标:

首帧以当前测得的关节状态为初值。EVA不会丢弃无法到达的帧:跟踪误差超过容差时,EVA记录警告并下发最接近的关节角。反复出现跟踪警告,说明策略要求的位姿超出可达范围。

双臂机器人按每臂块拆分独立求解再合并。额外身体关节(如固定的头和躯干)保持冻结,仅更新臂关节。

真实机器人与仿真

解算出的关节角可发往两个目标之一:

控制台STEP模式先在SIM预览一个块,再在REAL上确认。离开EVA的只有按publish_rate下发的关节角,位姿不会外泄。