Isaac Gym 3. 基础总结

近期使用isaac gym,所以对一些使用进行汇总。

1. ISAAC GYM

在isaac gym中,存在几个基础且常见的概念:gym, sim, env, actor, rigid

  1. Gym: 在Isaac Gym中,“Gym”通常指的是整个仿真平台或框架本身。它提供了创建和管理多个仿真环境的接口。

  2. Sim: “Sim”是指模拟器(simulator),是仿真的核心组件。它负责处理物理计算和仿真的所有细节,如动力学、碰撞检测和其他物理交互。Isaac Gym使用NVIDIA PhysX作为其后端物理引擎,可以高效地在GPU上运行。在代码中的体现是,调用sim可以完成对模拟器的step。

  3. Env: “Env”是指环境(environment),是智能体(agent)进行学习和互动的场所。每个环境包含了特定的任务或场景设置,智能体需要在这些环境中执行操作以获取奖励并学习策略。

  4. Actor: “Actor”是在仿真中表示具有物理属性的对象,如机器人、物体等。每个Actor包括了用于描述其形状、质量、动力学属性等的各种参数。Actors是智能体与环境互动的主体,例如一个机器人的手臂或车辆。

  5. Rigid: “Rigid”,刚体,是一种物理对象,其形状在仿真过程中不会发生变化。在Isaac Gym中,刚体用来表示那些不需要弹性或变形特性的实体。刚体动力学是计算这些对象如何在力和碰撞作用下移动和反应的基础。

  6. Index / indcies: 这是一个很容易混淆的概念,特别是在多env多actor,每个actor拥有1个以上rigid时。理解index的索引获取和它代表的对象非常重要。

由此,可以得到isaac gym仿真环境的基本框架,即基于gym,使用sim进行仿真,在sim中可以生成多个env,每个env中可以生成多个actor作为交互对象。对于每个actor,可以由rigid或其他非刚体关系组成。

2. 仿真环境

2.1. 基础环境搭建

 基础环境包括gym和sim,viewer的初始化,以下是添加ground plane和设置sim参数的代码:

# initialize gym
gym = gymapi.acquire_gym()

# parse arguments
args = gymutil.parse_arguments(description="Joint control Methods Example")

# create a simulator
sim_params = gymapi.SimParams()
sim_params.substeps = 1
sim_params.dt = opt.dt

sim_params.physx.solver_type = 1
sim_params.physx.num_position_iterations = 4
sim_params.physx.num_velocity_iterations = 1

sim_params.physx.num_threads = args.num_threads
sim_params.physx.use_gpu = args.use_gpu
sim_params.use_gpu_pipeline = args.use_gpu_pipeline
if args.sim_device_type == 'cuda' and sim_params.use_gpu_pipeline:
    device = args.sim_device
else:
    device = 'cpu'

sim = gym.create_sim(args.compute_device_id, args.graphics_device_id, args.physics_engine, sim_params)

if sim is None:
    print("*** Failed to create sim")
    quit()

# create viewer using the default camera properties
viewer = gym.create_viewer(sim, gymapi.CameraProperties())
if viewer is None:
    raise ValueError('*** Failed to create viewer')

# add ground plane
plane_params = gymapi.PlaneParams()
gym.add_ground(sim, gymapi.PlaneParams())

 sim搭建好后就是声明env或envs。

使用gym.create_env声明env并获得env_handle,如果使用多个环境可添加handle到envs。

如:

num_envs = 16
num_per_row = int(np.sqrt(num_envs))
spacing = 1.5  # actor 之间的间隔
env_lower = gymapi.Vec3(-spacing, 0.0, -spacing)
env_upper = gymapi.Vec3(spacing, 0.0, spacing)

envs = []
for i in range(num_envs):
    # create env
    env_handle = gym.create_env(sim, env_lower, env_upper, int(np.sqrt(num_envs)))
    envs.append(env_handle)

创建完成env后可以创建viewer:

