首页/文章/ 详情

IsaacSim如何用批量化运行?

3月前浏览1279

 

作者:张新红    出品:车路漫漫

#机器人仿真  #具身智能  #IsaccSim


做机器人仿真的话估计你肯定知道IsaacSim这个软件。

今天来跟大家分享一下IsaacSim的使用技巧,主要是IsaacSim是一个需要大量UI操作来进行仿真的软件,但是我们测试开发人员往往需要进行批量化大规模运行,因此,本文分享的是如何通过代码来进行配置已实现批量化运行,本文仅以立方体为例进行演示,机器人同理。

照例先交代下我的运行环境:
· 操作系统:ubuntu 20.04
· 编程语言:python 3.6
· 仿真软件:isaacsim 6.0.0

以下是完整代码(my_application.py)。能看懂的盆友看这个就行,看不明白的我后面有挨个片段说明。

  # Launch Isaac Sim before any other imports
# Default first two lines in any standalone application
# 导入 SimulationApp 类,而不是整个模块,或者从模块中导入类
from isaacsim.simulation_app import SimulationApp

# 创建实例,注意变量名不要与导入的类名或模块名混淆(虽然这里用 simulation_app 做变量名也可以,但最好区分开)
# 推荐做法:实例化 SimulationApp 类
simulation_app = SimulationApp({"headless": False})  # we can also run as headless

# Now import Isaac Sim modules
import isaacsim.core.experimental.utils.stage as stage_utils
import numpy as np
import omni.timeline
from isaacsim.core.experimental.materials import PreviewSurfaceMaterial
from isaacsim.core.experimental.objects import Cube
from isaacsim.core.experimental.prims import GeomPrim, RigidPrim
from isaacsim.core.simulation_manager import SimulationManager
from isaacsim.storage.native import get_assets_root_path

# Add ground plane
ground_plane = stage_utils.add_reference_to_stage(
    usd_path=get_assets_root_path() + "/Isaac/Environments/Grid/default_environment.usd",
    path="/World/ground",
)

# Create a blue visual material for the cube
visual_material = PreviewSurfaceMaterial("/World/Materials/blue")
visual_material.set_input_values("diffuseColor", [0.0, 0.0, 1.0])

# Create the cube geometry
cube_shape = Cube(
    paths="/World/fancy_cube",
    positions=np.array([[0.0, 0.0, 1.0]]),
    sizes=[1.0],
    scales=np.array([[0.5, 0.5, 0.5]]),
    reset_xform_op_properties=True,
)

# Apply collision and rigid body
GeomPrim(paths=cube_shape.paths, apply_collision_apis=True)
cube = RigidPrim(paths=cube_shape.paths)

# --- [修正] 自定义物理属性 ---
# 获取 stage 和 prim 来设置阻尼
stage = omni.usd.get_context().get_stage()
prim_path = cube_shape.paths[0] # 获取字符串路径
prim = stage.GetPrimAtPath(prim_path)

if prim.IsValid():
    # 设置线性阻尼 (0.0 ~ 1.0+, 默认通常为 0.0)
    # 属性名称可能因版本略有不同,但 physxRigidBody:linearDamping 是标准名称
    attr_lin = prim.GetAttribute("physxRigidBody:linearDamping")
    if attr_lin.IsValid():
        attr_lin.Set(0.1)
        print(f"Set linear damping to 0.1")
    
    # 设置角阻尼
    attr_ang = prim.GetAttribute("physxRigidBody:angularDamping")
    if attr_ang.IsValid():
        attr_ang.Set(0.1)
        print(f"Set angular damping to 0.1")
        
    # 可选:设置质量 (Mass)
    # attr_mass = prim.GetAttribute("physics:mass")
    # if attr_mass.IsValid():
    #     attr_mass.Set(1.0)
# -------------------------

cube_shape.apply_visual_materials(visual_material)

