强化学习基本框架

OnPolicyAlgorithm类

OnPolicyAlgorithm类,是稳定基线3 (Stable Baselines3) 中所有策略梯度 (On-Policy) 强化学习算法的基类,例如 A2C 和 PPO。
主要功能:

  1. 初始化和设置:

    • 初始化算法的参数,包括策略网络、环境、学习率、折扣因子、GAE 参数、熵系数等。
    • 设置学习率计划、随机种子。
    • 根据观测空间类型选择合适的 rollout buffer (经验回放缓冲区)。
    • 创建 rollout buffer 和策略网络,并将策略网络移动到指定的设备 (CPU 或 GPU)。
  2. 收集经验 (collect_rollouts):

    • 使用当前策略与环境交互,收集经验数据并存储到 rollout buffer 中。
    • 在收集经验的过程中,会调用回调函数进行一些操作,例如记录日志、保存模型等。
    • 处理超时 (timeout) 情况,使用值函数进行 bootstrapping。
    • 计算回报 (returns) 和优势 (advantage) 函数。
  3. 训练 (train):

    • 这个方法是一个抽象方法,具体的训练逻辑由子类实现,例如 A2C 和 PPO。
    • 子类需要根据 rollout buffer 中的经验数据更新策略网络的参数。
  4. 记录日志 (_dump_logs):

    • 记录训练过程中的信息,例如迭代次数、奖励、episode 长度、成功率等。
  5. 学习 (learn):

    • 这是算法的主循环,它会不断地收集经验和训练策略网络,直到达到指定的训练步数。
    • 在训练过程中,会定期调用回调函数和记录日志。

关键概念:

  • 策略梯度 (On-Policy): 这类算法直接学习策略,并根据当前策略收集的经验数据进行更新。
  • Rollout Buffer: 存储经验数据的缓冲区,包括状态、动作、奖励、是否结束等信息。
  • GAE (Generalized Advantage Estimation): 一种计算优势函数的方法,可以平衡偏差和方差。
  • 熵系数 (Entropy Coefficient): 鼓励策略探索环境,避免过早收敛到次优解。
  • 值函数系数 (Value Function Coefficient): 控制值函数损失的权重。

代码结构:

  • OnPolicyAlgorithm 继承自 BaseAlgorithmBaseAlgorithm 提供了一些通用的功能,例如设置环境、策略、学习率等。
  • OnPolicyAlgorithm 定义了一些抽象方法,例如 train,由子类实现具体的训练逻辑。
  • OnPolicyAlgorithm 提供了一些辅助方法,例如 collect_rollouts_dump_logslearn 等。

总结:

OnPolicyAlgorithm 是 Stable Baselines3 中策略梯度算法的基类,它定义了策略梯度算法的基本框架,包括初始化、收集经验、训练、记录日志等功能。具体的训练逻辑由子类实现,例如 A2C 和 PPO。 通过继承 OnPolicyAlgorithm,可以方便地开发新的策略梯度算法。

PPO

PPO类,是稳定基线3 (Stable Baselines3) 中实现的近端策略优化 (Proximal Policy Optimization) 算法。PPO 是一种常用的策略梯度强化学习算法,它在 A2C 的基础上进行了改进,通过引入 clipped surrogate objective 和 KL 惩罚项来提高训练的稳定性和效率。

主要功能:

  1. 初始化和设置:

    • 初始化算法的参数,包括策略网络、环境、学习率、折扣因子、GAE 参数、clip range 等。
    • 检查参数的有效性,例如 batch_size 是否大于 1,rollout buffer 的大小是否合适等。
    • 设置学习率计划、clip range 计划。
  2. 训练 (train):

    • 将策略网络设置为训练模式。
    • 更新优化器的学习率。
    • 计算当前的 clip range。
    • 进行 n_epochs 轮训练,每轮训练都遍历一遍 rollout buffer 中的数据。
    • 对于每个 minibatch 的数据,计算价值函数、动作的对数概率、熵、优势函数、比率等。
    • 计算 clipped surrogate loss、价值函数损失、熵损失。
    • 计算近似 KL 散度,用于提前停止训练。
    • 进行梯度下降更新策略网络的参数。
    • 记录训练过程中的信息,例如损失函数、KL 散度、clip fraction 等。

关键概念:

  • Clipped Surrogate Objective: PPO 使用 clipped surrogate objective 来限制策略更新的幅度,防止策略更新过度偏离之前的策略。
  • KL 惩罚项: PPO 可以选择使用 KL 惩罚项来限制策略更新的幅度,防止策略更新过度偏离之前的策略。
  • Advantage Normalization: PPO 通常会对优势函数进行归一化,以提高训练的稳定性。
  • Entropy Bonus: PPO 可以选择使用熵奖励来鼓励策略探索环境,避免过早收敛到次优解。

代码结构:

  • PPO 继承自 OnPolicyAlgorithmOnPolicyAlgorithm 是策略梯度算法的基类。
  • PPO 实现了 train 方法,定义了 PPO 算法的训练逻辑。
  • PPO 使用了 RolloutBuffer 来存储经验数据。
  • PPO 使用了 ActorCriticPolicy 作为策略网络。

总结:

PPO 是 Stable Baselines3 中实现的近端策略优化算法,它是一种常用的策略梯度强化学习算法。PPO 通过引入 clipped surrogate objective 和 KL 惩罚项来提高训练的稳定性和效率。PPO 类实现了 PPO 算法的训练逻辑,并提供了一些辅助方法,例如 learn 等。

基本操作

添加资产

首先设定cfg,再调用相应函数

cfg = sim_utils.UsdFileCfg(usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd")
cfg.func("/World/Objects/Table", cfg, translation=(0.0, 0.0, 1.05))

添加传感器

    camera = CameraCfg(
        prim_path="{ENV_REGEX_NS}/Robot/base/front_cam",
        update_period=0.1,
        height=480,
        width=640,
        data_types=["rgb", "distance_to_image_plane"],
        spawn=sim_utils.PinholeCameraCfg(
            focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1.0e5)
        ),
        offset=CameraCfg.OffsetCfg(pos=(0.510, 0.0, 0.015), rot=(0.5, -0.5, 0.5, -0.5), convention="ros"),
    )

基本工作流

创建空场景

https://isaac-sim.github.io/IsaacLab/source/tutorials/00_sim/create_empty.html
这段代码演示了如何使用 Python 脚本在 Isaac Sim 中创建一个简单的空场景。它涵盖了启动模拟器、配置模拟上下文、运行模拟以及退出模拟等步骤。

代码解析:

  1. 导入必要的库:

    • argparse: 用于解析命令行参数。
    • omni.isaac.lab.app: 用于启动 Isaac Sim 应用程序。
    • omni.isaac.lab.sim: 用于配置和控制模拟器。
  2. 解析命令行参数:

    • 使用 argparse 创建一个参数解析器。
    • 使用 AppLauncher.add_app_launcher_args 将 Isaac Sim 启动器的命令行参数添加到解析器中。
    • 解析命令行参数,并将结果存储在 args_cli 中。
  3. 启动 Isaac Sim 应用程序:

    • 使用 AppLauncher 类启动 Isaac Sim 应用程序,并将解析的命令行参数传递给它。
    • 将应用程序对象存储在 simulation_app 中。
  4. 配置模拟上下文:

    • 使用 SimulationCfg 类创建一个模拟配置对象 sim_cfg,设置模拟步长 dt 为 0.01 秒。
    • 使用 SimulationContext 类创建一个模拟上下文对象 sim,并将配置对象 sim_cfg 传递给它。
    • 使用 sim.set_camera_view 设置主摄像机的视角,其中第一个列表指定相机位置,第二个列表指定相机目标点。
  5. 运行模拟:

    • 使用 sim.reset 方法重置模拟器,这会初始化物理引擎并开始模拟。
    • 使用 while 循环不断执行模拟步骤,直到 Isaac Sim 应用程序停止运行 (simulation_app.is_running() 返回 False)。
    • 在循环中,使用 sim.step 方法执行单个模拟步骤。
  6. 关闭模拟器应用程序:

    • 在模拟循环结束后,使用 simulation_app.close 方法关闭 Isaac Sim 应用程序。