# create viewer
mid = 0.5 * spacing * (num_per_row - 1)
cam_pos = gymapi.Vec3(0, spacing, 0)
cam_target = gymapi.Vec3(mid, 0, mid)
gym.viewer_camera_look_at(viewer, None, cam_pos, cam_target)

2.2. 环境参数

这里的环境参数是以上内容中设定环境时可能使用的参数,调用gymutil和gymapi。

# parse arguments 这个函数句柄没有在handbook中找到,待议
args = gymutil.parse_arguments(description="Joint control Methods Example")

其中gymapi.SimParams()返回一个Gym Simulation Parameters的类,其中会包括FlexParams和PhysXParams两个子类用于设定详细参数。

sim_params.dt = 0.01         # 环境step时间为10ms
sim_params.substeps = 2      # 模拟的子步数,暂不确定有什么用
sim_params.gravity = [0., 0., -9.81]

sim_params.enable_actor_creation_warning
sim_params.num_client_threads
sim_params.flex              # 更详细的仿真设置,参考FlexParams
sim_params.up_axis = 1       # 设定坐标系的垂直坐标轴,0为y,1为z

sim_params.use_gpu_pipeline

sim_params.stress_visualization
sim_params.stress_visualization_min
sim_params.stress_visualization_max

sim_params.physx.solver_type = 1                # 
sim_params.physx.num_position_iterations = 4    # 
sim_params.physx.num_velocity_iterations = 1    # 

sim_params.physx.num_threads = args.num_threads
sim_params.physx.use_gpu = args.use_gpu

3.1. 模型导入

请参考https://github.com/leggedrobotics/legged_gym

3.2. 模型生成

举例,生成一个球体,需要用到代码获得球体预设,并将球体句柄加入到actor中。(此时为多环境)

sphere_asset = self.gym.create_sphere(self.sim, radius, asset_options)
# (self: Gym, env: Env, asset: Asset, pose: Transform, name: str = None, group: int = - 1, filter: int = - 1, segmentationId: int = 0)
sphere_handle = self.gym.create_actor(env, sphere_asset, pos, "sphere", filter, 1)  # in filter i
actor_handles.append(sphere_handle)

 其中,使用gymapi.AssetOptions(),对球体的部分参数进行设定,如:

# Create the sphere asset with specific physical properties
asset_options = gymapi.AssetOptions()
asset_options.density = 530  # Set the density for the tennis ball

以及,使用gymapi.Transform(),对球体的位姿进行设定,如:

initial_pose = np.random.uniform(-1, 1, size=3)
initial_pose = torch.tensor(initial_pose, device=device)
pos = gymapi.Transform()
pos.p = gymapi.Vec3(*initial_pose)
pos.r = gymapi.Quat(-0.707107, 0.0, 0.0, 0.707107)

以及,使用gymapi.RigidShapeProperties(),对于部分刚体参数的设置,如:

# Set the restitution using RigidShapeProperties
properties = gymapi.RigidShapeProperties()  # 具有filter参数
properties.restitution = 0.85  # Set the restitution for the tennis ball
properties.filter = 0
gym.set_actor_rigid_shape_properties(env, sphere_handle, [properties])

注意,以上的几个参数相互存在互补和重复,正确设定即可。

也可以调整球体的颜色:

color = gymapi.Vec3(random.random(), random.random(), random.random())
gym.set_rigid_body_color(env, actor_handle, 0, gymapi.MESH_VISUAL_AND_COLLISION, color)

在导入模型时,我们需要对模型的handle和index进行记录,以便于后续的数据索引,并避免重复检查索引,加速程序运算。

self.actor_handles = []
self.actor_idxs = []
self.rigid_body_idxs = []
self.envs = []

 使用以下api获取index和handle。如果发现返回的idx或handle为-1,则代表未检索到对象。