# Start the timeline (physics simulation)
omni.timeline.get_timeline_interface().play()
simulation_app.update()

# Run the simulation loop
for i in range(50000):
    # Only query when physics is actively simulating
    if SimulationManager.is_simulating():
        positions, orientations = cube.get_world_poses()
        linear_velocities, angular_velocities = cube.get_velocities()

        # Will be shown on terminal
        print("Cube position is : " + str(positions.numpy()[0]))
        print("Cube's orientation is : " + str(orientations.numpy()[0]))
        print("Cube's linear velocity is : " + str(linear_velocities.numpy()[0]))

    # Step the app (physics + rendering)
    simulation_app.update()

# simulation_app.close()  # close Isaac Sim

上述代码执行方式为:

  me@Linux:/data/code/IsaacSim/_build/linux-x86_64/release$ ./python.sh ./exts/isaacsim.examples.interactive/isaacsim/examples/interactive/user_examples/my_application.py

1、初始化仿真应用 (Initialization)

导入 SimulationApp 类,而不是整个模块,或者从模块中导入类。
代码:

  # Launch Isaac Sim before any other imports
# Default first two lines in any standalone application
from isaacsim.simulation_app import SimulationApp

解释:从 isaacsim.simulation_app 模块中导入 SimulationApp 类。这是启动 Isaac Sim 引擎的核心类。注意:必须在导入其他 Omniverse/Isaac 模块之前执行此操作。

创建实例,注意变量名不要与导入的类名或模块名混淆(虽然这里用 simulation_app 做变量名也可以,但最好区分开)。推荐做法:实例化 SimulationApp 类。

代码:

  simulation_app = SimulationApp({"headless": False})  # we can also run as headless

解释:实例化 SimulationApp 对象。

{"headless": False}:表示启动带有图形用户界面(GUI)的窗口。如果设为 True,则只在后台运行,不显示画面,适合服务器环境。

这行代码执行后,Isaac Sim 引擎正式加载,窗口弹出。

2、导入依赖模块 (Imports)

代码:

  # 导入舞台(Stage)工具模块。stage_utils 提供了方便的方法来操作 USD 舞台,例如添加参考模型。
import isaacsim.core.experimental.utils.stage as stage_utils
import numpy as np
# 导入 Omniverse 时间线模块。用于控制仿真的播放、暂停和步进。
import omni.timeline
# 导入预览表面材质类。用于创建简单的视觉材质(如颜色、粗糙度)。
from isaacsim.core.experimental.materials import PreviewSurfaceMaterial
# 导入立方体几何体类。这是一个高级封装,用于快速创建立方体形状。
from isaacsim.core.experimental.objects import Cube
# 导入原始对象(Prim)处理类。
#  GeomPrim:用于处理几何属性,如添加碰撞体(Collision)。
#  RigidPrim:用于处理刚体属性,如质量、速度、受力。
from isaacsim.core.experimental.prims import GeomPrim, RigidPrim
# 导入仿真管理器。用于查询仿真状态(如是否正在模拟、当前时间步等)。
from isaacsim.core.simulation_manager import SimulationManager
# 获取 Isaac Sim 本地资源库的根路径。用于定位内置的资源文件(如地面、机器人模型等)。
from isaacsim.storage.native import get_assets_root_path

3、构建场景 (Scene Construction)

代码:

  # Add ground plane
ground_plane = stage_utils.add_reference_to_stage(
    usd_path=get_assets_root_path() + "/Isaac/Environments/Grid/default_environment.usd",
    path="/World/ground",
)

解释:向舞台添加一个参考模型。
usd_path:指定资源文件的路径。这里加载的是默认的网格环境,包含一个无限大的地面平面。
path:指定该模型在 USD 舞台中的层级路径为 /World/ground。
ground_plane:返回创建的 Prim 对象引用。

  # Create a blue visual material for the cube
visual_material = PreviewSurfaceMaterial("/World/Materials/blue")

