当前位置: 首页 > news >正文

第四讲、Isaaclab与刚性物体交互

0 前言

官方教程:https://isaac-sim.github.io/IsaacLab/main/source/tutorials/01_assets/run_rigid_object.html
Isaacsim+Isaaclab安装:https://blog.csdn.net/m0_47719040/article/details/146389391?spm=1001.2014.3001.5502

在之前的教程中,我们学习了独立python脚本如何启动Issacsim以及如何在仿真场景中生成不同的对象(prim)。本教程将演示如何创建刚体对象并与之交互。本节将围绕Isaac Lab 中提供的assets.RigidObject类展开研究。

教程对应的脚本为run_rigid_object.pyscripts/tutorials/01_assets目录下。

运行该程序:

  • 进入安装 isaac lab 时创建的conda虚拟环境
  • 在该环境下进入 isaac sim文件夹中运行source setup_conda_env.sh
  • 终端中输入python scripts/tutorials/01_assets/run_rigid_object.py运行你的代码,会在isaac sim中出现4个绿色的锥体。

在这里插入图片描述代码主体部分由三个函数构成:design_scene()run_simulator()以及main(),其中main()作为主函数由design_scene()run_simulator()构成。实际上就是讲整个仿真模拟过程分为两个步骤:

  • 场景设计:顾名思义,这部分负责讲所有的对象(prim)添加到场景(stage)中。
  • 运行模拟:此部分负责启动模拟器,与场景中的基本对象进行交互,例如改变它们的姿态,以及对他们应用各种复杂指令。

分阶段进行仿真模拟是必要的,因为运行模拟必须在场景设计完成后并重置模拟器才会正常进习惯。重置模拟器后不能再经任何新的对象添加到场景中,但可以通过手柄或键盘与对象进行交互。比如,我们可以通过键盘控制四足机器人前后左右运动。

1 场景设计 design_scene()

构建场景的第一步是向场景中添加一个地平面和一个光源:

	# 添加地平面
	cfg = sim_utils.GroundPlaneCfg()
	cfg.func("/World/defaultGroundPlane", cfg)
	# 添加光源
	cfg = sim_utils.DomeLightCfg(intensity=2000.0, color=(0.8, 0.8, 0.8))
	cfg.func("/World/Light", cfg)

基于assets.RigidObject向场景中添加多个锥形刚体对象:

前一节中使用下述代码创建刚体对象,通过sim_utils.ConeCfg指定是锥体,通过rigid_props=sim_utils.RigidBodyPropertiesCfg()指定刚体属性。

cfg_cone_rigid = sim_utils.ConeCfg(
        radius=0.15,
        height=0.5,
        rigid_props=sim_utils.RigidBodyPropertiesCfg(),
        mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
        collision_props=sim_utils.CollisionPropertiesCfg(),
        visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
    )
    cfg_cone_rigid.func(
        "/World/Objects/ConeRigid", cfg_cone_rigid, translation=(-0.2, 0.0, 2.0), orientation=(0.5, 0.0, 0.5, 0.0)
    )

本节中将生成配置包装到assets.RigidObjectCfg类中,该类包含对象加载策略、默认初始状态和其他对象信息,将该类实例传递给 assets.RigidObject类时,会生成对行并再开启仿真时初始化相应的物理属性。

# 创建原点组(Xform 容器),创建四个空变换节点作为父容器
origins = [[0.25, 0.25, 0.0], [-0.25, 0.25, 0.0], [0.25, -0.25, 0.0], [-0.25, -0.25, 0.0]]
# Prim路径 /World/Origin0 到 /World/Origin3
for i, origin in enumerate(origins):
    prim_utils.create_prim(f"/World/Origin{i}", "Xform", translation=origin)
# 创建锥形刚体参数    
cone_cfg = RigidObjectCfg(
	# 正则表达式 /World/Origin.*/Cone 匹配所有 /World/Origin{i}/Cone 路径
	prim_path="/World/Origin.*/Cone",  # 正则路径模式
	spawn=sim_utils.ConeCfg(          # 锥体几何参数
	    radius=0.1,                   # 底面半径(米)
	    height=0.2,                   # 高度(米)
	    rigid_props=sim_utils.RigidBodyPropertiesCfg(),  # 默认刚体属性
	    mass_props=sim_utils.MassPropertiesCfg(mass=1.0),  # 质量1kg
	    collision_props=sim_utils.CollisionPropertiesCfg(),  # 默认碰撞属性
	    visual_material=sim_utils.PreviewSurfaceCfg(       # 视觉材质
	        diffuse_color=(0.0, 1.0, 0.0),  # 漫反射颜色(RGB绿色)
	        metallic=0.2                   # 金属质感(0-1)
	    ),
	),
	init_state=RigidObjectCfg.InitialStateCfg(),  # 初始状态(默认位姿)
)
# 实例化刚体对象
cone_object = RigidObject(cfg=cone_cfg)
#1 路径匹配:扫描场景中所有匹配 /World/Origin.* 的 Xform 节点
#2 子节点生成:在每个匹配的 Xform 下创建 /Cone 子 Prim
#3 物理绑定:为每个 Cone Prim 添加 PhysX 刚体属性
# /World/Origin0/Cone
# /World/Origin1/Cone
# /World/Origin2/Cone
# /World/Origin3/Cone
# 返回场景信息
scene_entities = {"cone": cone_object}

在这里插入图片描述

2 运行模拟循环

循环模拟部分,循环的与刚体进行交互,其中主要包含三个步骤:

  • 以固定间隔重置仿真状态
  • 步进仿真
  • 更新刚体缓冲区 (数据同步,确保获取最新物理状态)

3 重置模拟状态

重置刚体对象prim的模拟状态,需要设置刚体prim的(重置)姿态和速度,两者一起决定了根状态(Root State)。