关键概念:

  • 模拟器 (Simulator): 一个用于模拟物理世界行为的软件环境。Isaac Sim 就是一个用于机器人仿真的模拟器。
  • 场景 (Scene): 模拟器中的一个虚拟环境,包含各种对象和属性。
  • 模拟上下文 (Simulation Context): 用于控制模拟器行为的对象,例如启动、停止、重置和单步执行模拟。
  • 模拟配置 (Simulation Configuration): 用于配置模拟器参数的对象,例如模拟步长、物理引擎参数等。
  • 模拟步长 (Simulation Time Step): 模拟器执行单个步骤的时间间隔。

代码总结:

这段代码展示了如何使用 Python 脚本在 Isaac Sim 中创建一个简单的空场景,并运行模拟。它涵盖了以下步骤:

  1. 启动 Isaac Sim 应用程序。
  2. 创建一个模拟上下文对象,并配置模拟参数。
  3. 重置模拟器并启动模拟循环。
  4. 不断执行模拟步骤,直到模拟器停止运行。
  5. 关闭模拟器应用程序。

添加prim到场景中

https://isaac-sim.github.io/IsaacLab/source/tutorials/00_sim/create_empty.html 这段代码演示了如何在 Isaac Lab 中使用 Python 将各种对象(或 Prim)生成到场景中。它涵盖了生成地面、灯光、基本形状和网格(从 USD 文件)的方法。

代码核心目标:

这段代码的目标是在 Isaac Sim 模拟器中创建一个包含各种元素的 3D 场景,包括地面、灯光、基本几何形状和从 USD 文件加载的网格模型(例如桌子)。

代码实现步骤:

  1. 初始化 Isaac Sim 应用程序:

    • 使用 argparse 解析命令行参数,获取启动 Isaac Sim 应用程序所需的参数。
    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  2. 设计场景 (design_scene 函数):

    • 生成地面:
      • 使用 sim_utils.GroundPlaneCfg() 创建一个地面配置对象 cfg_ground
      • 使用 cfg_ground.func() 函数将地面生成到场景中,路径为 "/World/defaultGroundPlane"。
    • 生成灯光:
      • 使用 sim_utils.DistantLightCfg() 创建一个远光灯配置对象 cfg_light_distant,设置光照强度和颜色。
      • 使用 cfg_light_distant.func() 函数将远光灯生成到场景中,路径为 "/World/lightDistant",并设置其位置。
    • 创建 Xform Prim:
      • 使用 prim_utils.create_prim() 创建一个名为 "/World/Objects" 的 Xform Prim,用于组织场景中的对象。Xform Prim 用于对场景中的对象进行分组和变换。
    • 生成基本形状:
      • 使用 sim_utils.ConeCfg() 创建一个圆锥体配置对象 cfg_cone,设置半径、高度和颜色。
      • 使用 cfg_cone.func() 函数将两个圆锥体 Cone1Cone2 生成到场景中,并设置其位置。
      • 使用 sim_utils.ConeCfg() 创建另一个圆锥体配置对象 cfg_cone_rigid,设置半径、高度、颜色,并添加刚体物理属性(质量、碰撞属性等)。
      • 使用 cfg_cone_rigid.func() 函数将圆锥体 ConeRigid 生成到场景中,并设置其位置和方向。
      • 使用 sim_utils.MeshCuboidCfg() 创建一个长方体配置对象 cfg_cuboid_deformable,设置尺寸、颜色,并添加可变形体物理属性。
      • 使用 cfg_cuboid_deformable.func() 函数将长方体 CuboidDeformable 生成到场景中,并设置其位置。
    • 从 USD 文件生成:
      • 使用 sim_utils.UsdFileCfg() 创建一个 USD 文件配置对象 cfg,指定 USD 文件路径 (SeattleLabTable)。
      • 使用 cfg.func() 函数将桌子模型生成到场景中,路径为 "/World/Objects/Table",并设置其位置。桌子模型以引用的方式添加到场景中,这意味着对桌子模型的修改会反映到场景中,而无需直接修改 USD 文件。
  3. 主函数 (main 函数):

    • 初始化模拟上下文,设置模拟步长。
    • 设置主摄像机视角。
    • 调用 design_scene() 函数设计场景。
    • 重置模拟器并开始模拟。
    • 在循环中执行模拟步骤,直到模拟器停止运行。
  4. 程序入口:

    • if __name__ == "__main__": 语句确保只有当脚本作为主程序运行时才会执行 main() 函数。
    • 最后,关闭 Isaac Sim 应用程序。

关键概念:

  • USD (Universal Scene Description): 一种用于描述 3D 场景的软件系统和文件格式。
  • Prim (Primitive): USD 场景的基本构建块,可以是网格、灯光、相机、变换或其他 Prim 的组。
  • 属性 (Attribute): Prim 的属性,例如颜色、大小等。
  • 关系 (Relationship): Prim 之间的连接,例如网格 Prim 与材质 Prim 之间的关系。
  • 阶段 (Stage): USD 场景的容器,包含所有 Prim、属性和关系。
  • Xform (Transform Prim): 仅包含变换属性的 Prim,用于对其他 Prim 进行分组和变换。
  • 刚体 (Rigid Body): 在模拟中不会发生形变的物体。
  • 可变形体 (Deformable Body): 可以发生形变的物体,例如布料、橡胶等。
  • 引用 (Reference): 将外部文件以引用的方式添加到场景中,以便在不修改原始文件的情况下进行修改。
  • Isaac Nucleus: Isaac Sim 的资源库,包含各种预先构建好的 USD 模型,例如机器人、家具、环境等。

总结:

这段代码演示了如何在 Isaac Sim 中使用 Python 生成各种 Prim 到场景中,包括地面、灯光、基本形状和网格。它还介绍了 USD 的基本概念,以及如何使用 Isaac Lab 提供的配置驱动接口来简化场景设计过程。通过学习这段代码,可以掌握在 Isaac Sim 中进行场景设计的基本方法,并将其应用到更复杂的仿真任务中。

与物体交互

与刚体交互

这段代码演示了如何在 Isaac Sim 中创建刚体并与其交互。它涵盖了场景设计、模拟循环的运行,以及与刚体交互的具体方法。

