训练用于实机部署的 Reach 策略#

本教程介绍如何训练末端执行器位姿跟踪(Reach)强化学习(RL)策略,并从仿真迁移到真实机器人。完成后,您将得到一个能够控制机械臂、在工作空间内到达任意目标末端位姿的策略。

支持的机器人:

  • Universal Robots UR10e :6 自由度工业机械臂

  • Flexiv Rizon 4s :7 自由度协作机械臂

本教程的范围:

本教程介绍仿真到现实工作流的 训练 部分。实机部署步骤,包括机器人接口设置及 ROS 推理节点配置,见 Isaac ROS 文档 。

前提条件:

开始之前,请确保已安装并配置 Isaac Lab。如果尚未配置环境,请按 安装指南 操作。

任务概览#

Reach 任务训练策略跟踪机器人工作空间内随机采样的末端执行器位姿。

工作原理:

  1. 在指定工作空间内随机采样目标位姿(位置和朝向)

  2. 策略接收当前关节状态和目标位姿作为观测

  3. 策略输出增量关节位置指令,使末端执行器朝目标移动

  4. 训练时定期重新采样目标,让策略能泛化到整个工作空间

仿真到现实迁移的关键概念#

成功的仿真到现实迁移需要保证三方面的一致性:

  1. 输入一致性 :仿真中的观测必须与实机可获得的观测一致。

  2. 系统响应一致性 :仿真机器人对动作的响应应与实机相近。

  3. 输出一致性 :部署时必须复现对策略输出进行的所有后处理。

妥善处理这些问题后,仅在仿真中训练的策略也能迁移到真实硬件,无需任何实机训练数据。

观测空间#

策略只接收本体感知观测,这些数据可由机器人控制器可靠地提供:

Reach 环境观测#

观测

UR10e 维度

Rizon 4s 维度

来源

joint_pos

6

7

机器人关节编码器

joint_vel

6

7

机器人关节编码器

pose_command

7

7

目标位姿(三维位置 + 四元数)

总观测维度: 19(UR10e)或 21(Rizon 4s)

实现:

@configclass
class PolicyCfg(ObsGroup):
    """Observations for policy group."""

    joint_pos = ObsTerm(func=mdp.joint_pos, noise=Unoise(n_min=-0.0, n_max=0.0))
    joint_vel = ObsTerm(func=mdp.joint_vel, noise=Unoise(n_min=-0.0, n_max=0.0))
    pose_command = ObsTerm(func=mdp.generated_commands, params={"command_name": "ee_pose"})

    def __post_init__(self):
        self.enable_corruption = True
        self.concatenate_terms = True

备注

噪声项默认为零( Unoise(n_min=-0.0, n_max=0.0) ),即不添加观测噪声。如果希望通过噪声建模进一步提升鲁棒性,可以调整这些值。现代机器人控制器提供的关节状态反馈已足够准确,因此本任务的仿真到现实迁移不需要在训练时额外加噪声。

动作空间#

策略输出 增量关节位置指令 。每个动作指定应叠加到当前关节位置上的增量:

self.actions.arm_action = mdp.RelativeJointPositionActionCfg(
    asset_name="robot",
    joint_names=[".*"],
    scale=0.0625,        # ~3.6 degrees per action step
    use_zero_offset=True,
)
self.actions.arm_action = mdp.RelativeJointPositionActionCfg(
    asset_name="robot",
    joint_names=["joint[1-7]"],
    scale=0.0625,        # ~3.6 degrees per action step
    use_zero_offset=True,
)

每步动作缩放系数为 0.0625 弧度(约 3.6 度),兼顾响应速度和运动平滑性。UR10e 使用 [".*"] 匹配所有关节;Rizon 4s 则显式指定 ["joint[1-7]"] ,匹配 7 个机械臂关节。

动作维度: 6(UR10e)或 7(Rizon 4s)

机器人配置#

