[Isaac Lab]使用方法教程及注意事项--更新中

1. 前言

记录自己isaac lab所遇到的问题和经历,由于源代码有层层的封装,因此这里做简要的记录。。。。
一方面便于日后自己的温故学习,另一方面也便于大家的学习和交流。
如有不对之处,欢迎评论区指出错误,你我共同进步学习!

本文呢,笔者梦到哪里就写到了哪里(😅

2. 正文

CLI 命令行接口(Command Line Interface)

2.1 官方教程

这是FanZiQi对Isaac Lab的中文翻译连接:https://docs.robotsfan.com/isaaclab/source/overview/showroom.html(感谢大佬)
这是一些推荐的Isaac Lab开源的Github代码部分:https://docs.tianbot.com/advanced/isaac/nice_project_with_isaaclab.html
image
create empty.py创建空的窗口
安装、下载等按照官网操作的接口,本文主要说明一些官方没有提到的地方。

2.2 URDF导入并制作USD模型

USD(Universal Scene Description)通用的场景描述文件是由皮克斯动画工作室开源的一款开源文件格式。如果是自己的URDF的话需要通过这个脚本转换成USD的文件类型,这是Isaac Lab的基础机器人模型文件。

2.3 cfg文件和env文件

我们所熟知的isaac gym是面向过程的,因此其会公开对应的函数和参数,他们非常便于修改和自定义,但NVIDIA官方并不再维护他了;

而isaac lab是“面向对象的”,当然这是我自己定义的说法,因为其将函数和调用进行层层封装,并给出了一些已经写好的函数方法,你只需非常便捷的调用这个API就可以完成和isaac gym同样的事情,仅需几行代码而已。这方便了操作,但却增加了复杂度,因为原始的代码的顺序实在是和isaac gym太不一样了。。。。

2.3.1 cfg文件

假设我现在想训练GO2的locomotion的任务,那么我找到了他的配置 文件:
image
这俩文件又继承于:
image
这个文件的很多类被封装成一个个的Term,每一个Term又由其他地方继承
image
继承的Term来自这里:包括传感器、场景、关节执行器等类别。
image
这里回过头来重点关注下mdp的来源,这个是很关键的一个量。MDP(马尔科夫决策过程)
这是最原始的mdp这个量的方法位置:比如我们随便找其中的一个脚本文件进入的话,我们选择rewards.py,里面定义了很多的奖励函数
image
我们可以在cfg.py文件中看到这个定义:
image
这里面的Rew_Term来自于managers的的调用:
image

image
其中圈1是函数的定义方法,func后面的Callable是“函数”类别定义,weight后面的float也是浮点数类别定义。
圈2是权重定义方法。
感觉这么做的原因是把函数封装成一个类,便于诸如:

       self.rewards.feet_air_time.params["sensor_cfg"].body_names = ".*_foot"
        self.rewards.feet_air_time.weight = 0.01
        self.rewards.undesired_contacts = None
        self.rewards.dof_torques_l2.weight = -0.0002
        self.rewards.track_lin_vel_xy_exp.weight = 1.5
        self.rewards.track_ang_vel_z_exp.weight = 0.75
        self.rewards.dof_acc_l2.weight = -2.5e-7

等的调用等。。。

2.3.2 env文件

image
圈1是类似于isaac gym那种的直接暴露函数的方法
圈2是使用层层封装的抽象类方法带manager
每一个其中的带rl的名字都是强化学习方法的,这个也继承于之上。比如manager_based_rl_env.py 就继承于manager_based_env.py,二者主要区别起始是奖励函数计算的部分,还有关于强化学习的地方,这其中最主要的一点就是原始的manager_based_env.py有可能用于传统运动控制的计算方法,所以是不带RL的,这个暂时不重要。
image

2.4 SceneEntityCfg

定义如下:
image
按照位置参数传递参数,主要用于封装一些参数和属性,这样方便调用

2.5 play.py推理的时候想从checkpoint地方切入,该如何操作??

官方文档原话是这样的:

python scripts/skrl/play.py --task=Template-Isaac-Lab-Tutorial-Direct-v0

请注意,您无需指定检查点文件的路径!这是因为 Isaac Lab 处理诸如检查点保存、加载和记录等许多细节。在这种情况下, train.py 脚本将创建两个目录: logs 和 output ,它们用作此项目运行的任务的默认输出目录。

相关代码如下,引入特定checkpoint的路径进行推理:

# run script for playing with 32 environments
./isaaclab.sh -p scripts/reinforcement_learning/rsl_rl/play.py --task Isaac-Reach-Franka-v0 --num_envs 32 --load_run run_folder_name --checkpoint model.pt

经验证在checkpoint里面把model.pt的完整路径加入即可。
我自己写的bash脚本,一键运行,不用重复写hyra-args了

python play.py \
    --task="IsaacLab_Go2_Plane_EnvCfg" \
    --num_envs="50" \
    --checkpoint="//home//yyds//文档//Issac_Lab//Test1//IsaacLab-main//scripts//reinforcement_learning//rsl_rl//logs//rsl_rl//unitree_go2_flat//2025-07-21_19-31-43//model_4650.pt" \

2.6 地形

在这个路径下,存放着关于地形设置相关的文件。这里做一个简单的汇总和记录。
。。。。。。。/IsaacLab-main/source/isaaclab/isaaclab/terrains
image
先看主config部分的调用:
image

  • 圈1的部分ROUGH_TERRAINS_CFG其实是TerrainGeneratorCfg的实例化,主要地形的修改和配置看圈1部分的内容,这里类似于isaac gym的terrain config
  • 圈2和圈3部分(height_field和trimesh文件夹下),分别是高度场地形和三角网格地形。就是细致定义了每一种地形类型,以及如何实现的。这里笔者觉得可以自己添加,然后修改对应的cfg。height_field文件夹下的utils.py是一些几何形状的定义,比如圆柱、长方体等。
    image

image

高度场地形是计算机图形学和机器人仿真中的一种重要地形表示方法。它通过在二维网格上为每个点指定高度值来定义三维地形表面,这种方法特别适合表示自然地形、起伏地面或复杂的地表结构。相比于完整的三角网格表示,高度场具有更高的内存效率和计算性能,同时仍能提供足够的细节来模拟真实世界的地形复杂性。

  • 圈4的部分,TerrainImporterCfg将上述所有对象进行类封装,最终terrain实例化的就是这个对象,其参数细节参考如下:
terrain = TerrainImporterCfg(
    prim_path="/World/ground",  # 地形对象在USD场景图中的路径
    terrain_type="generator",   # 地形类型:使用程序化生成器创建地形
    terrain_generator=ROUGH_TERRAINS_CFG,  # 地形生成器配置:使用预定义的粗糙地形配置
    max_init_terrain_level=5,   # 最大初始地形难度级别:限制训练初期的地形复杂度
    collision_group=-1,         # 碰撞组:-1表示与所有其他碰撞组发生碰撞

    # 物理材质配置:定义地形的物理交互属性
    physics_material=sim_utils.RigidBodyMaterialCfg(
        friction_combine_mode="multiply",  # 摩擦力合并模式:相乘方式结合摩擦系数
        restitution_combine_mode="multiply",  # 弹性系数合并模式:相乘方式结合弹性
        static_friction=1.0,    # 静摩擦系数:防止静止物体滑动的阻力
        dynamic_friction=1.0,   # 动摩擦系数:运动物体受到的摩擦阻力
    ),
    
    # 视觉材质配置:定义地形的外观渲染
    visual_material=sim_utils.MdlFileCfg(
        # 材质文件路径:使用NVIDIA提供的大理石砖纹理材质
        mdl_path=f"{ISAACLAB_NUCLEUS_DIR}/Materials/TilesMarbleSpiderWhiteBrickBondHoned/TilesMarbleSpiderWhiteBrickBondHoned.mdl",
        project_uvw=True,       # 启用UV纹理投影:自动生成纹理坐标
        texture_scale=(0.25, 0.25),  # 纹理缩放:设置纹理在表面的重复密度
    ),
    
    debug_vis=False,            # 调试可视化:关闭地形原点的可视化标记
)

image

2.7 添加外力

在articulation.py里面找到了set_external_force_and_torque函数,设置body id的外力大小,最终修改的是

        self._external_force_b.flatten(0, 1)[indices] = forces.flatten(0, 1)
        self._external_torque_b.flatten(0, 1)[indices] = torques.flatten(0, 1)

这两个量的维度:
image

两个变量被修改。根据这两个变量查找,找到rigid_object_collection.py,
image
在这里被调用。这步将仿真外力添加到仿真的每一步。执行:apply_forces_and_torques_at_position函数。我们根据这个函数继续查找。在isaac lab里面找不到了,说明这个不是内部实现的函数,应该是外部包调用的函数方法。

    @property
    def root_physx_view(self) -> physx.ArticulationView:
        """Articulation view for the asset (PhysX).

        Note:
            Use this view with caution. It requires handling of tensors in a specific way.
        """
        return self._root_physx_view

这个地方看来是直接调用的physx物理引擎的,返回的变量也是该类型。记录一下是怎么调用物理引擎API添加外力的:

        # write actions into simulation
        self.root_physx_view.set_dof_actuation_forces(self._joint_effort_target_sim, self._ALL_INDICES)
        # position and velocity targets only for implicit actuators
        if self._has_implicit_actuators:
            self.root_physx_view.set_dof_position_targets(self._joint_pos_target_sim, self._ALL_INDICES)
            self.root_physx_view.set_dof_velocity_targets(self._joint_vel_target_sim, self._ALL_INDICES)

现在找到了怎么用什么加的外力,但是在哪里加呢??
IsaacLab-main/source/isaaclab/isaaclab/scene/interactive_scene.py里有这么一段话,
image
这段话在step里被调用。这个函数调用了所有asset的更新、写入以及reset。

在开发者注释中有这么一句话:

This function does not apply the external wrench to the simulation. It only fills the buffers with the desired values. To apply the external wrench, call the :meth:write_data_to_sim function right before the simulation step.

说明调用前需要用这个write_data_to_sim函数写入到仿真中。

在isaaclab文件夹下的articulation文件夹中的articulation.py,找到对刚体添加速度的定义:
image
同样找到对刚体速度命令的设置:
image

2.8 isaac_lab/assets

这个标题指的是请看这个路径。

资产存在四类:

  • articulation 关节(关节属性)
  • deformable object 可变形物体(包括软体、是食物类型、毛茸茸的动物等)
  • rigid object 刚体(刚体是由刚体组成的资源。它们可用于表示动态对象,例如盒子、球体等。刚体由其姿势、速度和质量分布来描述。)
  • rigid object collection 刚体对象集合(a collection of rigid objects)

每一类包含:

  • __cfg.py 配置
  • __data.py 数据( This class contains the data for an articulation in the simulation. The data includes the state of
    the root rigid body, the state of all the bodies in the articulation, and the joint state. The data is
    stored in the simulation world frame unless otherwise specified.)
  • __.py 调用上述二,主要文件橱

2.9 step

这里和isaac gym还不太一样。我来简单记录下过程。
我想改网络结构,但是isaac lab这个工程里是没有接口的,需要到site package的python功能包里直接找rsl-rl,这其实就很逆天,有点太面向对象了,一点过程就都没有。
image
里面的过程就很类似于isaac gym了。所以需要修改或者添加网络的同学这个得注意一下。不然isaac lab的isaac_lab_rl里面是只有cfg的。

看train.py文件,直接头文件调用了on policy runner:(所以我是这么才知道的,笔者也是找了很久的。。。)
image
这里调用了learning函数进行训练。
image

2.10 env

在train.py里面有一个env_vec的wrapper,这个可以直接在传入env的基础上扩展一些额外的函数。
image

这里是我们常用的基类环境.py文件
image

这里我遇到了一个问题,按理来说这个调用是没什么问题的,但是却报错了:提示没有这个函数。但是我传参类型是manager.....类型的啊,为什么实例化的self.env.appl...函数没有???
image

我试图修改step函数,试图覆盖原来的函数,把参数穿进去,但底层不支持直接修改step函数:(sb isaac lab)
image

2.11 ids

  • body_ids
  • env_ids是从0,1,2,3........,4096
    这里展平方便相加
    image

2.12 configclass

类的装饰器,用来实现对类的一些操作,可以直接用类的.class_info等函数转化为字典形式等.其余感觉加和没加一样.

2.13 terminations

在cfg里面定义终止条件:
image

在manager_based_rl_env.py里面就实现了对应的功能. 后面就是按照函数的功能解析DoneTerm里面的func,然后把param的值传给func,但值的注意的是,函数的默认参数self._env其实已经在处理的时候传进去了.就不需要在定义u的时候额外再传一遍了.
image

最后设定条件,返回True为进入终止条件的触发.

2.14 mode

对于EventCfg的randomize,注意到mode的不同种类:

  • "startup" 模式
    在环境初始化时调用;通常只执行一次;用于加载固定参数、初始资产、静态属性等。
  • "reset" 模式
    在 每个 episode 重置时 调用;调用条件:自上次触发以来,环境步数已达到配置中定义的间隔(例如每 N 步重置一次);
    常用于:重置机器人姿态;随机化物理参数;重置观测统计量等。如果 global_env_step_count 没提供,会抛出 ValueError。
  • ️"interval" 模式
    以固定时间间隔(dt)触发;通常用于周期性事件,例如每 1 秒钟随机摩擦一次;调用条件:时间累计达到配置的间隔;环境索引 env_ids 不能手动提供,因为它由内部逻辑(时间剩余量)自动计算。如果没提供 dt,或提供了 env_ids,则会报 ValueError。
  • ️ "once" 模式(可能存在于部分版本)
    在任务启动时只执行一次;用于全局场景初始化。

2.15 from future import annotations

class Node:
    def __init__(self, next: Node | None = None):
        self.next = next

这在旧版 Python(❤️.10)里会报错,因为当解释器执行到函数定义时,Node 这个类还没定义好。

from __future__ import annotations

class Node:
    def __init__(self, next: Node | None = None):
        self.next = next

则不会报错。在新版本的python中写不写都一个样子。个人感觉主要是为了兼容就版本的python。

2.16 观测的处理

观测term的处理:
image
image

2.17

image

3. Q&A issues

3.1 ISSUE1

image
出现上图这种情况,同时reset失效。添加下面的随即化可以解决这一问题。

    ## <><><> 随机重置base位置和速度 <><><>
    # NOTE 不加的话,机器人将按照间隔均匀分布,部分可能出现在场景之外
    randomize_reset_base = EventTerm(
        func=mdp.reset_root_state_uniform,
        mode="reset",
        params={
            "pose_range": {"x": (-0.5, 0.5), "y": (-0.5, 0.5), "yaw": (-3.14, 3.14)},
            "velocity_range": {
                "x": (-0.5, 0.5),
                "y": (-0.5, 0.5),
                "z": (-0.5, 0.5),
                "roll": (-0.5, 0.5),
                "pitch": (-0.5, 0.5),
                "yaw": (-0.5, 0.5),
            },
        },
    )

这篇博客暂时记录到这里,日后我会继续补充。

posted @ 2025-07-21 16:33  泪水下的笑靥  阅读(1497)  评论(0)    收藏  举报