代码结构:

  1. 导入必要的库:

    • argparse 用于处理命令行参数。
    • torch 用于张量计算。
    • omni.isaac.core.utils.prims 用于创建场景元素。
    • omni.isaac.lab.sim 用于与 Isaac Sim 进行交互。
    • omni.isaac.lab.utils.math 用于数学计算,例如采样圆柱体上的随机位置。
    • omni.isaac.lab.assets 用于加载刚体模型。
    • omni.isaac.lab.sim 用于模拟上下文。
  2. 解析命令行参数:

    • 使用 argparse 解析命令行参数,这些参数用于启动 Isaac Sim 应用程序。
  3. 启动 Isaac Sim 应用程序:

    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  4. 设计场景 (design_scene 函数):

    • 创建地面平面和灯光。
    • 创建四个名为 "Origin1"、"Origin2"、"Origin3" 和 "Origin4" 的坐标系,用于放置刚体。
    • 使用 RigidObjectCfg 配置刚体,包括:
      • prim_path:刚体在场景中的路径,使用正则表达式 /World/Origin.*/Cone 表示在每个 Origin 坐标系下创建一个名为 Cone 的刚体。
      • spawn:刚体的生成配置,使用 sim_utils.ConeCfg 创建圆锥体。
      • init_state:刚体的初始状态,使用默认配置。
    • 使用 RigidObject 类实例化刚体,并将配置对象传递给构造函数。
    • 返回一个字典 scene_entities,其中包含场景中的实体(例如刚体),以及一个列表 origins,其中包含每个刚体的初始位置。
  5. 运行模拟循环 (run_simulator 函数):

    • 重置模拟状态:
      • 每隔一段时间重置刚体的根状态,包括位置和速度。
      • 使用 RigidObject.data.default_root_state 获取刚体的默认根状态。
      • 使用 math_utils.sample_cylinder 在圆柱体上采样随机位置,并将随机位置添加到根状态的平移部分。
      • 使用 RigidObject.write_root_state_to_sim 将根状态写入模拟缓冲区。
      • 使用 RigidObject.reset 重置刚体的内部缓冲区。
    • 执行模拟步骤:
      • 使用 RigidObject.write_data_to_sim 将其他数据(例如外力)写入模拟缓冲区。
      • 本教程中没有应用外力,因此此方法不是必需的,但为了完整性而包含在内。
      • 使用 sim.step() 执行模拟步骤。
    • 更新状态:
      • 使用 RigidObject.update() 更新刚体的内部缓冲区。
      • 打印刚体的根位置。
  6. 主函数 (main 函数):

    • 加载 Isaac Sim 模拟器。
    • 设置主摄像机视角。
    • 调用 design_scene() 函数创建场景。
    • 重置模拟器。
    • 调用 run_simulator() 函数运行模拟循环。
  7. 程序入口:

    • if __name__ == "__main__": 语句确保只有当脚本作为主程序运行时才会执行 main() 函数。
    • 最后,关闭 Isaac Sim 应用程序。

关键概念:

  • 刚体 (Rigid Object): 在模拟中不会发生形变的物体。
  • 根状态 (Root State): 刚体的位置和速度。
  • 模拟缓冲区 (Simulation Buffer): 用于存储模拟数据的缓冲区,例如刚体的根状态、外力等。

总结:

这段代码演示了如何在 Isaac Sim 中创建刚体并与其交互,包括设置根状态、执行模拟步骤和更新刚体状态。通过学习这段代码,可以掌握在 Isaac Sim 中进行刚体仿真的基本方法,并将其应用到更复杂的仿真任务中。

与关节交互

这段代码演示了如何在 Isaac Sim 中与铰接机器人(例如倒立摆)进行交互。它涵盖了场景设计、模拟循环的运行,以及与机器人交互的具体方法。

代码结构:

  1. 导入必要的库:

    • argparse 用于处理命令行参数。
    • torch 用于张量计算。
    • omni.isaac.core.utils.prims 用于创建场景元素。
    • omni.isaac.lab.sim 用于与 Isaac Sim 进行交互。
    • omni.isaac.lab.assets 用于加载机器人模型。
    • omni.isaac.lab_assets 用于加载预定义的机器人配置。
  2. 解析命令行参数:

    • 使用 argparse 解析命令行参数,这些参数用于启动 Isaac Sim 应用程序。
  3. 启动 Isaac Sim 应用程序:

    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  4. 设计场景 (design_scene 函数):

    • 创建地面平面和灯光。
    • 创建两个名为 "Origin1" 和 "Origin2" 的坐标系,用于放置倒立摆机器人。
    • 使用预定义的配置对象 CARTPOLE_CFG 创建倒立摆机器人。
    • CARTPOLE_CFG 包含机器人的生成策略、默认初始状态、关节驱动器模型等信息。
    • 使用 Articulation 类实例化倒立摆机器人,并将配置对象传递给构造函数。
    • 返回一个字典 scene_entities,其中包含场景中的实体(例如机器人),以及一个列表 origins,其中包含每个机器人的初始位置。
  5. 运行模拟循环 (run_simulator 函数):

    • 重置模拟:
      • 与刚体类似,铰接机器人也有根状态,可以使用 Articulation.write_root_state_to_sim() 方法设置。
      • 此外,铰接机器人还有关节状态,可以使用 Articulation.write_joint_state_to_sim() 方法设置。
      • Articulation.reset() 方法用于重置内部缓冲区和缓存。
    • 执行模拟步骤:
      • 向铰接机器人发送控制指令包括两个步骤:
        • 设置关节目标值:使用 Articulation.set_joint_effort_target() 等方法设置关节位置、速度或力矩目标值。
        • 将数据写入模拟器:使用 Articulation.write_data_to_sim() 方法将转换后的控制指令写入 PhysX 缓冲区。
      • 本教程中使用关节力矩控制倒立摆,需要将关节刚度和阻尼参数设置为零,这在预定义的配置对象中完成。
    • 更新状态:
      • Articulation 类包含一个 ArticulationData 对象,用于存储机器人的状态。
      • 使用 Articulation.update() 方法更新缓冲区中的状态。
  6. 主函数 (main 函数):

    • 加载 Isaac Sim 模拟器。
    • 设置主摄像机视角。
    • 调用 design_scene() 函数创建场景。
    • 重置模拟器。
    • 调用 run_simulator() 函数运行模拟循环。
  7. 程序入口:

    • if __name__ == "__main__": 语句确保只有当脚本作为主程序运行时才会执行 main() 函数。
    • 最后,关闭 Isaac Sim 应用程序。

关键概念:

  • 铰接机器人 (Articulation): 由多个刚体通过关节连接而成的机器人,例如倒立摆、机械臂等。
  • 根状态 (Root State): 铰接机器人树形结构中根节点的状态,通常指位置和方向。
  • 关节状态 (Joint State): 铰接机器人关节的状态,通常指关节角度和速度。
  • 控制指令 (Commands): 用于控制铰接机器人运动的指令,例如关节位置、速度或力矩目标值。

总结:

这段代码演示了如何在 Isaac Sim 中与铰接机器人进行交互,包括设置根状态和关节状态、发送控制指令以及更新机器人状态。通过学习这段代码,可以掌握控制铰接机器人的基本方法,并将其应用到更复杂的机器人仿真任务中。

与可变形物体交互

这段代码演示了如何在 Isaac Sim 中与可变形体(例如软体)进行交互。它涵盖了场景设计、模拟循环的运行,以及与可变形体交互的具体方法,例如设置节点位置和速度,以及应用运动学指令控制网格节点移动软体。

代码结构:

  1. 导入必要的库:

    • argparse 用于处理命令行参数。
    • torch 用于张量计算。
    • omni.isaac.core.utils.prims 用于创建场景元素。
    • omni.isaac.lab.sim 用于与 Isaac Sim 进行交互。
    • omni.isaac.lab.utils.math 用于数学计算,例如生成随机方向。
    • omni.isaac.lab.assets 用于加载可变形体模型。
    • omni.isaac.lab.sim 用于模拟上下文。
  2. 解析命令行参数:

    • 使用 argparse 解析命令行参数,这些参数用于启动 Isaac Sim 应用程序。
  3. 启动 Isaac Sim 应用程序:

    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  4. 设计场景 (design_scene 函数):

    • 创建地面平面和灯光。
    • 创建四个名为 "Origin1"、"Origin2"、"Origin3" 和 "Origin4" 的坐标系,用于放置可变形体。
    • 使用 DeformableObjectCfg 配置可变形体,包括:
      • prim_path:可变形体在场景中的路径,使用正则表达式 /World/Origin.*/Cube 表示在每个 Origin 坐标系下创建一个名为 Cube 的可变形体。
      • spawn:可变形体的生成配置,使用 sim_utils.MeshCuboidCfg 创建立方体网格。
        • 设置可变形体属性,例如 rest_offsetcontact_offset
        • 设置视觉材质,例如颜色。
        • 设置物理材质,例如泊松比和杨氏模量。
      • init_state:可变形体的初始状态,设置初始位置。
      • debug_vis:是否启用调试可视化。
    • 使用 DeformableObject 类实例化可变形体,并将配置对象传递给构造函数。
    • 返回一个字典 scene_entities,其中包含场景中的实体(例如可变形体),以及一个列表 origins,其中包含每个可变形体的初始位置。
  5. 运行模拟循环 (run_simulator 函数):

    • 重置模拟状态:
      • 每隔一段时间重置可变形体的节点状态,包括位置和速度。
      • 使用 DeformableObject.data.default_nodal_state_w 获取可变形体的默认节点状态。
      • 对节点位置应用随机变换,使可变形体初始状态略有不同。
      • 使用 DeformableObject.write_nodal_state_to_sim 将节点状态写入模拟缓冲区。
      • 使用 DeformableObject.write_nodal_kinematic_target_to_sim 将节点运动学目标重置为当前节点状态,并释放所有节点的运动学约束。
      • 使用 DeformableObject.reset 重置可变形体的内部缓冲区。
    • 执行模拟步骤:
      • 更新部分可变形体的运动学目标,例如使索引为 0 和 3 的立方体沿 z 轴移动。
      • 使用 DeformableObject.write_nodal_kinematic_target_to_sim 将节点运动学目标写入模拟缓冲区。
      • 使用 DeformableObject.write_data_to_sim 将内部数据写入模拟缓冲区。
      • 使用 sim.step() 执行模拟步骤。
    • 更新状态:
      • 使用 DeformableObject.update() 更新可变形体的内部缓冲区。
      • 打印可变形体的根位置(计算为所有节点位置的平均值)。
  6. 主函数 (main 函数):

    • 加载 Isaac Sim 模拟器。
    • 设置主摄像机视角。
    • 调用 design_scene() 函数创建场景。
    • 重置模拟器。
    • 调用 run_simulator() 函数运行模拟循环。
  7. 程序入口:

    • if __name__ == "__main__": 语句确保只有当脚本作为主程序运行时才会执行 main() 函数。
    • 最后,关闭 Isaac Sim 应用程序。