每个机器人都有专用的执行器配置和工作空间定义。

UR10e 是 6 自由度工业机器人,使用以下执行器配置:

actuators = {
    "shoulder": ImplicitActuatorCfg(
        joint_names_expr=["shoulder_.*"],
        stiffness=1320.0,
        damping=72.66,
        friction=0.0,
        armature=0.0,
    ),
    "elbow": ImplicitActuatorCfg(
        joint_names_expr=["elbow_joint"],
        stiffness=600.0,
        damping=34.64,
        friction=0.0,
        armature=0.0,
    ),
    "wrist": ImplicitActuatorCfg(
        joint_names_expr=["wrist_.*"],
        stiffness=216.0,
        damping=29.39,
        friction=0.0,
        armature=0.0,
    ),
}

末端执行器:

  • 连杆: wrist_3_link

  • 默认朝向:末端执行器朝下(roll = pi,yaw = -pi/2)

目标工作空间:

# Position (meters, relative to robot base)
pos_center = (0.8875, -0.225, 0.2)
pos_range = (0.25, 0.125, 0.1)  # ±25cm x, ±12.5cm y, ±10cm z

# Orientation (radians)
rot_center = (pi, 0.0, -pi/2)
rot_range = (pi/6, pi/6, pi*2/3)  # ±30 deg roll/pitch, ±120 deg yaw

Rizon 4s 是 7 自由度协作机器人,各关节组的力矩、速度及刚度特性不同:

actuators = {
    # Joints 1-2: Higher torque (123 Nm), lower speed
    "shoulder": ImplicitActuatorCfg(
        joint_names_expr=["joint[1-2]"],
        joint_effort_limit=123.0,
        joint_velocity_limit=2.094,  # 120 deg/s
        stiffness=6000.0,
        damping=108.5,
        friction=0.0,
        armature=0.0,
    ),
    # Joints 3-4: Medium torque (64 Nm), medium speed
    "elbow": ImplicitActuatorCfg(
        joint_names_expr=["joint[3-4]"],
        joint_effort_limit=64.0,
        joint_velocity_limit=2.443,  # 140 deg/s
        stiffness=4200.0,
        damping=90.7,
        friction=0.0,
        armature=0.0,
    ),
    # Joints 5-7: Lower torque (39 Nm), higher speed
    "wrist": ImplicitActuatorCfg(
        joint_names_expr=["joint[5-7]"],
        joint_effort_limit=39.0,
        joint_velocity_limit=4.887,  # 280 deg/s
        stiffness=1500.0,
        damping=54.2,
        friction=0.0,
        armature=0.0,
    ),
}

末端执行器:

  • 连杆: flange

  • 默认朝向:末端执行器朝下(roll = pi)

目标工作空间:

# Position (meters, relative to robot base)
pos_center = (0.4, 0.0, 0.4)
pos_range = (0.4, 0.4, 0.35)  # ±40cm x, ±40cm y, ±35cm z

# Orientation (radians)
rot_center = (pi, 0.0, 0.0)
rot_range = (pi/2, pi/2, pi)  # ±90 deg roll/pitch, ±180 deg yaw

自定义工作空间#

您可能需要修改目标工作空间,以匹配实际部署场景。可调整的主要参数包括:

目标位置范围

修改机器人专用配置文件(如 joint_pos_env_cfg.py )中的 target_pos_centre 和 target_pos_range :

# Center of the target workspace (meters, relative to robot base)
self.target_pos_centre = (0.5, 0.0, 0.4)

# Half-extents of the workspace in each dimension
self.target_pos_range = (0.2, 0.2, 0.15)  # ±20cm x, ±20cm y, ±15cm z

影响:

  • 扩大范围会增加任务难度,但有助于提升泛化能力。

  • 确保所有目标位置都在机器人可达范围内(满足运动学限制)。

  • 工作空间之外的目标会导致策略失败。

目标朝向范围