物理引擎只理解世界坐标系,所以在更新刚体的位置时坐标必须时世界坐标系下的~
物理引擎的坐标系要求:PhysX 等物理引擎仅处理全局坐标系下的刚体状态,忽略 USD 层级中的父节点变换。

# 父 Xform 位置:/World/Origin0 (x=0.25, y=0.25, z=0)
# 锥体局部位置:/World/Origin0/Cone (x=0, y=0, z=0)
# 物理引擎视角:锥体实际位置为 (0.25, 0.25, 0)

从Isaacsim中更直观的看有(Origin0):
在这里插入图片描述在这里插入图片描述

  • assets.RigidObject.data.default_root_state :获取生成的刚体对象prim的默认根状态。
  • assets.RigidObjectCfg.init_state:上述默认状态可以从该方法中配置。
  • assets.RigidObject.write_root_pose_to_sim():设置刚体对象prim的所需姿态。
  • assets.RigidObject.write_root_velocity_to_sim():设置刚体对象prim的所需速度。
"""Runs the simulation loop."""
    # 对象提取与初始化
    cone_object = entities["cone"] # 从场景字典提取锥体管理器实例
    # 仿真时间参数配置
    sim_dt = sim.get_physics_dt() # 获取物理步长时间(默认 1/60 秒
    sim_time = 0.0 # 累计仿真时间
    count = 0 # 步数计数器
    # 仿真循环
    while simulation_app.is_running():  # 持续运行直到用户停止
        # 每250步触发重置
        if count % 250 == 0:
  					
            # --- 阶段1: 重置参数 ---
            sim_time = 0.0 # 重置累计时间
            count = 0 # 重置步数计数器
            
            # --- 阶段2: 生成新根状态 ---
            root_state = cone_object.data.default_root_state.clone() # 克隆默认状态(包含初始位姿、速度)
            # 在原点基础上叠加圆柱形随机偏移
            '''
            这部分实际上就是把默认的位置转换为圆锥的世界坐标系的位置,实际上就是在初始origins坐标的基础上做了一个随机的偏移。
			'''
            root_state[:, :3] += origins # origins为各实例父节点的世界坐标
            root_state[:, :3] += math_utils.sample_cylinder(
                radius=0.1, # 圆柱半径
                h_range=(0.25, 0.5), # 高度范围(Z轴)
                size=cone_object.num_instances, # 实例数量
                device=cone_object.device # 计算设备(CPU/GPU)
            )
            
            # --- 阶段3: 写入物理引擎 ---
            cone_object.write_root_pose_to_sim(root_state[:, :7]) # 写入位姿(位置 + 四元数)
            cone_object.write_root_velocity_to_sim(root_state[:, 7:]) # 写入速度(线速度 + 角速度)
            # --- 阶段4: 重置内部状态 ---
            cone_object.reset() # 更新对象内部缓冲区
            print("----------------------------------------")
            print("[INFO]: Resetting object state...")

注:可以修改origins坐标及随机圆柱半径看看结果,以下是我将origins修改为origins = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]的结果,注意这里是刚体,开始仿真后可以看到有的圆锥会被挤走~
在这里插入图片描述

4 逐步进行模拟

在开始模拟之前,我们先执行该assets.RigidObject.write_data_to_sim()方法。该方法会将其他数据(例如外力)写入模拟缓冲区。在本教程中,我们不对刚体施加任何外力,因此该方法并非必需。但为了完整性,我们仍然包含该方法。

        # 将其他数据(例如外力)写入模拟缓冲区
        cone_object.write_data_to_sim()
        # 步进
        sim.step()
        # 更新参数
        sim_time += sim_dt
        count += 1

5 更新状态

逐步模拟后,我们更新刚体prim的内部缓冲区,使其与物理引擎的当前状态同步。此操作使用assets.RigidObject.update()方法完成。

        # 更新缓冲区
        cone_object.update(sim_dt)

不调用 update() 的后果:

  • 状态滞后:读取到的位置/速度比实际物理状态晚 1 帧或多帧
  • 控制失效:设置的指令未提交到物理引擎,物体无响应
  • 传感器数据过期:相机图像或 LiDAR 点云停留在旧时间戳

相关文章:

  • C++的*了又*
  • vue项目引入tailwindcss
  • 【基于开源insightface的人脸检测,人脸识别初步测试】
  • 本地部署DeepSeek-R1,搭建本地知识库
  • 查看容器内的eth0网卡对应宿主机上的哪块网卡
  • 视频云存储/对象存储EasyCVR视频汇聚平台对接S3存储不能持久化运行的原因排查
  • wkhtmltopdf生成图片的实践教程,包含完整的环境配置、参数解析及多语言调用示例
  • 13、nRF52xx蓝牙学习(GPIOTE组件方式的任务配置)
  • Python asyncio
  • C++ | 多态
  • 要查看 ​​指定 Pod 的资源限制(CPU/内存)
  • 图书管理系统(Python)
  • 蓝桥杯单片机刷题——按键控制距离显示精度
  • Android studio | From Zero To One ——手机弹幕
  • 算法 模版
  • 408 计算机网络 知识点记忆(8)
  • 数据可视化 —— 堆形图应用(大全)
  • 在windows服务器使用Nginx反向代理云端的python实现的web应用
  • 极简cnn-based手写数字识别程序
  • 生成验证码图片
  • dreamwear做网站/自助建站系统个人网站
  • 怎么做网站百度贴吧/深圳做网站的公司
  • 心悦dnf免做卡网站/seo推广专员招聘
  • 网站建设框架搭建/seo营销技巧
  • 做企业网站用什么cms/近期发生的重大新闻
  • 怎么做网页app/站长工具seo排名查询