关键概念:

  • 可变形体 (Deformable Object): 在模拟中可以发生形变的物体,例如软体。
  • 节点状态 (Nodal State): 可变形体网格节点的位置和速度。
  • 运动学目标 (Kinematic Target): 用户指定的节点位置目标,用于控制可变形体的运动。
  • 有限元方法 (FEM): 用于模拟可变形体形变的数值方法。

总结:

这段代码演示了如何在 Isaac Sim 中与可变形体进行交互,包括设置节点状态、应用运动学指令和更新可变形体状态。通过学习这段代码,可以掌握在 Isaac Sim 中进行可变形体仿真的基本方法,并将其应用到更复杂的仿真任务中。

场景创建

scene.InteractiveScene类

这段文档介绍了 Isaac Sim 中的 scene.InteractiveScene 类,它提供了一种便捷的接口,用于在模拟中生成和管理场景元素。

背景:

在之前的教程中,我们手动将资源生成了模拟环境,并创建了对象实例来与它们交互。然而,随着场景复杂性的增加,手动执行这些任务变得乏味。在本教程中,我们将介绍 scene.InteractiveScene 类,它提供了一种便捷的接口,用于生成图元并在模拟中管理它们。

交互式场景:

从高层次上讲,交互式场景是场景实体的集合。每个实体可以是非交互式图元(例如地面、光源)、交互式图元(例如关节、刚体)或传感器(例如相机、激光雷达)。交互式场景提供了一个便捷的接口,用于生成这些实体并在模拟中管理它们。

与手动方法相比,它提供了以下好处:

  • 减轻了用户需要单独生成每个资源的负担,因为这是隐式处理的。
  • 为多个环境启用用户友好的场景图元克隆。
  • 将所有场景实体收集到单个对象中,这使得它们更易于管理。

在本教程中,我们以“与关节交互”教程中的 Cartpole 示例为例,并将 design_scene 函数替换为 scene.InteractiveScene 对象。虽然在这个简单的示例中使用交互式场景似乎有点大 overkill,但随着将来向场景中添加更多资源和传感器,它将变得更加有用。

代码解释:

1. 场景配置:

  • 场景由一组实体组成,每个实体都有自己的配置。这些配置在一个继承自 scene.InteractiveSceneCfg 的配置类中指定。然后将配置类传递给 scene.InteractiveScene 构造函数以创建场景。
  • 对于 Cartpole 示例,我们指定与之前教程相同的场景,但现在将它们列在配置类 CartpoleSceneCfg 中,而不是手动生成它们。
@configclass
class CartpoleSceneCfg(InteractiveSceneCfg):
    """Configuration for a cart-pole scene."""

    # ground plane
    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=sim_utils.GroundPlaneCfg())

    # lights
    dome_light = AssetBaseCfg(
        prim_path="/World/Light", spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
    )

    # articulation
    cartpole: ArticulationCfg = CARTPOLE_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
  • 配置类中的变量名称用作从 scene.InteractiveScene 对象访问相应实体的键。例如,可以通过 scene["cartpole"] 访问 Cartpole。
  • 地面和光源使用 assets.AssetBaseCfg 类指定,而 Cartpole 使用 assets.ArticulationCfg 类配置。任何不是交互式图元的东西(即既不是资源也不是传感器)在模拟步骤期间都不会被场景处理。
  • 不同的图元的图元路径规范:
    • 地面:/World/defaultGroundPlane
    • 光源:/World/Light
    • Cartpole:{ENV_REGEX_NS}/Robot
  • ENV_REGEX_NS 变量是一个特殊变量,在场景创建期间会被环境名称替换。任何在其图元路径中具有 ENV_REGEX_NS 变量的实体都将为每个环境克隆。此路径由场景对象替换为 /World/envs/env_{i},其中 i 是环境索引。

2. 场景实例化:

  • 我们现在创建一个 scene.InteractiveScene 类的实例,并将配置对象传递给它的构造函数。在创建 CartpoleSceneCfg 的配置实例时,我们使用 num_envs 参数指定要创建的环境副本的数量。这将用于为每个环境克隆场景。
# Design scene
scene_cfg = CartpoleSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
scene = InteractiveScene(scene_cfg)

3. 访问场景元素:

  • 与之前教程中从字典访问实体的方式类似,可以使用 [] 运算符从 InteractiveScene 对象访问场景元素。运算符接受字符串键并返回相应的实体。键是通过每个实体的配置类指定的。例如,Cartpole 在配置类中使用键 "cartpole" 指定。
# Extract scene entities
# note: we only do this here for readability.
robot = scene["cartpole"]

4. 运行模拟循环:

  • 脚本的其余部分看起来类似于之前与 assets.Articulation 交互的脚本,在调用的方法上有一些细微的差别:
    • assets.Articulation.reset()scene.InteractiveScene.reset()
    • assets.Articulation.write_data_to_sim()scene.InteractiveScene.write_data_to_sim()
    • assets.Articulation.update()scene.InteractiveScene.update()
  • 在底层,scene.InteractiveScene 的方法调用场景中实体的相应方法。

总结:

本教程介绍了如何使用 scene.InteractiveScene 创建包含多个资源的场景。我们还看到了如何使用 num_envs 参数为多个环境克隆场景。scene.InteractiveSceneCfgomni.isaac.lab_tasks 扩展下的任务中还有更多示例用法。请查看源代码以了解它们如何用于更复杂的场景。

简而言之,scene.InteractiveScene 提供了一种更便捷、更易于管理的方式来创建和控制 Isaac Sim 中的复杂场景,尤其是在需要处理多个环境或大量场景元素的情况下。

环境创建

Manager-Based RL Environment

这段代码演示了如何在 Isaac Lab 中创建一个基于管理器的强化学习 (RL) 环境,并以倒立摆任务为例,展示了如何配置奖励、终止条件、指令和课程等强化学习要素。

核心目标:

这段代码的目标是创建一个可配置的、基于管理器的倒立摆强化学习环境,使用户能够训练智能体学习如何平衡杆。