修改 target_rot_centre 和 target_rot_range :

# Center orientation (roll, pitch, yaw in radians)
self.target_rot_centre = (math.pi, 0.0, 0.0)

# Range of rotation variation around the center
self.target_rot_range = (math.pi/6, math.pi/6, math.pi)  # ±30 deg, ±30 deg, ±180 deg

影响:

  • 扩大朝向范围可训练适用范围更广的策略,但可能减慢收敛。

  • 范围过大(如允许任意旋转)会显著增加训练难度。

动作缩放系数

修改动作配置中的 scale 参数:

self.actions.arm_action = mdp.RelativeJointPositionActionCfg(
    asset_name="robot",
    joint_names=[".*"],
    scale=0.0625,  # Decrease for finer control, increase for faster motion
    use_zero_offset=True,
)

影响:

  • 系数较小:控制更精细、运动更平滑,但到达目标较慢。

  • 系数较大:运动更快,但可能出现突变或越过目标。

  • 部署到实机时必须使用相同的缩放系数。

目标重采样间隔

修改命令配置中的 resampling_time_range :

self.commands.ee_pose.resampling_time_range = (4.0, 4.0)  # Resample every 4 seconds

影响:

  • 间隔较短:每回合能接触更多不同目标,但到达每个目标的时间更少。

  • 间隔较长:有更多时间精细跟踪,但训练中接触的目标更少。

域随机化#

域随机化有助于策略适应真实机器人行为的变化。

执行器增益随机化:

robot_joint_stiffness_and_damping = EventTerm(
    func=mdp.randomize_actuator_gains,
    min_step_count_between_reset=200,
    mode="reset",
    params={
        "asset_cfg": SceneEntityCfg("robot"),
        "stiffness_distribution_params": (0.9, 1.1),   # 90-110% of nominal
        "damping_distribution_params": (0.75, 1.5),   # 75-150% of nominal
        "operation": "scale",
        "distribution": "uniform",
    },
)

min_step_count_between_reset=200 可避免执行器增益过于频繁地重新随机化,让策略在参数再次变化前有时间适应当前设置。

关节摩擦随机化:

joint_friction = EventTerm(
    func=mdp.randomize_joint_parameters,
    min_step_count_between_reset=200,
    mode="reset",
    params={
        "asset_cfg": SceneEntityCfg("robot"),
        "friction_distribution_params": (0.0, 0.1),  # Add 0-0.1 Nm friction
        "operation": "add",
        "distribution": "uniform",
    },
)

初始关节位置随机化:

reset_robot_joints = EventTerm(
    func=mdp.reset_joints_by_offset,
    mode="reset",
    params={
        "position_range": (-0.125, 0.125),  # ±7 degrees
        "velocity_range": (0.0, 0.0),
    },
)

奖励结构#

策略使用基于关键点的奖励进行训练,同时衡量位置和朝向精度:

@configclass
class RewardsCfg:
    """Reward terms for the MDP."""

    # Linear penalty for keypoint tracking error
    end_effector_keypoint_tracking = RewTerm(
        func=mdp.keypoint_command_error,
        weight=-1.5,
        params={
            "asset_cfg": SceneEntityCfg("ee_frame"),
            "command_name": "ee_pose",
            "keypoint_scale": 0.45,
        },
    )

    # Exponential reward for fine precision
    end_effector_keypoint_tracking_exp = RewTerm(
        func=mdp.keypoint_command_error_exp,
        weight=1.5,
        params={
            "asset_cfg": SceneEntityCfg("ee_frame"),
            "command_name": "ee_pose",
            "kp_exp_coeffs": [(50, 0.0001), (300, 0.0001), (5000, 0.0001)],
            "kp_use_sum_of_exps": False,
            "keypoint_scale": 0.45,
        },
    )

    # Penalties for smooth motion
    action_rate = RewTerm(func=mdp.action_rate_l2, weight=-0.005)
    action = RewTerm(func=mdp.action_l2, weight=-0.005)