解释:创建一个名为 PreviewSurfaceMaterial 的材质对象,并将其放置在舞台路径 /World/Materials/blue 下。

  visual_material.set_input_values("diffuseColor", [0.0, 0.0, 1.0])

解释:设置材质的输入参数。
"diffuseColor":漫反射 颜色。
[0.0, 0.0, 1.0]:RGB 值,代表纯蓝色。

  # Create the cube geometry
cube_shape = Cube(
    paths="/World/fancy_cube",
    positions=np.array([[0.0, 0.0, 1.0]]),
    sizes=[1.0],
    scales=np.array([[0.5, 0.5, 0.5]]),
    reset_xform_op_properties=True,
)

解释:创建立方体几何体。
paths:立方体在舞台中的路径 /World/fancy_cube。
positions:初始位置坐标 (x=0, y=0, z=1),即离地面 1 米高。
sizes:立方体的原始尺寸为 1x1x1 米。
scales:缩放比例为 0.5,所以最终显示大小为 0.5x0.5x0.5 米。
reset_xform_op_properties:重置变换属性,确保位置和大小的设置生效,不受默认变换影响。

4、应用物理属性 (Physics Application)

代码:

  # Apply collision and rigid body
GeomPrim(paths=cube_shape.paths, apply_collision_apis=True)

解释:为立方体添加碰撞属性。
apply_collision_apis=True:自动添加 PhysxCollisionAPI,使立方体能够与其他物体(如地面)发生碰撞检测,防止穿透。

代码:

  cube = RigidPrim(paths=cube_shape.paths)

解释:为立方体添加刚体属性。
这会添加 PhysxRigidBodyAPI,使立方体成为受物理引擎控制的刚体,具有质量、速度,并受重力影响。
cube 是一个 RigidPrim 对象,后续可以通过它查询或设置物理状态。

代码:

  # --- [修正] 自定义物理属性 ---
# 获取 stage 和 prim 来设置阻尼
stage = omni.usd.get_context().get_stage()
prim_path = cube_shape.paths[0] # 获取字符串路径
prim = stage.GetPrimAtPath(prim_path)    # Stage中的逻辑路径

解释:获取底层的 USD Stage 和 Prim 对象,以便直接修改底层属性。
cube_shape.paths[0]:因为 paths 可能是一个列表,这里取第一个路径字符串。
stage.GetPrimAtPath(...):根据路径获取具体的 USD Prim 对象。

代码:

  if prim.IsValid():
    # 设置线性阻尼 (0.0 ~ 1.0+, 默认通常为 0.0)
    # 属性名称可能因版本略有不同,但 physxRigidBody:linearDamping 是标准名称
    attr_lin = prim.GetAttribute("physxRigidBody:linearDamping")
    if attr_lin.IsValid():
        attr_lin.Set(0.1)
        print(f"Set linear damping to 0.1")
    
    # 设置角阻尼
    attr_ang = prim.GetAttribute("physxRigidBody:angularDamping")
    if attr_ang.IsValid():
        attr_ang.Set(0.1)
        print(f"Set angular damping to 0.1")
        
    # 可选:设置质量 (Mass)
    # attr_mass = prim.GetAttribute("physics:mass")
    # if attr_mass.IsValid():
    #     attr_mass.Set(1.0)
# -------------------------

解释:通过 USD 属性接口设置物理参数。
linearDamping:线性阻尼,模拟空气阻力。值越大,物体移动越慢。
angularDamping:角阻尼,模拟旋转阻力。值越大,物体旋转停止得越快。
IsValid() 检查确保属性存在且可写,避免报错。

代码:

  cube_shape.apply_visual_materials(visual_material)

解释:将之前创建的蓝色材质应用到立方体上。这样立方体在渲染时就会显示为蓝色。

5、启动仿真 (Start Simulation)

代码:

  # Start the timeline (physics simulation)