代码实现步骤:

  1. 定义场景配置 (CartpoleSceneCfg 类):

    • 使用 @configclass 装饰器将 CartpoleSceneCfg 类定义为配置类,继承自 InteractiveSceneCfg
    • 定义地面、倒立摆机器人和灯光等场景元素的配置。
    • 使用 AssetBaseCfg 配置每个场景元素,包括 Prim 路径、生成配置 (spawn) 和初始状态 (init_state)。
  2. 定义指令配置 (CommandsCfg 类):

    • 使用 @configclass 装饰器将 CommandsCfg 类定义为配置类。
    • 由于倒立摆任务不需要指令,因此使用 mdp.NullCommandCfg() 配置一个空指令。
  3. 定义动作配置 (ActionsCfg 类):

    • 使用 @configclass 装饰器将 ActionsCfg 类定义为配置类。
    • 使用 mdp.JointEffortActionCfg 配置关节力矩动作,指定要控制的关节 ("slider_to_cart") 和缩放比例。
  4. 定义观察配置 (ObservationsCfg 类):

    • 使用 @configclass 装饰器将 ObservationsCfg 类定义为配置类。
    • 定义一个嵌套的 PolicyCfg 类,继承自 ObsGroup,用于配置策略观察组。
      • 定义两个观察项:joint_pos_reljoint_vel_rel,分别使用 mdp.joint_pos_relmdp.joint_vel_rel 函数计算关节的相对位置和速度。
      • __post_init__ 方法中,设置 enable_corruptionFalse (不启用噪声污染) 和 concatenate_termsTrue (将观察项连接成单个张量)。
    • 定义一个 policy 属性,实例化 PolicyCfg 类。
  5. 定义事件配置 (EventCfg 类):

    • 使用 @configclass 装饰器将 EventCfg 类定义为配置类。
    • 定义两个事件项:
      • reset_cart_position: 在重置时 (mode="reset") 随机重置滑块的位置和速度,使用 mdp.reset_joints_by_offset 函数。
      • reset_pole_position: 在重置时 (mode="reset") 随机重置杆的角度和角速度,使用 mdp.reset_joints_by_offset 函数。
  6. 定义奖励配置 (RewardsCfg 类):

    • 使用 @configclass 装饰器将 RewardsCfg 类定义为配置类。
    • 定义五个奖励项:
      • alive: 智能体存活的奖励。
      • terminating: 智能体终止的惩罚。
      • pole_pos: 保持杆直立的奖励。
      • cart_vel: 滑块速度低的奖励。
      • pole_vel: 杆角速度低的奖励。
    • 使用 RewTerm 配置每个奖励项,指定奖励函数、权重和参数。
  7. 定义终止条件配置 (TerminationsCfg 类):

    • 使用 @configclass 装饰器将 TerminationsCfg 类定义为配置类。
    • 定义两个终止条件:
      • time_out: 超时终止,使用 mdp.time_out 函数判断。
      • cart_out_of_bounds: 滑块超出边界终止,使用 mdp.joint_pos_out_of_manual_limit 函数判断。
    • 使用 DoneTerm 配置每个终止条件,指定终止函数和参数。
  8. 定义课程配置 (CurriculumCfg 类):

    • 使用 @configclass 装饰器将 CurriculumCfg 类定义为配置类。
    • 由于倒立摆任务不需要课程,因此使用 pass 跳过配置。
  9. 定义环境配置 (CartpoleEnvCfg 类):

    • 使用 @configclass 装饰器将 CartpoleEnvCfg 类定义为配置类,继承自 ManagerBasedRLEnvCfg
    • 定义场景配置 scene,使用 CartpoleSceneCfg,设置环境数量和环境间距。
    • 定义观察配置 observations,使用 ObservationsCfg
    • 定义动作配置 actions,使用 ActionsCfg
    • 定义事件配置 events,使用 EventCfg
    • 定义课程配置 curriculum,使用 CurriculumCfg
    • 定义奖励配置 rewards,使用 RewardsCfg
    • 定义终止条件配置 terminations,使用 TerminationsCfg
    • 定义指令配置 commands,使用 CommandsCfg
    • __post_init__ 方法中,设置模拟步长、降采样率、最大回合步数和观察视角。
  10. 创建并运行环境 (main 函数):

  • 创建 CartpoleEnvCfg 配置对象 env_cfg
  • 根据命令行参数设置环境数量。
  • 使用 ManagerBasedRLEnv 类创建环境对象 env,传入配置对象 env_cfg
  • 在循环中:
    • 每隔一段时间重置环境。
    • 生成随机动作。
    • 执行环境步骤,获取观察结果、奖励、终止状态和信息。
    • 打印杆的角度。
  • 关闭环境。

关键概念:

  • 基于管理器的强化学习环境: 使用管理器 (Manager) 来管理强化学习环境的各个方面,例如场景、动作、观察、奖励、终止条件、指令和课程。
  • 奖励管理器 (RewardManager): 负责计算智能体的奖励,可以包含多个奖励项 (RewardTerm)。
  • 终止条件管理器 (TerminationManager): 负责判断回合是否终止,可以包含多个终止条件 (TerminationTerm)。
  • 指令管理器 (CommandManager): 负责管理智能体的目标或指令,可以生成、更新和提供指令作为观察。
  • 课程管理器 (CurriculumManager): 负责管理环境的难度,可以根据智能体的学习进度调整任务难度。

总结:

这段代码展示了如何使用 Isaac Lab 创建一个基于管理器的强化学习环境,并以倒立摆任务为例,演示了如何配置场景、动作、观察、奖励、终止条件、指令和课程。通过学习这段代码,可以掌握创建可配置的强化学习环境的基本方法,并将其应用到更复杂的仿真任务中。

Direct Workflow RL Environment

定义了一个名为 CartpoleEnv 的类,它实现了 Isaac Sim 中的 Cartpole 环境。Cartpole 是一个经典的控制问题,目标是通过控制小车的左右移动来保持杆子竖直不倒。

主要功能:

  1. 环境配置 (CartpoleEnvCfg):

    • CartpoleEnvCfg 类继承自 DirectRLEnvCfg,定义了 Cartpole 环境的各种参数,包括:
      • env: 仿真步长、episode 长度、动作缩放比例、动作和观测空间维度等。
      • simulation: 仿真时间步长、渲染间隔等。
      • robot: 小车和杆子的配置,包括关节名称等。
      • scene: 场景配置,包括环境数量、环境间距等。
      • reset: 重置环境时的参数,包括小车最大位置、杆子初始角度范围等。
      • reward scales: 奖励函数的缩放比例,包括存活奖励、终止奖励、杆子位置奖励、小车速度奖励、杆子速度奖励等。
  2. 环境初始化 (CartpoleEnv.init):

    • 初始化环境,包括获取小车和杆子的关节索引、动作缩放比例等。
  3. 场景设置 (CartpoleEnv._setup_scene):

    • 创建小车和杆子模型。
    • 添加地面。
    • 克隆环境,并设置碰撞过滤器。
    • 将小车和杆子添加到场景中。
    • 添加灯光。
  4. 仿真步骤前 (CartpoleEnv._pre_physics_step):

    • 在每个仿真步骤之前,将 Agent 的动作缩放至合适的范围。
  5. 应用动作 (CartpoleEnv._apply_action):

    • 将缩放后的动作应用到小车的关节上,控制小车的移动。
  6. 获取观测值 (CartpoleEnv._get_observations):

    • 获取环境的观测值,包括杆子的角度、杆子的角速度、小车的位置、小车的速度。
  7. 获取奖励 (CartpoleEnv._get_rewards):

    • 根据环境状态计算奖励值,奖励函数的设计鼓励杆子保持竖直,并惩罚小车移动过快或杆子摆动过大。
  8. 获取结束标志 (CartpoleEnv._get_dones):

    • 判断 episode 是否结束,结束条件包括:
      • episode 超过最大长度。
      • 小车超出边界。
      • 杆子角度超过阈值。
  9. 重置环境 (CartpoleEnv._reset_idx):

    • 重置指定环境的状态,包括:
      • 将小车和杆子重置到初始位置。
      • 随机设置杆子的初始角度。
  10. 计算奖励函数 (compute_rewards):

    • 一个辅助函数,用于计算奖励值。