基于关键点的奖励在末端执行器坐标系上放置虚拟标记,并测量它们与目标坐标系上对应标记之间的距离。该指标能够自然地同时反映位置和朝向误差。

训练策略#

步骤 1:验证环境#

开始完整训练前,先短暂运行一次可视化,确认环境配置正确:

uv run isaaclab train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e-ROS-Inference \
    --num_envs 4 \
    --visualizer kit
./isaaclab.sh train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e-ROS-Inference \
    --num_envs 4 \
    --visualizer kit
uv run isaaclab train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s-ROS-Inference \
    --num_envs 4 \
    --visualizer kit
./isaaclab.sh train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s-ROS-Inference \
    --num_envs 4 \
    --visualizer kit

这会打开 Isaac Sim 查看器,让您实时观察训练。

Isaac Lab 中的 Reach 策略训练可视化

训练可视化展示多个并行环境中的机器人向目标位姿移动。#

检查要点:

  • 机器人应移动机械臂,尝试到达不同位姿。

  • 训练初期策略正在探索,运动不规则是正常现象。

  • 对于 Rizon 4s :目标位姿标记以坐标系形式显示在场景中。

  • 对于 UR10e :目标可视化已关闭( debug_vis = False ),因为命令在 base 坐标系中生成,而它与渲染使用的 base_link 坐标系相差 180 度。机器人仍会跟踪目标,但不会显示标记。

确认环境显示正确后,按 Ctrl+C 停止训练,再开始完整规模的训练。

步骤 2:完整规模训练#

在无界面模式下,使用大量并行环境启动完整训练:

uv run --extra video isaaclab train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e-ROS-Inference \
    --num_envs 4096 \
    --video --video_length 720 --video_interval 72000
./isaaclab.sh train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e-ROS-Inference \
    --num_envs 4096 \
    --video --video_length 720 --video_interval 72000
uv run --extra video isaaclab train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s-ROS-Inference \
    --num_envs 4096 \
    --video --video_length 720 --video_interval 72000
./isaaclab.sh train --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s-ROS-Inference \
    --num_envs 4096 \
    --video --video_length 720 --video_interval 72000

命令说明:

  • --num_envs 4096 :运行 4096 个并行环境,高效采集数据。

  • --video :录制视频,便于观察训练进展。

  • --video_length 720 :每段视频恰好覆盖一个完整回合( episode_length_s / (sim.dt * decimation) = 12.0 / (1/120 * 2) = 720 步)。

  • --video_interval 72000 :每 72000 个环境步(约每 100 次训练迭代)录制一段视频。

训练配置:

两个机器人使用相同的训练超参数:

num_steps_per_env = 512
max_iterations = 1500
save_interval = 50
obs_groups = {"actor": ["policy"], "critic": ["policy"]}

actor = RslRlMLPModelCfg(
    hidden_dims=[256, 128, 64],
    activation="elu",
    obs_normalization=True,
    distribution_cfg=RslRlMLPModelCfg.GaussianDistributionCfg(init_std=1.0),
)
critic = RslRlMLPModelCfg(
    hidden_dims=[256, 128, 64],
    activation="elu",
    obs_normalization=True,
)

algorithm = RslRlPpoAlgorithmCfg(
    value_loss_coef=1.0,
    use_clipped_value_loss=True,
    clip_param=0.2,
    entropy_coef=0.0,
    num_learning_epochs=8,
    num_mini_batches=8,
    learning_rate=5.0e-4,
    schedule="adaptive",
    gamma=0.99,
    lam=0.95,
    desired_kl=0.008,
    max_grad_norm=1.0,
)

UR10e 的 experiment_name 为 "reach_ur10e" ,Rizon 4s 的为 "reach_rizon4s" 。训练通常需要 1–3 小时,具体取决于 GPU。

步骤 3:监控训练进展#