omni.timeline.get_timeline_interface().play()
解释:获取时间线接口并调用 play()。这会启动物理引擎,开始计算重力、碰撞等物理效果。
Python
simulation_app.update()

解释:触发一次应用更新。这会渲染第一帧画面,并让物理引擎迈出第一步。

6、仿真循环 (Simulation Loop)

代码:

  # Run the simulation loop
for i in range(50000):
    # Only query when physics is actively simulating
    # 检查仿真管理器是否处于“正在仿真”状态。这是一种安全检查,确保在物理引擎就绪时才读取数据。
    if SimulationManager.is_simulating():
        # 从 RigidPrim 对象 cube 中读取当前状态。
        positions, orientations = cube.get_world_poses()    # 返回世界坐标系下的位置(Position)和方向(Orientation,四元数)。
        linear_velocities, angular_velocities = cube.get_velocities() # 返回线性速度(Linear Velocity)和角速度(Angular Velocity)。

        # Will be shown on terminal
        print("Cube position is : " + str(positions.numpy()[0]))
        print("Cube's orientation is : " + str(orientations.numpy()[0]))
        print("Cube's linear velocity is : " + str(linear_velocities.numpy()[0]))

    # Step the app (physics + rendering)
    # 推进物理引擎一步(计算下一时刻的位置和速度)。
    # 渲染引擎绘制当前帧的画面。
    # 处理窗口事件(如点击关闭按钮)。
    # 如果没有这行代码,仿真不会前进,画面也不会刷新。
    simulation_app.update()    # # close Isaac Sim

 

以上,本文完。


来源:车路漫漫
ACT碰撞pythonUMGID机器人控制渲染
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-05-07
最近编辑:3月前
李慢慢
硕士 自动驾驶仿真工程师一枚
获赞 14粉丝 93文章 320课程 0
点赞
收藏
作者推荐

让无人机飞入自动驾驶世界:南科大开源CARLA-Air,一个进程搞定空地协同仿真