关键概念:

  • Isaac Sim: NVIDIA Omniverse Isaac Sim 是一个用于机器人仿真的平台。
  • Cartpole: 一个经典的控制问题,目标是通过控制小车的左右移动来保持杆子竖直不倒。
  • DirectRLEnv: Isaac Sim 中用于构建强化学习环境的基类。
  • Articulation: Isaac Sim 中用于表示机器人或其他多关节物体的类。
  • Reward Function: 强化学习中的奖励函数,用于评估 Agent 的行为。

代码结构:

  • 代码首先定义了环境配置类 CartpoleEnvCfg
  • 然后定义了环境类 CartpoleEnv,它继承自 DirectRLEnv
  • CartpoleEnv 类实现了环境的初始化、场景设置、仿真步骤、动作应用、观测值获取、奖励获取、结束标志获取和环境重置等功能。
  • 最后定义了一个辅助函数 compute_rewards,用于计算奖励值。

总结:

这段代码实现了一个 Isaac Sim 中的 Cartpole 环境,它可以用于训练强化学习 Agent 来解决 Cartpole 控制问题。代码结构清晰,功能完整,可以作为 Isaac Sim 中构建其他强化学习环境的参考。

环境注册

这段文档解释了如何在 Isaac Sim 中注册自定义环境,以便通过 gymnasium.make() 函数方便地创建环境实例。

背景:

在之前的教程中,我们学习了如何创建自定义的 Cartpole 环境。我们可以通过导入环境类及其配置类来手动创建环境实例。

# create environment configuration
env_cfg = CartpoleEnvCfg()
env_cfg.scene.num_envs = args_cli.num_envs
# setup RL environment
env = ManagerBasedRLEnv(cfg=env_cfg)

虽然这种方法很直接,但是当我们拥有大量的环境时,它就无法扩展。在本教程中,我们将展示如何使用 gymnasium.register() 方法将环境注册到 Gymnasium 注册表中。这允许我们通过 gymnasium.make() 函数创建环境。

代码示例:

from omni.isaac.lab_tasks.utils import parse_env_cfg

def main():
    """Random actions agent with Isaac Lab environment."""
    # create environment configuration
    env_cfg = parse_env_cfg(
        args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
    )
    # create environment
    env = gym.make(args_cli.task, cfg=env_cfg)

代码解释:

  • envs.ManagerBasedRLEnv 类和 envs.DirectRLEnv 类都继承自 gymnasium.Env 类,遵循标准接口。
  • 与传统的 Gym 环境不同,envs.ManagerBasedRLEnv 实现了矢量化环境,这意味着多个环境实例在同一进程中同时运行,所有数据都以批处理方式返回。

使用 Gym 注册表:

  • 要注册环境,我们使用 gymnasium.register() 方法。此方法接受环境名称、环境类的入口点和环境配置类的入口点。
  • 注意: Gymnasium 注册表是一个全局注册表。因此,确保环境名称是唯一的非常重要。否则,注册表在注册环境时会引发错误。

基于管理器的环境:

  • 对于基于管理器的环境,以下代码显示了 omni.isaac.lab_tasks.manager_based.classic.cartpole 子包中 Cartpole 环境的注册调用:
import gymnasium as gym

from . import agents
from .cartpole_env_cfg import CartpoleEnvCfg

##
# Register Gym environments.
##

gym.register(
    id="Isaac-Cartpole-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": CartpoleEnvCfg,
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_cfg.yaml",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:CartpolePPORunnerCfg",
        "skrl_cfg_entry_point": f"{agents.__name__}:skrl_ppo_cfg.yaml",
        "sb3_cfg_entry_point": f"{agents.__name__}:sb3_ppo_cfg.yaml",
    },
)
  • id 参数是环境的名称。按照惯例,我们使用前缀 Isaac- 命名所有环境,以便在注册表中更容易搜索它们。环境的名称通常后跟任务的名称,然后是机器人的名称。例如,对于 ANYmal C 在平坦地形上的腿部运动,环境称为 Isaac-Velocity-Flat-Anymal-C-v0。版本号 v<N> 通常用于指定同一环境的不同变体。否则,环境的名称可能会变得太长且难以阅读。
  • entry_point 参数是环境类的入口点。入口点是 <module>:<class> 形式的字符串。在 Cartpole 环境的情况下,入口点是 omni.isaac.lab.envs:ManagerBasedRLEnv。入口点用于在创建环境实例时导入环境类。
  • env_cfg_entry_point 参数指定环境的默认配置。默认配置使用 omni.isaac.lab_tasks.utils.parse_env_cfg() 函数加载。然后将其传递给 gymnasium.make() 函数以创建环境实例。配置入口点可以是 YAML 文件或 Python 配置类。

直接环境:

  • 对于基于直接的环境,环境注册遵循类似的模式。我们不是将环境的入口点注册为 ManagerBasedRLEnv 类,而是将环境的入口点注册为环境的实现类。此外,我们在环境名称后添加后缀 -Direct 以将其与基于管理器的环境区分开来。
  • 例如,以下代码显示了 omni.isaac.lab_tasks.direct.cartpole 子包中 Cartpole 环境的注册调用:
import gymnasium as gym

from . import agents
from .cartpole_camera_env import CartpoleCameraEnv, CartpoleDepthCameraEnvCfg, CartpoleRGBCameraEnvCfg
from .cartpole_env import CartpoleEnv, CartpoleEnvCfg

##
# Register Gym environments.
##

gym.register(
    id="Isaac-Cartpole-Direct-v0",
    entry_point="omni.isaac.lab_tasks.direct.cartpole:CartpoleEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": CartpoleEnvCfg,
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_cfg.yaml",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:CartpolePPORunnerCfg",
        "skrl_cfg_entry_point": f"{agents.__name__}:skrl_ppo_cfg.yaml",
        "sb3_cfg_entry_point": f"{agents.__name__}:sb3_ppo_cfg.yaml",
    },
)

创建环境:

  • 要将 omni.isaac.lab_tasks 扩展提供的所有环境通知 Gym 注册表,我们必须在脚本开始时导入模块。这将执行 __init__.py 文件,该文件迭代所有子包并注册其各自的环境。
import omni.isaac.lab_tasks  # noqa: F401
  • 在本教程中,任务名称是从命令行读取的。任务名称用于解析默认配置以及创建环境实例。此外,其他解析的命令行参数(例如环境数量、模拟设备以及是否渲染)用于覆盖默认配置。
# create environment configuration
env_cfg = parse_env_cfg(
    args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
)
# create environment
env = gym.make(args_cli.task, cfg=env_cfg)
  • 创建环境后,其余的执行遵循标准的重置和步进操作。

总结:

这段文档解释了如何在 Isaac Sim 中注册自定义环境,以便通过 gymnasium.make() 函数方便地创建环境实例。它涵盖了基于管理器的环境和直接环境的注册过程,并提供了代码示例和详细解释。通过注册环境,我们可以更方便地管理和使用 Isaac Sim 中的大量环境。

训练

使用 Stable Baselines3 库在 Isaac Sim 环境中训练强化学习 (RL) Agent 的脚本。它结合了 Isaac Sim 的环境配置和 Stable Baselines3 的训练流程。