actor_handle = self.gym.create_actor(env_handle, robot_asset, start_pose, self.cfg.asset.name, i,self.cfg.asset.self_collisions, 0)
self.envs.append(env_handle)
self.actor_handles.append(actor_handle)
actor_idx = self.gym.find_actor_index(env_handle, self.cfg.asset.name, gymapi.DOMAIN_SIM)
self.actor_idxs.append(actor_idx)

 Isaac gym手册中有大量的句柄搜索方法,此处我只列举了当前选出的较为合适的方法。由于这些概念较为抽象,请实际debug时进行查看以理解。

4. 信息读取

4.1. ISAAC GYM运行流程

sim声明后的运行主要为以下流程:

# after init and before loop
gym.prepare_sim(sim)

# start loop
while not gym.query_viewer_has_closed(viewer):
    # step the physics
    gym.simulate(sim)
    gym.fetch_results(sim, True)

    # refresh tensors
    
    # take actions

    # update viewer
    gym.step_graphics(sim)
    gym.draw_viewer(viewer, sim, True)
    gym.sync_frame_time(sim)


# end and clean up
gym.destroy_viewer(viewer)
gym.destroy_sim(myball.sim)

sim中的信息以isaac gym自有的tensor类型存储,不同于pytorch。为了确保获取实时的信息,使用以下句柄在读取tensor前对tensor进行刷新和维护:

# refresh tensors
gym.refresh_rigid_body_state_tensor(sim)
gym.refresh_dof_state_tensor(sim)
gym.refresh_jacobian_tensors(sim)
gym.refresh_mass_matrix_tensors(sim)

4.1. 基本信息

Isaac gym中的状态tensor大致有几类:_root_tensor, rigid_body_tensor, contact_force_tensor. dof_tensor暂时不提及。

以上的tensor可以通过以下api获取:

self._root_tensor = self.gym.acquire_actor_root_state_tensor(self.sim)
_rb_states = self.gym.acquire_rigid_body_state_tensor(self.sim)
_net_cf = self.gym.acquire_net_contact_force_tensor(self.sim)

获取tensor后,需要通过wrap_tensor操作来将isaac gym类型的tensor转化为torch类型的tensor。

self.root_states = gymtorch.wrap_tensor(self._root_tensor)
self.rb_states = gymtorch.wrap_tensor(_rb_states)
self.contact_forces = gymtorch.wrap_tensor(_net_cf).view(self.num_envs, -1, 3)

从调用的sim句柄可以看出,此处获取的tensor索引(index)应该是sim的全局索引。

由于一次获取的是全部环境的rigid tensor,所以可以按照需要使用env对rigid进行数据切片:

positions = []
velocities = []

for i, (env, ball_handle) in enumerate(zip(envs, actor_handles)):
    num_bodies = gym.get_actor_rigid_body_count(env, ball_handle)
    if num_bodies == 0:
        raise ValueError("The specified ball handle has no rigid bodies.")
    # body_index = gym.get_actor_rigid_body_handle(env, ball_handle, 0)

    pos = rb_states[i, 0:3].cpu().numpy()
    vel = rb_states[i, 7:10].cpu().numpy()

    positions.append(pos)
    velocities.append(vel)

注:以上代码仅适用与多环境单actor单rigid的情况。后续更新

对于gym.acquire_rigid_body_state_tensor的参数定义如下:

Retrieves buffer for Rigid body states.

The buffer has shape (num_rigid_bodies, 13).

State for each rigid body contains position([0:3]), rotation([3:7]), linear velocity([7:10]), and angular velocity([10:13]).

4.1.1. 获取具体刚体的信息

参考isaac gym的例程franka_ cube_ik_osc.py

其中,涉及使用函数

gym.get_actor_rigid_body_index,DOMAIN_SIM表示返回sim中的句柄,DOMAIN_ENV则是返回env中的句柄。

box_idx = gym.get_actor_rigid_body_index(env, box_handle, 0, gymapi.DOMAIN_SIM)
box_idxs.append(box_idx)

gym.find_actor_rigid_body_handle,查找给定名称的actor刚体句柄。