「空地一体化仿真平台」低空经济正在加速起飞。无人机配送、空中巡检、空地协同救援等场景层出不穷。但一个尴尬的现实是:当研究者需要让无人机和自动驾驶汽车在同一个城市场景中协同工作时,却找不到一个好用的仿真平台。自动驾驶领域的"明星"仿真器CARLA,拥有逼真的城市街景和丰富的交通流,却飞不了无人机;无人机仿真器AirSim,飞行物理精确,却没有真实的地面交通和行人。以往,研究者只能用"桥接"的方式把两者勉强拼在一起,但跨进程通信带来的延迟和时空不一致,让精密的空地协同实验几乎无从谈起。为了彻底打通天地之间的仿真壁垒,南方科技大学的研究团队联合深圳市机器人与计算机视觉重点实验室提出了CARLA-Air——一个在单个Unreal Engine进程中同时运行CARLA和AirSim的开源统一仿真平台,让空地协同的具身智能研究真正成为可能。该项目发布当日即登顶 HuggingFace 每日论文关注榜首,并在数周内收获 GitHub 400+ Stars。研究团队已开源全部代码并提供预编译打包文件,下载后无需配置环境,一键即可运行(文末附链接)。 1—"一山不容二虎"?组合式设计巧解引擎底层冲突要理解CARLA-Air的核心创新,首先需要了解一个Unreal Engine 4(UE4)的底层限制:每个世界只能有一个活跃的Game Mode。CARLA和AirSim各自深度耦合了自己的Game Mode,如果简单地将两者塞进同一个UE4进程,必然有一方的Game Mode被覆盖,导致其API完全失效。CARLA-Air的解法堪称精妙。研究团队设计了一个名为CARLAAirGameMode的统一游戏模式,它通过继承获得CARLA的地面子系统(交通管理、天气控制、行人行为等),同时通过组合将AirSim的空中飞行体(Aerial Flight Actor)作为普通的世界实体纳入其中。这种"继承+组合"的设计哲学,仅修改了上游CARLA代码库约35行,就实现了两大仿真引擎在同一进程中的和谐共存。图1 | CARLA-Air统一仿真世界一览。在同一个高保真城市场景中,行人、车辆和无人机共享物理一致的仿真环境,右侧展示了平台支持的自定义资产导入和空地协同能力。这种"天地一体"的仿真世界,正是CARLA-Air的核心价值所在。在运行时,CARLA-Air在单个UE4进程内同时托管CARLA RPC Server和AirSim RPC Server两个独立的通信服务端。研究者可以通过一个Python脚本同时驱动地面客户端和空中客户端,所有空中和地面平台在每个仿真Tick内同步采集数据,共享渲染管线、天气系统和物理时钟。图2 | "一山不容二虎"的破解之道。左侧(a)展示了朴素方案的困境——两个Game Mode争抢唯一的槽位,必有一方被丢弃;右侧(b)是CARLA-Air的组合式解决方案——CARLAAirGameMode继承CARLA的地面子系统,同时将AirSim的飞行体以组合方式纳入,巧妙地在单个Game Mode槽位中容纳了两套完整的仿真能力。2—亮点一:零修改迁移,原有代码直接复用对于已经在CARLA或AirSim上积累了大量代码的研究者来说,迁移成本是选择新平台时最大的顾虑。CARLA-Air在这一点上做到了极致:它完整保留了两个平台的原生Python API和ROS 2接口,研究者无需修改任何一行已有代码。具体而言,CARLA的89项自动化API测试全部通过,AirSim的全部飞行控制和传感器访问API均已验证,平台还发布了63个ROS 2 topics(43个CARLA + 14个AirSim + 6个通用)。这意味着,无论是CARLA社区的manual_control.py手动驾驶脚本,还是AirSim的hello_drone.py基础飞行演示,都可以在CARLA-Air中直接运行。图3 | CARLA-Air运行时架构。单个UE4进程内同时托管两套RPC服务器,通过统一的CARLAAirGameMode实现共享物理Tick、共享渲染管线和共享天气系统。研究者只需一个Python脚本,就能同时操控地面车辆和空中无人机。3—亮点二:微秒级通信,告别桥接延迟桥接式联合仿真的最大痛点在于跨进程通信延迟。由于CARLA和AirSim运行在不同进程甚至不同机器上,每次数据交换都需要经过序列化、网络传输和反序列化,往返延迟通常在1000到5000微秒之间,且无法保证两个仿真器的物理时钟严格同步。CARLA-Air通过单进程架构彻底消除了这一瓶颈。实测数据显示,轻量级状态查询(如获取位姿)的API往返延迟仅为280到490微秒,Actor生成约1850微秒,图像捕获约3200微秒——所有操作均在同一进程的共享内存中完成,无需任何跨进程通信。更关键的是,由于共享同一个物理Tick,空中和地面传感器的数据在时间上实现了绝对同步,最大对齐偏差不超过1个Tick。图4 | ROS平台运行测试。 在RViz中同步可视化无人机与车辆的多模态传感器数据,无人机与车辆传感器均呈现出高度一致的视觉效果,充分验证了空地传感器之间出色的感知一致性。4—亮点三:18种传感器模态,空地同步一键采集在具身智能和多模态感知研究中,构建大规模的配对数据集是训练模型的关键瓶颈。CARLA-Air支持多达18种传感器模态的同步采集,包括RGB相机、深度图、语义分割、实例分割、表面法线、LiDAR点云、LiDAR鸟瞰图、雷达、IMU、GNSS、气压计等。图5 | 无人机追踪卡车任务中的机载传感器数据采集可视化。 上方为三路RGB相机合成的全景图像,下方依次为深度图、语义分割图及机载LiDAR点云。所有传感器数据均可同步采集与落盘,内外参保持稳定,时间戳严格对齐。在一次典型的数据采集实验中,平台以17.1 FPS的帧率同时运行12路传感器流(6路车辆视角 + 6路无人机视角),持续采集1000个Tick的数据,每个Tick的写入延迟仅为61±9毫秒,且全程零RPC错误。图6 | 单Tick内同步采集的12路多模态传感器流。上排为地面车辆视角,下排为无人机鸟瞰视角,从左到右依次为RGB、语义分割、深度图、LiDAR鸟瞰、表面法线和实例分割。由于共享同一个渲染管线和天气条件,所有数据在时空上实现了"零误差"对齐。5—实验与表现CARLA-Air的性能评估在NVIDIA RTX A4000(16GB显存)、AMD Ryzen 7 5800X和32GB内存的硬件配置上进行。在帧率方面,地面单独运行时为28.4 FPS,空中单独运行时为44.7 FPS,空地联合运行时为19.8±1.1 FPS。集成带来的帧率开销约为30.3%(8.6 FPS),其中2.1 FPS归因于地面共存,6.5 FPS归因于空中物理引擎的计算。值得注意的是,当车辆数量翻倍进入交通监控模式时,帧率几乎不变(20.1 FPS),说明平台对Actor数量具有良好的扩展性。图7 | CARLA-Air稳定性测试量化结果。 经过三小时无人机、车辆、行人及传感器的持续创建与销毁压力测试,CARLA-Air全程保持稳定运行,无任何卡顿或报错,最低帧率维持在19.7 FPS。这一长时复杂任务下的稳定性表现,使CARLA-Air能够胜任数据采集、在线强化学习等长周期任务场景。在稳定性方面,平台经历了长达3小时的耐久测试,期间完成了357个Actor生成/销毁周期,帧率始终稳定在19.7±1.3 FPS,显存无显著累积(线性拟合R²仅0.11),全程零API错误、零仿真崩溃。图8 | 空地协同精准降落全过程。(a)时序图展示了无人机从接近到触地的五个关键时刻;(b)3D轨迹显示无人机轨迹(蓝色)逐步收敛到车辆轨迹(橙色);(c)高度曲线记录了从12米到地面的平滑下降过程;(d)水平误差从约6米迅速收敛至0.5米以内。整个过程以19.3 FPS运行,耗时约20秒,零RPC错误。在具身导航方面,CARLA-Air还展示了支持视觉语言动作(VLA)数据生成的能力。无人机可以在城市上空自主跟踪行人,每一帧都伴随着链式推理(Think/Action)的注释,为训练具身导航大模型提供了丰富的标注数据。图9 | 无人机自主跟踪行人的视觉语言导航演示,无人机与行人飞别用蓝色框与红色框标记,无人机接受的指令为“跟随在行人后方,保持行人位于相机画面中心”。该过程展示了CarlaAir平台在生成VLA训练数据,验证空地协同VLA算法以及进行在线强化学习方面的潜力。6—总结与延伸CARLA-Air的出现,代表了仿真基础设施从"单域专精"向"跨域融合"演进的重要趋势。它以极其优雅的工程设计——仅修改约35行上游代码——就打通了地面驾驶与空中飞行之间的仿真壁垒,为空地协同、跨视角感知、具身导航和强化学习等前沿方向提供了统一的实验底座。随着低空经济的蓬勃发展和具身大模型的快速演进,空地协同智能正在从学术概念走向工程落地。CARLA-Air作为一个完备的开源项目,是否会成为这一领域的"标准基础设施"?REF•论文标题:CARLA-Air: Fly Drones Inside a CARLA World — A Unified Infrastructure for Air-Ground Embodied Intelligence•论文链接:https://arxiv.org/abs/2603.28032 •项目主页:https://github.com/louiszengCN/CarlaAir 以上,原文完。来源:车路漫漫

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