主要功能:

  1. 参数解析和环境配置:

    • 使用 argparse 解析命令行参数,包括是否录制视频、视频参数、环境数量、任务名称、随机种子、最大迭代次数等。
    • 使用 AppLauncher 启动 Isaac Sim 应用程序。
    • 使用 Hydra 加载任务配置文件,并根据命令行参数覆盖环境配置。
    • 创建日志目录,并将环境和 Agent 配置保存到 YAML 和 pickle 文件中。
  2. 环境创建和包装:

    • 使用 gym.make 创建 Isaac Sim 环境。
    • 如果需要录制视频,则使用 gym.wrappers.RecordVideo 包装环境。
    • 使用 Sb3VecEnvWrapper 包装环境,使其兼容 Stable Baselines3。
    • 设置环境的随机种子。
    • 如果配置中指定了输入或价值归一化,则使用 VecNormalize 包装环境。
  3. Agent 创建和训练:

    • 使用 PPO 创建 Stable Baselines3 的 PPO Agent。
    • 配置 Stable Baselines3 的日志记录器。
    • 创建 CheckpointCallback 回调函数,用于定期保存模型 checkpoints。
    • 使用 agent.learn 开始训练 Agent。
    • 训练完成后,保存最终的模型。
  4. 环境关闭:

    • 关闭 Isaac Sim 环境。
    • 关闭 Isaac Sim 应用程序。

关键概念:

  • Isaac Sim: NVIDIA Omniverse Isaac Sim 是一个用于机器人仿真的平台。
  • Stable Baselines3: 一个基于 PyTorch 的强化学习库,提供了各种常用的 RL 算法实现。
  • PPO: 近端策略优化算法,一种常用的策略梯度强化学习算法。
  • VecEnv: Stable Baselines3 中用于并行模拟多个环境的接口。
  • Hydra: 一个用于配置管理的框架,可以方便地管理复杂的配置文件。

代码结构:

  • 脚本首先解析命令行参数和加载 Hydra 配置文件。
  • 然后创建 Isaac Sim 环境,并使用 Stable Baselines3 的包装器进行包装。
  • 接下来创建 PPO Agent,配置日志记录器和回调函数。
  • 最后开始训练 Agent,并在训练完成后保存模型。

总结:

这段代码演示了如何使用 Stable Baselines3 在 Isaac Sim 环境中训练 RL Agent。它结合了 Isaac Sim 的环境配置和 Stable Baselines3 的训练流程,提供了一个完整的 RL 训练脚本示例。

调试

使用 Stable Baselines3 库在 Isaac Sim 环境中播放强化学习 (RL) Agent Checkpoint 的脚本。它加载之前训练好的模型,并在环境中运行 Agent,展示其学习到的策略。

主要功能:

  1. 参数解析和环境配置:

    • 使用 argparse 解析命令行参数,包括是否录制视频、视频参数、是否禁用 Fabric、环境数量、任务名称、Checkpoint 路径等。
    • 使用 AppLauncher 启动 Isaac Sim 应用程序。
    • 解析任务配置文件和 Agent 配置文件。
    • 确定 Checkpoint 路径,如果未指定,则根据 use_last_checkpoint 参数选择最后一个或最佳的 Checkpoint。
  2. 环境创建和包装:

    • 使用 gym.make 创建 Isaac Sim 环境。
    • 如果需要录制视频,则使用 gym.wrappers.RecordVideo 包装环境。
    • 使用 Sb3VecEnvWrapper 包装环境,使其兼容 Stable Baselines3。
    • 如果配置中指定了输入或价值归一化,则使用 VecNormalize 包装环境。
  3. Agent 加载:

    • 使用 PPO.load 加载之前训练好的 PPO Agent 模型。
  4. 环境模拟:

    • 重置环境,获取初始观测值。
    • 在 Isaac Sim 应用程序运行期间,循环执行以下操作:
      • 使用 agent.predict 获取 Agent 的动作。
      • 使用 env.step 执行动作,并获取新的观测值、奖励、是否结束等信息。
      • 如果录制视频,则在录制完成后退出循环。
  5. 环境关闭:

    • 关闭 Isaac Sim 环境。
    • 关闭 Isaac Sim 应用程序。

关键概念:

  • Isaac Sim: NVIDIA Omniverse Isaac Sim 是一个用于机器人仿真的平台。
  • Stable Baselines3: 一个基于 PyTorch 的强化学习库,提供了各种常用的 RL 算法实现。
  • PPO: 近端策略优化算法,一种常用的策略梯度强化学习算法。
  • VecEnv: Stable Baselines3 中用于并行模拟多个环境的接口。
  • Checkpoint: 保存模型参数的文件,用于加载和恢复训练好的模型。

代码结构:

  • 脚本首先解析命令行参数和加载配置文件。
  • 然后创建 Isaac Sim 环境,并使用 Stable Baselines3 的包装器进行包装。
  • 接下来加载之前训练好的 PPO Agent 模型。
  • 最后循环模拟环境,并使用 Agent 的策略进行控制。

总结:

这段代码演示了如何使用 Stable Baselines3 在 Isaac Sim 环境中播放 RL Agent Checkpoint。它加载训练好的模型,并在环境中运行 Agent,展示其学习到的策略。

添加传感器

这段代码演示了如何在 Isaac Sim 中为机器人配置和使用各种传感器,以获取环境信息。以 ANYmal-C 四足机器人为例,展示了如何添加相机传感器、高度扫描传感器和接触传感器。

代码解析:

  1. 初始化和导入:

    • 导入必要的库,包括 omni.isaac.lab 模块,用于与 Isaac Sim 进行交互,以及 torch 用于张量操作。
    • 使用 argparse 解析命令行参数,包括要生成的 ANYmal-C 机器人环境数量 --num_envs
    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  2. 场景配置 (SensorsSceneCfg 类):

    • 使用 @configclass 装饰器将 SensorsSceneCfg 类定义为配置类,继承自 InteractiveSceneCfg
    • 场景元素配置:
      • ground: 定义地面,使用 sim_utils.GroundPlaneCfg() 配置。
      • dome_light: 定义穹顶灯光,使用 sim_utils.DomeLightCfg 配置灯光颜色和强度。
      • robot: 定义 ANYmal-C 机器人,使用预定义的 ANYMAL_C_CFG 并修改 Prim 路径,{ENV_REGEX_NS}/Robot 会根据环境数量生成多个机器人实例,例如 /env_0/Robot, /env_1/Robot 等等。
    • 传感器配置:
      • camera: 定义相机传感器,使用 CameraCfg 配置,包括:
        • prim_path: 相机传感器在场景中的路径,这里相对于机器人基座。
        • update_period: 传感器更新数据的频率,以秒为单位。
        • heightwidth: 相机分辨率。
        • data_types: 传感器获取的数据类型,例如 RGB 图像、深度图像等。
        • spawn: 使用 sim_utils.PinholeCameraCfg 配置针孔相机模型,设置焦距、对焦距离、水平视角和裁剪范围。
        • offset: 使用 CameraCfg.OffsetCfg 配置相机相对于机器人基座的偏移,设置位置、旋转和惯例 ("ros")。
      • height_scanner: 定义高度扫描传感器,使用 RayCasterCfg 配置,包括:
        • prim_path: 传感器在场景中的路径,这里相对于机器人基座。
        • update_period: 传感器更新数据的频率,以秒为单位。
        • offset: 使用 RayCasterCfg.OffsetCfg 配置传感器相对于机器人基座的偏移,设置位置。
        • attach_yaw_only: 是否仅附着在偏航轴上,设置为 True 表示传感器只跟随机器人的偏航旋转。
        • pattern_cfg: 使用 patterns.GridPatternCfg 配置均匀网格模式的光线投射,设置分辨率和大小。
        • debug_vis: 是否启用调试可视化,设置为 True 会在场景中显示光线投射的点。
        • mesh_prim_paths: 要扫描的网格 Prim 路径,这里设置为地面。
      • contact_forces: 定义接触传感器,使用 ContactSensorCfg 配置,包括:
        • prim_path: 传感器在场景中的路径,这里使用正则表达式匹配所有以 "_FOOT" 结尾的 Prim,即机器人的四个脚。
        • update_period: 传感器更新数据的频率,以秒为单位,设置为 0 表示与模拟步长相同。
        • history_length: 要存储的接触信息的历史长度,设置为 6 表示存储最近 6 个模拟步骤的信息。
        • debug_vis: 是否启用调试可视化。
  3. 运行模拟循环 (run_simulator 函数):

    • sim_dt: 获取模拟步长。
    • sim_time: 记录模拟时间。
    • count: 记录模拟步数。
    • 模拟循环:
      • 每 500 步重置场景,包括机器人的根状态和关节状态,并添加一些随机扰动。
      • 应用默认动作到机器人,设置关节位置目标。
      • 执行模拟步骤 (sim.step()),并更新场景 (scene.update(sim_dt))。
      • 打印传感器信息,包括:
        • 相机传感器获取的 RGB 和深度图像的形状。
        • 高度扫描传感器获取的最大高度值。
        • 接触传感器获取的最大接触力。
  4. 主函数 (main 函数):

    • 初始化模拟上下文 (SimulationContext),设置模拟步长为 0.005 秒。
    • 设置主摄像机视角。
    • 使用 SensorsSceneCfg 创建场景配置对象 scene_cfg,设置环境数量和环境间距。
    • 使用 InteractiveScene 类创建场景对象 scene,传入配置对象 scene_cfg
    • 重置模拟器 (sim.reset()),初始化传感器。
    • 调用 run_simulator 函数运行模拟循环。