使用 TensorBoard 监控训练指标:

uv run python -m tensorboard.main --logdir logs/rsl_rl/reach_ur10e
./isaaclab.sh -p -m tensorboard.main --logdir logs/rsl_rl/reach_ur10e
uv run python -m tensorboard.main --logdir logs/rsl_rl/reach_rizon4s
./isaaclab.sh -p -m tensorboard.main --logdir logs/rsl_rl/reach_rizon4s

如果训练日志位置不同,请将日志目录路径改为实际位置。

主要观察指标:

  • 平均奖励 :应持续增长,并在策略收敛后趋于平稳。

  • 奖励项 :观察各个奖励分量,以了解策略行为:

    • end_effector_keypoint_tracking :线性关键点跟踪惩罚,随着策略改善,应逐渐接近零(负值的绝对值减小)。

    • end_effector_keypoint_tracking_exp :指数精度奖励,随着跟踪精度提高,应逐渐增大。

    • action_rate 和 action :运动平滑性惩罚,数值较小,但训练中应逐渐增大(负值接近零),表明策略正收敛到更平滑的运动。

  • 位置误差 :末端执行器与目标位置之间的欧氏距离,单位为米,应随训练减小。

  • 朝向误差 :末端执行器与目标朝向之间的角度差,应随训练减小。

步骤 4:评估已训练策略#

训练完成后,用回放命令评估策略。回放命令会自动应用任务的回放模式覆盖设置( play_mode ),关闭观测扰动以便更清楚地评估,并限制环境数量以改善可视化:

uv run isaaclab play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e \
    --num_envs 50 \
    --visualizer kit
./isaaclab.sh play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e \
    --num_envs 50 \
    --visualizer kit
uv run isaaclab play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s \
    --num_envs 50 \
    --visualizer kit
./isaaclab.sh play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-Rizon4s \
    --num_envs 50 \
    --visualizer kit

加载检查点:

默认情况下,回放命令会自动加载最新训练运行中的最新检查点。它在 logs/rsl_rl/<experiment_name>/ 中搜索,按字母顺序排序后选择最后一个运行文件夹和检查点文件。

要加载指定检查点,使用以下参数:

# Load a specific checkpoint file
uv run isaaclab play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e \
    --checkpoint /path/to/model_1500.pt
# Load a specific checkpoint file
./isaaclab.sh play --rl_library rsl_rl \
    --task IsaacContrib-Deploy-Reach-UR10e \
    --checkpoint /path/to/model_1500.pt

步骤 5:部署到真实机器人#

确认训练效果符合预期后,通过 Isaac ROS 部署流水线部署到真实硬件。该流水线使用:

  • 训练得到的模型检查点( .pt 文件)

  • 训练时生成的 agent.yaml 和 env.yaml 配置文件

无需额外的导出步骤。

详细部署步骤见 Isaac ROS 文档 。

故障排除#

CUDA 内存不足#

错误:

torch.OutOfMemoryError: CUDA out of memory.

解决办法:

  1. 减少并行环境数量:

    --num_envs 2048  # or 1024, 512, etc.
    
  2. 关闭视频录制:

    移除 --video 参数,以释放 GPU 显存。

策略不收敛#

如果经过多次迭代奖励仍没有改善:

  1. 检查目标工作空间范围 :确保所有目标位姿都能被机器人到达。

  2. 核对关节名称 :确认仿真与配置中的关节顺序一致。

  3. 减小域随机化 :暂时关闭随机化,确认基础任务能正常运行。

实机运动不平滑#

如果部署后的策略产生突变或不稳定运动:

  1. 减小动作缩放系数 :降低 RelativeJointPositionActionCfg 中的 scale 参数。

  2. 核对控制频率 :确保实机与仿真的运行频率相同(默认为 60 Hz)。

  3. 核对关节顺序 :确认仿真与实机的关节名称和顺序一致。

更多资源#