hand_handle = gym.find_actor_rigid_body_handle(env, franka_handle, "panda_hand")
hand_pose = gym.get_rigid_transform(env, hand_handle)

gym.find_actor_rigid_body_index,使用此函数可查找状态缓冲区中刚体的索引。

hand_idx = gym.find_actor_rigid_body_index(env, franka_handle, "panda_hand", gymapi.DOMAIN_SIM)
hand_idxs.append(hand_idx)

以上带有DOMAIN_SIM一类参数函数是部分查找函数的集合,所以有更多不同名称的调用方法,具体见handbook。

获取index后即可切片读取信息:

box_pos = rb_states[box_idxs, :3]
box_rot = rb_states[box_idxs, 3:7]

hand_pos = rb_states[hand_idxs, :3]
hand_rot = rb_states[hand_idxs, 3:7]
hand_vel = rb_states[hand_idxs, 7:]

4.2. 碰撞检测

这里提及的碰撞检测使用

net_contact_forces = self.gym.acquire_net_contact_force_tensor(self.sim)
self.contact_forces = gymtorch.wrap_tensor(net_contact_forces).view(self.num_envs, -1, 3)  # shape: num_envs, num_bodies, xyz axis

刷新使用

self.gym.refresh_net_contact_force_tensor(self.sim)

刷新后可以检测

base_force = torch.norm(self.contact_forces[:, self.termination_contact_indices, :], dim=-1)

 

5. 设定状态

在这里提一个很恶心的问题,文档的说明不多。

在CPU状态下,我们可以通过以下方法来设定全局的刚体状态,比如需要重置状态的时候。

        # Unwrap the tensor before setting it
        rb_states = gymtorch.unwrap_tensor(rb_states)
        ii = self.gym.set_rigid_body_state_tensor(self.sim, rb_states)
        print("vel", ii)

 但是该方法不能在GPU环境下生效,(会返回false,但是程序运行不会报错)需要改为另一个方法:


        indices = torch.tensor(actor_idxs, device=self.device, dtype=torch.int32)
        self.gym.set_actor_root_state_tensor_indexed(self.sim,
                                                     gymtorch.unwrap_tensor(rb_states),
                                                     gymtorch.unwrap_tensor(indices), len(indices))

以上代码可以设定特定index的root_state状态,以下代码设定全部的状态:

self.gym.set_actor_root_state_tensor(self.sim, gymtorch.unwrap_tensor(self.rb_states))

在设定状态时,可能在gpu pipline遇见以下问题。

CUDA error: an illegal memory access was encountered - #2 by vamshikurva - Isaac Gym - NVIDIA Developer Forums

部分错误请详细阅读用户文档的:NVIDIA_Omniverse/ISAAC_Gym/isaacgym/docs/programming/tensors.html?highlight=set_dof_state_tensor_indexed

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以按照以下步骤来安装Isaac Gym: 1. 首先,您需要安装Nvidia驱动程序和Cuda模块。在安装之前,建议先安装Anaconda来管理包。您可以按照这篇博客中的指南来安装Anaconda和Nvidia驱动程序:\[1\] 2. 安装完成后,您可以下载Isaac Gym Benchmark Environments。您可以在这个国内镜像地址下载:\[2\] 3. 下载完成后,将文件解压并放在主目录下。然后进入解压后的文件夹中的isaacgym/docs目录,双击index.html文件,即可打开官方文档。 4. 按照文档中的步骤进行安装。您可以选择直接在新的虚拟环境中进行安装。可以通过以下命令来创建新的虚拟环境: ``` cd isaacgym/python/ sh ../create_conda_env_rlgpu.sh ``` 这样,您就可以按照官方文档中的指南来完成Isaac Gym的安装了。希望对您有所帮助! #### 引用[.reference_title] - *1* [issacgym+leggedgym安装](https://blog.csdn.net/svfsvadfv/article/details/129214461)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Isaac-gym(1): 安装及官方demo内容](https://blog.csdn.net/hongliyu_lvliyu/article/details/124605383)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值