关键概念:

  • Prim: USD 场景中的基本元素,可以是网格、灯光、相机、传感器等。
  • 传感器 (Sensor): 用于获取环境信息的设备,例如相机、激光雷达、接触传感器等。
  • 更新周期 (Update Period): 传感器更新数据的频率,以秒为单位。
  • 偏移 (Offset): 传感器相对于其父级 Prim 的位置和旋转。
  • 数据类型 (Data Type): 传感器获取的数据类型,例如 RGB 图像、深度图像、点云等。
  • 光线投射 (Ray Casting): 一种用于检测物体碰撞和获取距离信息的技术。
  • 接触传感器 (Contact Sensor): 用于检测物体之间接触的传感器。
  • 交互式场景 (InteractiveScene): Isaac Lab 中用于管理场景的类,提供了方便的 API 用于添加、控制和获取场景元素信息。

总结:

这段代码演示了如何在 Isaac Sim 中为机器人配置和使用各种传感器,以获取环境信息。通过学习这段代码,可以掌握在 Isaac Sim 中添加和使用传感器的方法,并将其应用到更复杂的仿真任务中。

代码示例解读:

  • 代码中使用 configclass 装饰器简化了配置类的定义,使其更易读和维护。
  • 传感器配置使用了 CameraCfgRayCasterCfgContactSensorCfg 等类,这些类提供了丰富的参数来配置不同的传感器类型。
  • 模拟循环中通过访问传感器的 data 属性来获取传感器数据,并进行简单的处理和打印。

使用任务空间控制器控制机器人

这段代码演示了如何在 Isaac Sim 中使用任务空间控制器控制机器人,以 Franka Emika Panda 和 Universal Robots UR10 机械臂为例,展示了如何使用 controllers.DifferentialIKController 类跟踪期望的末端执行器位姿指令。

代码核心目标:

这段代码的目标是展示如何在 Isaac Sim 中使用差分逆运动学 (Differential Inverse Kinematics, IK) 控制器控制机器人的末端执行器达到目标位姿。

代码实现步骤:

  1. 初始化 & 导入:

    • 导入必要的库,包括用于控制 Isaac Sim 的 omni.isaac.lab 模块以及 torch 用于张量操作。
    • 使用 argparse 解析命令行参数,包括要使用的机器人类型 --robot (默认 Franka Emika Panda) 和要生成的机器人环境数量 --num_envs
    • 使用 AppLauncher 类启动 Isaac Sim 应用程序。
  2. 场景配置 (TableTopSceneCfg 类):

    • 使用 @configclass 装饰器将 TableTopSceneCfg 类定义为配置类,继承自 InteractiveSceneCfg
    • 场景元素配置:
      • ground: 定义地面,使用 sim_utils.GroundPlaneCfg() 配置,并设置初始位置。
      • dome_light: 定义穹顶灯光,使用 sim_utils.DomeLightCfg 配置灯光颜色和强度。
      • table: 定义桌子,使用 sim_utils.UsdFileCfg 从 USD 文件加载桌子模型,并设置缩放比例。
      • robot: 根据命令行参数 --robot 选择机器人模型,使用预定义的 FRANKA_PANDA_HIGH_PD_CFGUR10_CFG,并修改 Prim 路径,{ENV_REGEX_NS}/Robot 会根据环境数量生成多个机器人实例。
  3. 运行模拟循环 (run_simulator 函数):

    • 创建差分 IK 控制器:
      • 使用 DifferentialIKControllerCfg 配置控制器,包括:
        • command_type: 指令类型,设置为 "pose",表示控制末端执行器位姿。
        • use_relative_mode: 是否使用相对模式,设置为 False,表示使用绝对位姿控制。
        • ik_method: IK 求解方法,设置为 "dls",表示使用阻尼最小二乘法。
      • 使用 DifferentialIKController 类创建控制器对象 diff_ik_controller,传入配置对象、环境数量和设备。
    • 创建可视化标记:
      • 使用 VisualizationMarkers 类创建两个标记对象,ee_marker 用于可视化当前末端执行器位置,goal_marker 用于可视化目标位置。
    • 定义目标位姿:
      • 创建一个包含三个目标位姿的列表 ee_goals,每个位姿包含位置和方向信息。
      • 将目标位姿列表转换为 torch.tensor
    • 初始化控制器指令:
      • 创建一个缓冲区 ik_commands 用于存储控制器指令,初始值为第一个目标位姿。
    • 获取机器人关节和刚体索引:
      • 根据机器人类型,使用 SceneEntityCfg 类获取机器人手臂关节和末端执行器刚体的索引。
      • 对于固定基座机器人,雅可比矩阵的末端执行器索引需要减 1,因为根刚体不包含在雅可比矩阵中。
    • 模拟循环:
      • 每 150 步重置场景,包括机器人的关节状态、控制器指令和目标位姿索引。
      • 获取机器人雅可比矩阵、末端执行器位姿、基座位姿和关节位置。
      • 使用 subtract_frame_transforms 函数将末端执行器位姿转换到基座坐标系。
      • 使用 diff_ik_controller.compute 函数计算目标关节位置。
      • 使用 robot.set_joint_position_target 函数设置机器人的关节位置目标。
      • 执行模拟步骤 (sim.step()),并更新场景 (scene.update(sim_dt))。
      • 更新可视化标记的位置。
  4. 主函数 (main 函数):

    • 初始化模拟上下文 (SimulationContext),设置模拟步长为 0.01 秒。
    • 设置主摄像机视角。
    • 使用 TableTopSceneCfg 创建场景配置对象 scene_cfg,设置环境数量和环境间距。
    • 使用 InteractiveScene 类创建场景对象 scene,传入配置对象 scene_cfg
    • 重置模拟器 (sim.reset()),初始化场景。
    • 调用 run_simulator 函数运行模拟循环。

关键概念:

  • 任务空间控制 (Task-Space Control): 直接控制机器人末端执行器在空间中的位姿,而不是控制各个关节的角度。
  • 差分逆运动学 (Differential Inverse Kinematics, IK): 一种计算机器人关节角度以达到目标末端执行器位姿的方法,通常使用雅可比矩阵进行计算。
  • 阻尼最小二乘法 (Damped Least Squares): 一种求解逆运动学问题的常用方法,可以解决奇异性问题。
  • 雅可比矩阵 (Jacobian Matrix): 描述机器人末端执行器速度与关节速度之间关系的矩阵。

总结:

这段代码展示了如何在 Isaac Sim 中使用差分 IK 控制器实现机器人的任务空间控制,通过设置目标末端执行器位姿,控制器可以自动计算出各个关节的目标角度,并控制机器人运动到目标位姿。

posted on 2024-08-28 14:13  FrostyForest  阅读(13)  评论(0编辑  收藏  举报