Isaacgym使用操作指南
背景知识
Isaac Gym 是由 NVIDIA 提供的一个高性能仿真平台,专门用于大规模的机器人学习和强化学习(RL)任务。它结合了物理仿真、GPU加速、深度学习框架互操作性等特点,使得研究人员和开发者可以快速进行复杂的机器人仿真和训练。以下是对 Isaac Gym 的详细介绍:
1. 高性能 GPU 加速
Isaac Gym 的一个显著特点是它利用 GPU 进行物理仿真加速。传统的物理引擎主要在 CPU 上运行,速度较慢,特别是在需要同时模拟多个环境时。Isaac Gym 将物理计算搬到 GPU 上,并行处理,使得可以同时运行数千个仿真环境,极大地提高了训练效率。
2. 多环境并行仿真
Isaac Gym 支持多环境并行仿真,这意味着你可以在同一块 GPU 上同时运行数千个机器人实例。这种能力对强化学习训练特别有用,因为它可以显著增加数据样本量,从而加快策略的收敛速度。
3. 深度学习框架集成
Isaac Gym 与流行的深度学习框架(如 PyTorch)无缝集成。通过提供与这些框架的互操作工具,Isaac Gym 可以直接在 GPU 上生成和操作张量,无需将数据复制到 CPU。这种紧密的集成减少了数据传输的开销,使得模型训练和仿真能够更高效地协同工作。
4. 物理引擎
Isaac Gym 内部使用了 NVIDIA PhysX 引擎,这是一种高精度、稳定的物理仿真引擎,能够处理刚体、关节、布料、流体等各种物理现象。通过这个引擎,Isaac Gym 能够提供逼真的物理互动,适用于从机器人学到计算机视觉等各种应用。
5. 强化学习支持
Isaac Gym 的设计特别考虑了强化学习应用。它提供了许多适用于 RL 任务的功能,例如并行环境重置、基于 GPU 的观察和奖励计算、随机化环境参数等。这些功能使得训练深度强化学习代理变得更加简单和高效。
6. Python API
Isaac Gym 提供了 Python API,用户可以使用 Python 编写仿真和训练脚本。这使得它更易于使用,并且可以与其他 Python 工具(如 NumPy、SciPy)无缝集成。
7. 应用场景
Isaac Gym 被广泛应用于各种机器人仿真任务,例如:
- 机器人操控:训练机器人手臂进行抓取、操作等任务。
- 移动机器人:开发自动导航、路径规划算法。
- 强化学习:在虚拟环境中训练复杂的策略,如步态生成、游戏AI等。
8. 生态系统
Isaac Gym 是 NVIDIA Isaac 机器人平台的一部分。Isaac 机器人平台包括硬件、软件、AI 模型以及工具链,支持从仿真到真实机器人的完整工作流。Isaac Gym 与其他 Isaac 工具(如 Isaac SDK 和 Omniverse)兼容,允许开发者在仿真中验证算法后,无缝地将其部署到真实机器人上。
总结
Isaac Gym 是一个强大的仿真工具,特别适合那些需要进行大规模并行仿真和训练的机器人和强化学习任务。通过 GPU 加速、深度学习集成和丰富的物理仿真能力,Isaac Gym 能够显著提高仿真和训练效率,是机器人学和 AI 研究中的一大利器。
常用api
isaacgym库
import isaacgym
主要常用的api
from isaacgym import gymapi, gymutil, gymtorch
-
gymapi是最核心的
-
gymtorch是和pytorch交互的
-
gymutil是一些辅助工具
设置仿真参数
# 初始化仿真
gym = gymapi.acquire_gym()
# 初始化仿真参数
sim_params = gymapi.SimParams()
# 设置仿真每个步骤的所用时间
sim_params.dt = 0.01
# 设置是否启动physX物理
sim_params.physx.use_gpu = True
# 设置是否启动GPU并行计算
sim_params.use_gpu_pipeline = True
# 创建一个仿真, 计算的设备号,渲染的设备号,
sim = gym.create_sim(compute_device_id, graphics_device_id, gymapi.SIM_PHYSX, sim_params)
创建底面平面
add ground plane
是一个用于在模拟环境中创建地面平面的函数调用。这个函数用于在模拟环境中添加一个物理上可以与机器人交互的平面,通常用于模拟机器人行走或导航的场景。
以下是如何解释 add ground plane
函数调用的步骤:
- 定义地面平面参数:
首先,定义地面平面的参数,如材质、摩擦系数等。
这些参数可以用于定义平面的属性,如它是由什么材料制成的,它的摩擦系数是多少,以及它是否可以移动或旋转。
- 调用函数添加地面平面:
使用 gym.add_ground(sim, plane_params)
函数调用,在模拟环境中添加一个地面平面。
其中 sim
是模拟环境的句柄,plane_params
是定义地面平面参数的对象。
- 创建视图:
使用 gym.create_viewer(sim, gymapi.CameraProperties())
函数调用,创建一个用于查看模拟环境的视图。
其中 sim
是模拟环境的句柄,gymapi.CameraProperties()
是用于定义相机属性的对象。
- 使用视图查看模拟环境:
创建视图后,可以使用它来查看模拟环境中的地面平面和机器人等物体。
视图可以用于监控模拟过程,调整模拟参数,或者进行其他与模拟相关的操作。
# add ground plane
plane_params = gymapi.PlaneParams()
gym.add_ground(sim, plane_params)
# create viewer
viewer = gym.create_viewer(sim, gymapi.CameraProperties())
加载资产
在 Isaac Gym 中,load_asset
是一个函数调用,用于加载预先定义好的资产(asset)到模拟环境中。这些资产通常包括机器人模型、传感器、环境布局等,它们是模拟和训练机器人行为的基础。
以下是 load_asset
函数的一些关键点:
-
资产定义:
在 Isaac Gym 中,资产是由一系列的文件和参数定义的,这些文件和参数描述了资产的外观、物理属性、传感器配置等。
资产可以是一个机器人模型,包括它的几何形状、关节和驱动器;也可以是一个传感器,如摄像头或激光扫描仪;还可以是一个环境布局,包括墙壁、地板和障碍物等。
-
加载资产到模拟环境:
使用
load_asset
函数调用,将资产加载到模拟环境中。该函数接受模拟环境的句柄(
sim
)和资产的定义参数作为输入,并返回资产的句柄。 -
资产句柄:
加载资产后,会得到一个资产的句柄,这个句柄可以用于后续的操作,如设置资产的属性、控制资产的运动等。
-
使用资产进行模拟和训练:
- 在 Isaac Gym 中,加载资产是进行模拟和训练机器人行为的重要步骤。
- 资产提供了机器人可以交互的环境和设备,使机器人能够执行各种任务,如导航、抓取、避障等。
以下是 AssetOptions
结构体中提到的几个关键选项的说明:
(1)fix_base_link:
-
这个选项用于指定资产的基链接是否固定在模拟环境中。
-
如果设置为
True
,基链接将不会移动或旋转,从而保持资产的稳定。 -
这通常用于机器人模型,以确保其不会在运动过程中意外移动或旋转。
(2) flip_visual_attachments:
-
这个选项用于指定资产的视觉附件(如摄像头)是否需要翻转。
-
如果设置为
True
,资产的视觉附件将会在加载时被翻转,这可能会影响资产的外观和行为。 -
这通常用于解决视觉附件在资产模型中的方向问题,确保它们在模拟环境中正确地指向目标。
(3) armature:
-
这个选项用于指定资产的骨架(armature)的厚度。
-
如果设置为非零值,资产的骨架将具有指定的厚度,这可能会影响资产的外观和行为。
-
骨架厚度可以帮助资产在模拟环境中更好地模拟真实物体的物理行为,如碰撞和变形。
总之,
AssetOptions
结构体中包含的这些选项允许开发者自定义资产的行为和外观。通过设置这些选项,可以更好地控制资产在模拟环境中的行为,并确保它们能够正确地执行模拟任务。
# 初始化资产选项
asset_options = gymapi.AssetOptions()
asset_options.fix_base_link = True
asset_options.flip_visual_attachments = True
asset_options.armature = 0.01
# asset_root 资产路径
my_asset = gym.load_asset(sim, asset_root, asset_file, asset_options)
创建环境
在 Isaac Gym 中,gym.create_env
是一个函数调用,用于创建一个环境(env)在模拟(sim)中。这个环境通常包含各种物体和结构,用于测试和训练机器人的行为。
以下是 gym.create_env
函数的一些关键点:
- 模拟环境:
sim
是 Isaac Gym 模拟环境的句柄,它代表模拟的物理引擎和环境设置。
- 环境界限:
env_lower
和env_upper
是一对数对,分别代表环境的下界和上界。- 这两个参数定义了环境的空间范围,即环境的大小和形状。
- 环境布局:
num_per_row
是一个整数,代表环境中的物体每行有多少个。- 这个参数用于定义环境中的物体布局,如它们的排列方式和数量。
- 创建环境:
- 使用
gym.create_env
函数调用,在指定的模拟环境中创建一个环境。 - 函数会根据
env_lower
、env_upper
和num_per_row
参数创建一个具有特定布局的环境。
- 使用
- 环境句柄:
- 创建环境后,会得到一个环境的句柄,这个句柄可以用于后续的操作,如设置环境的属性、控制环境中的物体等。
- 使用环境进行模拟和训练:
- 在 Isaac Gym 中,创建环境是进行模拟和训练机器人行为的重要步骤。
- 环境提供了机器人可以交互的环境和设备,使机器人能够执行各种任务,如导航、抓取、避障等。
# Set up the env grid
num_envs = 36
spacing = 1.0
env_lower = gymapi.Vec3(-spacing, 0.0, -spacing)
env_upper = gymapi.Vec3(spacing, spacing, spacing)
num_per_row = int(math.sqrt(num_envs))
for i in range(num_envs):
# create env
env = gym.create_env(sim, env_lower, env_upper, num_per_row)
envs.append(env)
# 从资产中创建演员
franka_handle = gym.create_actor(env, franka_asset, pose, "franka", i, 2)
body_dict = gym.get_actor_rigid_body_dict(env, franka_handle)
props = gym.get_actor_rigid_body_states(env, franka_handle, gymapi.STATE_POS)
hand_handle = body = gym.find_actor_rigid_body_handle(env, franka_handle, franka_hand)
在 Isaac Gym 中,这些代码片段用于创建一个名为 “franka” 的 Franka 机器人演员(actor)并获取与该演员相关的刚体(rigid body)句柄和状态。
franka_handle = gym.create_actor(env, franka_asset, pose, "franka", i, 2)
:- 创建一个名为 “franka” 的 Franka 机器人演员。
env
是模拟环境的句柄。franka_asset
是包含 Franka 机器人模型和属性的资产。pose
是演员在环境中的初始位置和方向。"franka"
是演员的名称。i
是一个整数,可能用于表示演员的索引或标识。2
是一个整数,可能用于表示演员的某种属性或配置。
body_dict = gym.get_actor_rigid_body_dict(env, franka_handle)
:- 获取与名为 “franka” 的演员相关的所有刚体句柄的字典。
env
是模拟环境的句柄。franka_handle
是演员的句柄。
props = gym.get_actor_rigid_body_states(env, franka_handle, gymapi.STATE_POS)
:- 获取与名为 “franka” 的演员相关的刚体状态。
env
是模拟环境的句柄。franka_handle
是演员的句柄。gymapi.STATE_POS
表示只获取刚体的位置状态。
hand_handle = body = gym.find_actor_rigid_body_handle(env, franka_handle, franka_hand)
:- 查找与名为 “franka” 的演员相关的名为 “franka_hand” 的刚体句柄。
env
是模拟环境的句柄。franka_handle
是演员的句柄。franka_hand
是刚体的名称或标识。
这些代码片段是 Isaac Gym 环境中用于创建和操作机器人演员的标准操作。通过这些操作,可以控制机器人演员在环境中的位置、姿态和行为。
准备好仿真设置
在 Isaac Gym 中,gym.prepare_sim
是一个函数调用,用于准备模拟环境,以便开始模拟或训练过程。这个函数通常在创建模拟环境之后被调用,用于初始化模拟环境,确保所有资产和设置都已经正确加载和配置。
以下是 gym.prepare_sim
函数的一些关键点:
- 模拟环境准备:
gym.prepare_sim
函数用于准备模拟环境,使其处于可以开始模拟或训练的状态。- 函数会根据之前设置的参数和配置,初始化模拟环境中的资产、传感器、机器人等。
- 资产加载和配置:
- 函数会加载之前通过
gym.load_asset
函数加载的资产,并根据资产的定义参数配置资产的属性。 - 资产的属性包括几何形状、物理属性、传感器配置等。
- 函数会加载之前通过
- 环境配置:
- 函数还会配置环境的其他参数,如重力、摩擦系数、碰撞检测等。
- 这些参数会影响模拟环境的行为和物理特性。
- 准备状态:
- 调用
gym.prepare_sim
函数后,模拟环境将被设置为准备状态,可以开始模拟或训练过程。 - 此时,模拟环境中的所有资产和设置都已经就绪,可以被激活和操作。
- 调用
- 使用模拟环境:
- 在 Isaac Gym 中,调用
gym.prepare_sim
函数是开始模拟或训练机器人行为的重要步骤。 - 模拟环境提供了机器人可以交互的环境和设备,使机器人能够执行各种任务,如导航、抓取、避障等。
总之,gym.prepare_sim
函数在 Isaac Gym 中用于准备模拟环境,使其处于可以开始模拟或训练的状态。通过调用这个函数,可以确保模拟环境中的所有资产和设置都已经正确加载和配置,为后续的模拟或训练过程做好准备。
- 在 Isaac Gym 中,调用
gym.prepare_sim(sim)
张量
第一张图片:物理状态张量
Tensor | 描述 | 形状 | 用法 |
---|---|---|---|
Actor root state tensor | 表示演员根身体的状态(位置、方向、线速度、角速度) | (num_actors, 13) | Get/Set |
DOF state tensor | 表示所有自由度的状态(位置和速度) | (num_dofs, 2) | Get/Set |
Rigid body state tensor | 表示所有刚体的状态(位置、方向、线速度、角速度) | (num_bodies, 13) | Get |
DOF force tensor | 每个自由度所经历的净力 | (num_dofs, 1) | Get |
Force sensor tensor | 用户定义的力传感器位置处的力和扭矩 | (num_force_sensors, 6) | Get |
Net contact force tensor | 每个刚体所经历的净接触力 | (num_bodies, 3) | Get |
Jacobian matrix tensor | 雅可比矩阵 | 根据演员类型变化 | Get |
Mass matrix tensor | 广义质量矩阵 | 根据演员类型变化 | Get |
第二张图片:物理控制张量
Tensor | 描述 | 形状 | 应用于 |
---|---|---|---|
DOF actuation force tensor | 施加到自由度的力或扭矩 | (num_dofs, 1) | 所有演员或索引的子集 |
DOF position target tensor | 自由度的PD位置目标 | (num_dofs, 1) | 所有演员或索引的子集 |
DOF velocity target tensor | 自由度的PD速度目标 | (num_dofs, 1) | 所有演员或索引的子集 |
Rigid body force tensor | 施加到刚体的力 | (num_bodies, 3) | 所有演员 |
Rigid body torque tensor | 施加到刚体的扭矩 | (num_bodies, 3) | 所有演员 |
这两张表分别列出了物理状态张量和物理控制张量的名称、描述、形状及其应用情况。物理状态张量描述了物理系统中不同部分的当前状态信息,而物理控制张量则涉及对系统的操作或施加的控制力。
获取张量
这段代码的作用是从物理仿真环境中获取演员的根状态张量和自由度(DOF)的状态张量,并将这些状态张量包装为PyTorch张量,便于在GPU或CPU上进一步操作和计算。
详细解释:
-
获取状态张量描述符
root_states_desc = gym.acquire_actor_root_state_tensor(sim) dof_state_desc = gym.acquire_dof_state_tensor(sim)
gym.acquire_actor_root_state_tensor(sim)
:从模拟环境sim
中获取所有演员的根状态张量的描述符。这包含了每个演员的根状态信息(如位置、方向、速度等)。gym.acquire_dof_state_tensor(sim)
:从模拟环境sim
中获取所有自由度(DOF)的状态张量的描述符。这包含了每个自由度的状态信息(如关节位置和速度)。
这些描述符实际上是指向在GPU或CPU上存储的原始数据缓冲区的指针。它们独立于任何特定的深度学习框架。
-
将状态张量包装为PyTorch张量
root_states = gymtorch.wrap_tensor(root_states_desc) dof_states = gymtorch.wrap_tensor(dof_state_desc)
gymtorch.wrap_tensor(root_states_desc)
:将root_states_desc
描述符包装为一个PyTorch张量root_states
。这使得你可以直接在PyTorch中对这些状态数据进行操作,而无需将数据复制到PyTorch中。gymtorch.wrap_tensor(dof_state_desc)
:将dof_state_desc
描述符包装为一个PyTorch张量dof_states
。同样,这允许在PyTorch中直接操作自由度的状态数据。
关键点:
- 无数据复制:通过
gymtorch.wrap_tensor
,数据不会被复制,而是直接在原始缓冲区的基础上进行操作。这提高了效率,特别是在处理大量物理模拟数据时。 - 兼容性:这个方法能够在不同的硬件设备(如CPU或GPU)上无缝操作,并且同样的代码可以在不同的设备上运行,适应不同的计算需求。
这段代码是为物理模拟场景准备的,用于高效获取并操作物理状态数据,常用于机器人仿真、游戏物理引擎或其他需要处理大量物理状态信息的应用中。
root_states_desc = gym.acquire_actor_root_state_tensor(sim)
dof_state_desc = gym.acquire_dof_state_tensor(sim)
root_states = gymtorch.wrap_tensor(root_states_desc)
dof_states = gymtorch.wrap_tensor(dof_state_desc)
张量reshape和切片
这段代码展示了如何对获取的物理状态张量进行形状调整(reshape),并提取其中的具体物理量,如位置、四元数(用于表示旋转)、线速度和角速度等。让我们详细分析每一行代码的作用。
1. 调整张量形状
root_states_vec = root_states.view(num_envs, actors_per_env, 13)
dof_states_vec = root_states.view(num_envs, dofs_per_env, 2)
-
root_states_vec = root_states.view(num_envs, actors_per_env, 13)
:- 将
root_states
张量的形状调整为(num_envs, actors_per_env, 13)
。 num_envs
表示环境的数量,actors_per_env
表示每个环境中的演员数量,13
表示每个演员根状态的13个元素(位置、旋转、线速度、角速度等)。
- 将
-
dof_states_vec = root_states.view(num_envs, dofs_per_env, 2)
:- 将
dof_states
张量的形状调整为(num_envs, dofs_per_env, 2)
。 dofs_per_env
表示每个环境中的自由度数量,2
表示每个自由度的两个状态元素(位置和速度)。
- 将
2. 提取具体物理量
root_p = root_states_vec[..., 0:3] # positions
root_q = root_states_vec[..., 3:7] # quaternions
root_v = root_states_vec[..., 7:10] # linear velocities
root_a = root_states_vec[..., 10:13] # angular velocities
dof_p = dof_states_vec[..., 0] # positions
dof_v = dof_states_vec[..., 1] # velocities
-
root_p = root_states_vec[..., 0:3]
:- 提取根状态张量中的前三个元素,即每个刚体的位置。
[..., 0:3]
表示提取每个根状态张量的第0到第2列(共3列)。
- 提取根状态张量中的前三个元素,即每个刚体的位置。
-
root_q = root_states_vec[..., 3:7]
:- 提取根状态张量中的第3到第6个元素,即刚体的四元数,用于表示旋转。
-
root_v = root_states_vec[..., 7:10]
:- 提取根状态张量中的第7到第9个元素,即刚体的线速度。
-
root_a = root_states_vec[..., 10:13]
:- 提取根状态张量中的第10到第12个元素,即刚体的角速度。
-
dof_p = dof_states_vec[..., 0]
:- 提取自由度状态张量的第0个元素,即关节位置。
-
dof_v = dof_states_vec[..., 1]
:- 提取自由度状态张量的第1个元素,即关节速度。
这段代码从获取的根状态和自由度状态张量中提取了具体的物理量,分别是位置、旋转(四元数)、线速度、角速度、关节位置和关节速度。通过调整张量的形状,代码可以轻松地从物理状态数据中访问这些信息,这在处理多环境、多演员的物理仿真时非常有用。
root_states_vec = root_states.view(num_envs, actors_per_env, 13)
dof_states_vec = root_states.view(num_envs, dofs_per_env, 2)
root_p = root_states_vec[..., 0:3] # positions
root_q = root_states_vec[..., 3:7] # quaternions
root_v = root_states_vec[..., 7:10] # linear velocities
root_a = root_states_vec[..., 10:13] # angular velocities
dof_p = dof_states_vec[..., 0] # positions
dof_p = dof_states_vec[..., 1] # velocities
更新状态张量
刷新状态张量
gym.refresh_actor_root_state_tensor(sim)
gym.refresh_dof_state_tensor(sim)
- 解释:
gym.refresh_actor_root_state_tensor(sim)
:刷新演员根状态张量。这个操作将确保所有与PyTorch张量相关的视图(view)得到更新,以反映当前仿真步骤后的最新状态。gym.refresh_dof_state_tensor(sim)
:刷新自由度状态张量。同样地,它会更新与自由度相关的PyTorch张量视图。
重要性
- 数据同步:通过
refresh_actor_root_state_tensor
和refresh_dof_state_tensor
,可以保证在仿真步骤后,程序中用于进一步计算或分析的PyTorch张量始终与仿真中的物理状态保持同步。这对于实时控制或调试非常关键。 - 持续仿真:在这个主循环中,仿真将不断地运行,并持续更新物体的状态。每个仿真时间步后,状态张量都可以被立即刷新并用于下一步的计算或决策。
这段代码是一个典型的物理仿真主循环。在每个仿真步中,它推进了仿真的物理状态,并且刷新了与这些状态相关的张量,确保所有后续计算和控制都基于最新的仿真数据。这种结构广泛应用于机器人控制、游戏引擎仿真以及任何需要实时物理仿真的场景中。
# simulation main loop
while True:
# step the simulation
gym.simulate(sim)
# refresh state tentors
# - this will refresh all the tensor views in Pytorch
gym.refresh_actor_root_state_tensor(sim)
gym.refresh_dof_state_tensor(sim)
加入控制
这段代码展示了如何在仿真环境中为每个自由度(DOF)生成随机力,并将这些力应用于仿真中的物体,还展示了如何使用位置和速度目标进行比例-微分(PD)控制。下面是对每一部分代码的详细解释:
1. 生成随机力
forces = 1.0 - 2.0 * torch.rand((num_envs, dofs_per_env), dtype=torch.float32, device='cuda:0')
- 解释:
- 这一行代码使用
torch.rand
函数生成了一个形状为(num_envs, dofs_per_env)
的随机张量。torch.rand
会生成一个范围在[0, 1)
之间的均匀分布随机数。 1.0 - 2.0 * torch.rand(...)
将这个随机数映射到[-1.0, 1.0)
的范围内。dtype=torch.float32
指定了生成张量的类型为32位浮点数。device='cuda:0'
指定张量在GPU上生成,cuda:0
表示第一个GPU设备。
- 这一行代码使用
2. 将PyTorch张量转换为原始张量描述符
forces_desc = gymtorch.unwrap_tensor(forces)
- 解释:
gymtorch.unwrap_tensor(forces)
将PyTorch张量forces
转换为一个原始的张量描述符。这是因为gym
库需要的是原始描述符来与物理仿真环境进行交互。- 这个步骤确保生成的随机力可以在后续的仿真操作中被正确应用。
3. 应用力
gym.set_dof_actuation_force_tensor(sim, forces_desc)
- 解释:
gym.set_dof_actuation_force_tensor(sim, forces_desc)
将生成的随机力应用到仿真中的每个自由度。- 这个函数接受仿真环境
sim
和之前生成的力描述符forces_desc
,然后将这些力施加到相应的自由度上,控制仿真中的物体运动。
4. 使用PD控制
gym.set_dof_position_target_tensor(sim, pos_targets_desc)
gym.set_dof_velocity_target_tensor(sim, vel_targets_desc)
- 解释:
gym.set_dof_position_target_tensor(sim, pos_targets_desc)
:为每个自由度设置位置目标。这通常用于PD控制中的比例控制部分,目标位置将决定物体应该移动到哪里。gym.set_dof_velocity_target_tensor(sim, vel_targets_desc)
:为每个自由度设置速度目标。这是PD控制中的微分控制部分,控制物体运动的速度。pos_targets_desc
和vel_targets_desc
是分别对应位置和速度目标的张量描述符。
这段代码展示了如何在仿真环境中生成随机力并应用到自由度上,以及如何使用PD控制来设置位置和速度目标。通过这些操作,用户可以在仿真中实现复杂的物体运动控制,适用于机器人仿真、物理仿真和其他需要实时力控制的场景。
- 随机力:用于随机施加力,使仿真中的物体运动。
- PD控制:精确控制物体的位置和速度,以实现稳定和期望的运动模式。
# generate a random force for each DOF in the simulation
forces = 1.0 - 2.0 * torch.rand((num_envs, dofs_per_env), dtype=torch.float32, device='cuda:0')
# use interop utility to cast Pytorch tensor to raw tensor descriptor
forces_desc = gymtorch.unwrap_tensor(forces)
# apply the forces
gym.set_dof_actuation_force_tensor(sim, forces_desc)
# can also use PD controls
gym.set_dof_position_target_tensor(sim, pos_targets_desc)
gym.set_dof_velocity_target_tensor(sim, vel_targets_desc)
构建一个简单的任务的框架(以倒立摆为例)
class CartPole(BaseTask):
# common callbacks
def create_sim(self):
"create environments and actors"
def pre_physics_step(self, actions):
"apply actions"
def post_physics_step(self):
"compute observations, rewards and resets"
计算观测结果和奖励
这段代码定义了一个物理仿真环境中用于计算观测和奖励的类方法,主要应用于类似倒立摆(cartpole)这样的控制任务。以下是对每个部分的详细解释:
1. 计算观测(compute_observations
方法)
def compute_observations(self):
# refresh state tensor
self.gym.refresh_dof_state_tensor(self.gym)
# copy DOF states to observation tensor
self.obs_buf[:, 0] = self.dof_pos[:, 0]
self.obs_buf[:, 1] = self.dof_vel[:, 0]
self.obs_buf[:, 2] = self.dof_pos[:, 1]
self.obs_buf[:, 3] = self.dof_vel[:, 1]
-
刷新状态张量:
self.gym.refresh_dof_state_tensor(self.gym)
:刷新自由度状态张量,确保后续获取的自由度位置和速度数据是最新的。
-
填充观测缓冲区:
self.obs_buf[:, 0] = self.dof_pos[:, 0]
:将第一个自由度(通常是小车的位置)的位置填入观测缓冲区的第0列。self.obs_buf[:, 1] = self.dof_vel[:, 0]
:将第一个自由度(小车)的速度填入观测缓冲区的第1列。self.obs_buf[:, 2] = self.dof_pos[:, 1]
:将第二个自由度(通常是杆的角度)的位置填入观测缓冲区的第2列。self.obs_buf[:, 3] = self.dof_vel[:, 1]
:将第二个自由度(杆)的速度填入观测缓冲区的第3列。
2. 计算奖励(compute_reward
方法)
def compute_reward(self):
cart_pos = self.obs_buf[:,0]
cart_vel = self.obs_buf[:,1]
pole_angle = self.obs_buf[:,2]
pole_vel = self.obs_buf[:,3]
self.rew_buf[:] = compute_cartpole_reward(cart_pos, cart_vel, pole_angle, pole_vel)
-
提取观测数据:
cart_pos = self.obs_buf[:,0]
:获取观测缓冲区中的小车位置。cart_vel = self.obs_buf[:,1]
:获取观测缓冲区中的小车速度。pole_angle = self.obs_buf[:,2]
:获取观测缓冲区中的杆角度。pole_vel = self.obs_buf[:,3]
:获取观测缓冲区中的杆速度。
-
计算奖励:
self.rew_buf[:] = compute_cartpole_reward(cart_pos, cart_vel, pole_angle, pole_vel)
:调用compute_cartpole_reward
函数,基于观测值计算每个环境的奖励,并将结果存储在奖励缓冲区中。
3. 计算倒立摆奖励(compute_cartpole_reward
函数)
# use the torchscript JIT compiler to run computations on GPU
@torch.jit.script
def compute_cartpole_reward(cart_pos, cart_vel, pole_angle, pole_vel):
# type: (tensor, tensor, tensor, tensor) -> tensor
angle_penalty = pole_angle * pole_vel
vel_penalty = 0.01 * torch.abs(cart_vel) - 0.005 * torch.abs(pole_vel)
return 1.0 - angle_penalty - vel_penalty
-
角度惩罚:
angle_penalty = pole_angle * pole_vel
:计算角度惩罚,基于杆的角度和角速度。这个惩罚项会使得杆的摆动越剧烈,得到的奖励越少。
-
速度惩罚:
vel_penalty = 0.01 * torch.abs(cart_vel) - 0.005 * torch.abs(pole_vel)
:计算速度惩罚。这里小车的速度越大惩罚越大,而杆的速度越大(摆动越快),惩罚越小。
-
奖励计算:
return 1.0 - angle_penalty - vel_penalty
:计算最终的奖励。初始值为1.0,通过扣除角度惩罚和速度惩罚来确定最终的奖励值。
这段代码实现了一个倒立摆(cartpole)任务的基本逻辑,其中包括计算观测值和计算奖励。奖励函数的设计旨在鼓励杆保持直立,同时控制小车的速度。通过使用PyTorch的torch.jit.script
,代码可以进行进一步优化和加速,这在实时仿真或训练深度强化学习模型时尤其重要。
加入action
这段代码定义了一个 pre_physics_step
方法,用于在每次物理仿真步骤之前根据给定的动作(actions
)为自由度(DOF)施加相应的力。以下是对代码的详细解释:
1. 准备DOF力张量
forces = torch.zeros((num_envs, dofs_per_env), dtype=torch.float32, device=self.device)
- 解释:
- 这一行代码创建了一个全零的张量
forces
,其形状为(num_envs, dofs_per_env)
。 num_envs
表示环境的数量,dofs_per_env
表示每个环境中自由度的数量。- 张量的数据类型是
float32
,并且被分配在设备(可能是GPU)上,self.device
表示当前设备。
- 这一行代码创建了一个全零的张量
2. 缩放动作并写入小车自由度切片
forces[:, 0] = actions * self.max_push_force
- 解释:
- 这一行代码根据给定的
actions
来计算需要施加的力,并将结果赋值给forces
张量的第一个自由度(假设这是小车的自由度)。 actions
是输入的动作,通常范围在[-1, 1]
之间。self.max_push_force
是一个常数,表示可以施加的最大推力。通过乘以actions
,生成的力将被限制在[self.max_push_force, -self.max_push_force]
范围内。
- 这一行代码根据给定的
3. 将力施加到所有演员上
self.gym.set_dof_actuation_force_tensor(self.sim, gymtorch.unwrap_tensor(forces))
- 解释:
self.gym.set_dof_actuation_force_tensor(self.sim, gymtorch.unwrap_tensor(forces))
函数将计算得到的forces
张量施加到仿真中的所有演员的自由度上。gymtorch.unwrap_tensor(forces)
将 PyTorch 张量forces
转换为 Gym 环境能够理解的原始张量描述符。- 这样,施加的力将直接影响每个环境中相应自由度的运动。
这个方法的主要目的是在每次物理仿真步骤之前,根据输入的动作(actions
),为环境中的每个自由度施加适当的力。具体来说,这里通过将动作缩放为实际施加的力,并应用到小车的自由度上,从而控制小车的运动。这种控制方法通常用于仿真和强化学习环境中,以实现对物理系统的动态控制。
def pre_pyhsics_step(self, actions):
# prepare DOF force tensor
forces = torch.zeros((num_envs, dofs_per_env), dtype=torch.float32, device=self.device)
# scale actions and write to cart DOF slice
forces[:, 0] = actions * self.max_push_force
# apply the forces to all actors
self.gym.set_dof_actuation_force_tensor(self.sim, gymtorch.unwarp_tensor(forces))
重置环境
这段代码定义了一个 reset
方法,用于在仿真环境中重置选定的环境(env_ids
),为这些环境的自由度(DOFs)生成新的随机初始位置和速度,并将这些新的状态应用到仿真中。以下是对每个部分的详细解释:
1. 获取需要重置的环境数量
num_resets = len(env_ids)
- 解释:
env_ids
是一个包含需要重置的环境ID的列表或张量。num_resets
计算出这个列表的长度,即需要重置的环境数量。
2. 生成随机的DOF位置和速度
p = 0.3 * (torch.rand((num_resets, dofs_per_env), device=self.device) - 0.5)
v = 0.5 * (torch.rand((num_resets, dofs_per_env), device=self.device) - 0.5)
- 解释:
torch.rand((num_resets, dofs_per_env), device=self.device)
生成一个形状为(num_resets, dofs_per_env)
的随机张量,其值在[0, 1)
之间。- 通过减去 0.5 和乘以适当的系数(0.3 和 0.5),这些随机值被映射到适当的范围内:
p
是新的DOF位置,范围在[-0.15, 0.15)
之间。v
是新的DOF速度,范围在[-0.25, 0.25)
之间。
device=self.device
指定这些张量在所选设备(通常是GPU)上生成。
3. 将新的状态写入DOF状态张量
self.dof_states[env_ids, 0] = p
self.dof_states[env_ids, 1] = v
- 解释:
self.dof_states
是存储所有环境的DOF状态的张量,其中包含每个环境的DOF位置和速度信息。- 通过
self.dof_states[env_ids, 0] = p
和self.dof_states[env_ids, 1] = v
,为env_ids
中指定的环境ID分配新的DOF位置和速度。
4. 将新的DOF状态应用到选定的环境中
self.gym.set_dof_state_tensor_indexed(self.sim, self.dof_states_desc, gymtorch.unwrap_tensor(env_ids), num_resets)
- 解释:
self.gym.set_dof_state_tensor_indexed
是一个将新的DOF状态应用到仿真环境中的方法。self.sim
是仿真环境,self.dof_states_desc
是DOF状态张量的描述符。gymtorch.unwrap_tensor(env_ids)
将PyTorch张量env_ids
转换为Gym库能够理解的原始张量描述符。num_resets
是重置的环境数量,指定了应用这些新状态的环境数。
这个 reset
方法用于在仿真中重置选定的环境,通过为这些环境的自由度生成新的随机位置和速度来初始化它们。这个方法特别适用于强化学习中的多环境仿真,在每次训练开始时或在某些条件下(如任务失败)重置环境以提供新的初始状态。这种随机初始化有助于在训练过程中增加多样性,从而提升模型的鲁棒性和泛化能力。
def reset(self, env_ids):
# number of envirnments to reset
num_restes = len(env_ids)
# generate random DOF positions and velocities
p = 0.3 * (torch.rand((num_resets, dofs_per_env), device=self.device) - 0.5)
v = 0.5 * (torch.rand((num_resets, dofs_per_env), device=self.device) - 0.5)
# write new states to DOF state tensor
self.dof_states[env_ids, 0] = p
self.dof_states[env_ids, 1] = v
# apply the new DOF states for the selected envs
# using env_ids as the actor index tensor
self.gym.set_dof_state_tensor_indexed(self.sim, self.dof_states_desc, gymtorch.unwarp_tensor(env_ids), num_resets)
标签:指南,tensor,self,dof,张量,env,操作,gym,Isaacgym
From: https://blog.csdn.net/qq_38023194/article/details/140874763