关于 isaac-sim-sensor
isaac-sim-sensor 是用于在 Isaac Sim 6 / Kit 110 中构建传感器与合成数据流程的技术技能,涵盖 RTX 和物理传感器、Replicator 工作流、厂商配置及数据 Writer。
主要功能
- 01创建相机传感器和标注器
- 02配置 RTX 激光雷达、雷达和声学传感器
- 03添加 IMU、接触等物理传感器
- 04应用 Replicator 域随机化
- 05使用 Writer 接收传感器输出
适用场景
- 01采集相机 RGB、深度和分割数据
- 02将厂商激光雷达和 IMU 安装到机器人上
- 03收集雷达或声学输出且避免丢帧
- 04生成经过随机化的合成传感器数据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ isaac-sim/ isaacsim --skill isaac-sim-sensor安装后在 Claude Code 中输入/isaac-sim-sensor确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
scripts/attach_lidar_imu.pycreate_camera_sensor.pylidar_gmo_writer.py详细介绍
Omniverse 传感器仿真
用途
使用 Replicator 和实验性传感器 API 模拟 RTX 摄像头、LiDAR、雷达、声学和物理传感器,包括供应商配置和安装座附件。
前提条件
- 已构建 Isaac Sim(
$ISAAC_SIM_DIR或_build/linux-x86_64/release)。 - 配备 NVIDIA GPU,且驱动程序为当前版本(
nvidia-smi)。 - 使用
isaac-sim-orchestrator中的 Shell 环境变量约定:$ISAAC_SIM_DIR、$ISAAC_LAB_DIR、$WORKSPACE_DIR。
限制
- 除非某节另有说明,否则适用于 Isaac Sim 6 / Kit 110。
- 对于不受支持的边缘情况,请参阅 NVIDIA 官方文档。
故障排除
| 错误 / 现象 | 原因 | 解决方案 |
|---|---|---|
| 找不到扩展或导入模块 | $ISAAC_SIM_DIR 错误或构建已过时 | 将环境变量指向 _build/linux-x86_64/release,或重新构建 |
| 画面全黑或为空 | 缺少灯光,或未使用 RTX 渲染模式 | 添加穹顶灯 / 主光;确认 RTX / PathTracing 设置 |
| 加载场景或首次渲染时卡住 | MDL 编译或场景过大 | 按照 isaac-sim-troubleshooting 中的隔离步骤操作 |
摄像头(RGB / 深度 / 分割 / 边界框)、LiDAR / 雷达 / 声学、IMU / 接触 / 力,以及 Replicator 域随机化。适用于 Isaac Sim 6 / Kit 110。
新代码请使用现代命名空间:
| 系列 | 模块 |
|---|---|
| RTX 传感器(LiDAR、雷达、声学、RTX 摄像头) | isaacsim.sensors.experimental.rtx |
| 物理传感器(接触、IMU、力、关节状态、射线投射) | isaacsim.sensors.experimental.physics |
| Replicator 核心 | omni.replicator.core as rep |
| Replicator 示例 / SDG | isaacsim.replicator.examples |
| 移动机器人 SDG | isaacsim.replicator.mobility_gen |
| 抓取 SDG | isaacsim.replicator.grasping |
| 回合录制 / 回放 | isaacsim.replicator.episode_recorder |
| 遥操作录制 / 回放 | isaacsim.replicator.teleop |
| 域随机化辅助工具 | isaacsim.replicator.domain_randomization |
旧版 isaacsim.sensors.physics.* 和 isaacsim.sensors.camera.Camera 类仍可加载,但其实现已迁移至 experimental.* 扩展;新项目请优先使用这些扩展。
迁移: 使用各系列的迁移指南更新脚本 — 物理传感器、摄像头传感器和 RTX 传感器(LiDAR / 雷达 / 声学)。
可用脚本
| 脚本 | 用途 | 参数 |
|---|---|---|
scripts/attach_lidar_imu.py | 将 RTX Ouster LiDAR 和物理 IMU 安装到机器人底盘上 | 参见脚本 --help |
scripts/create_camera_sensor.py | 为 Isaac Sim Replicator 创建摄像头传感器并附加标注器 | 参见脚本 --help |
scripts/lidar_gmo_writer.py | Isaac Sim 的 RTX LiDAR GMO(GenericModelOutput)写入器模式 | 参见脚本 --help |
运行脚本
对于提供技能执行辅助工具的 Agent 运行时,请使用 run_script() 调用辅助工具:
run_script("scripts/create_camera_sensor.py", args=["--help"])
在已构建的 Isaac Sim 目录中,从 _build/*/release 使用 ./python.sh(Linux)或 python.bat(Windows)运行同一文件;对于不需要模拟器的脚本,也可以直接运行 Shell 辅助工具。
相关技能
isaac-camera:深入了解RtxCamera/CameraSensor、标定和畸变。isaac-sim-rendering:无头捕获流水线、RT2、ACES 色调映射。physics-simulation:场景配置和物理传感器(Contact、IMU等)。data-collection-sim:静态场景 SDG 写入器流水线。mobility-gen:由轨迹驱动的移动机器人 SDG。
0. 厂商传感器目录(SUPPORTED_LIDAR_CONFIGS)
isaacsim.sensors.experimental.rtx.SUPPORTED_LIDAR_CONFIGS 是厂商激光雷达/雷达/声学 USD 资产的权威注册表。键是 get_assets_root_path() + "/Isaac/Sensors/..." 下的资产路径;值要么是针对 "sensor" 变体集的扁平变体名称 set,要么是显式 {variant_set: value} 字典组成的列表。配套常量 SUPPORTED_LIDAR_VARIANT_SET_NAME = "sensor" 指定了默认变体集名称。
| 制造商 | 型号(/Isaac/Sensors/ 下的资产路径) |
|---|---|
| NVIDIA | NVIDIA/Example_Rotary.usda、Example_Rotary_2D.usda、Example_Solid_State.usda、Simple_Example_Solid_State.usda |
| Ouster | Ouster/OS0/OS0.usd、OS1/OS1.usd、OS2/OS2.usd、VLS_128/Ouster_VLS_128.usd(rev6/rev7 变体,32/128 通道,10/20 Hz,512/1024/2048 分辨率) |
| Hesai | HESAI/XT32_SD10/HESAI_XT32_SD10.usd(另有 Pandar 系列资产) |
| Velodyne | VLP/HDL 系列(位于 Velodyne/ 下) |
| Robosense、SICK、Zvision 等 | 请参阅注册表/厂商文件夹 |
对于深度/立体摄像头(Intel RealSense D415/D435/D455/L515、Stereolabs ZED 2/2i/Mini/X),请使用摄像头式 RtxCamera 封装器和 SingleViewDepthCameraSensor;请参阅 isaac-camera。
Lidar.create(config=, variant=) 是简写形式:config 是去掉路径/扩展名后的注册表键;对于公开多个变体的资产(Ouster OS*、Hesai Pandar 等),必须指定 variant。
0.1 将厂商传感器连接到机器人安装架
USDA(根场景)
over "Robot" {
def Xform "sensor_mount" {
double3 xformOp:translate = (0.0, 0.0, 0.35)
uniform token[] xformOpOrder = ["xformOp:translate"]
def "lidar" (
prepend references = @${assetsRoot}/Isaac/Sensors/Ouster/OS1/OS1.usd@
variants = { string sensor = "OS1_REV6_32ch20hz512res" }
) {}
}
}
Python
from pxr import UsdGeom, Gf
from isaacsim.storage.native import get_assets_root_path
assets_root = get_assets_root_path()
mount = UsdGeom.Xform.Define(stage, "/World/Robot/sensor_mount")
UsdGeom.Xformable(mount.GetPrim()).AddTranslateOp().Set(Gf.Vec3d(0, 0, 0.35))
sensor_prim = stage.DefinePrim("/World/Robot/sensor_mount/lidar")
sensor_prim.GetReferences().AddReference(
assets_root + "/Isaac/Sensors/Ouster/OS1/OS1.usd"
)
vset = sensor_prim.GetVariantSets().GetVariantSet("sensor")
vset.SetVariantSelection("OS1_REV6_32ch20hz512res")
# Or use Lidar.create() at the mount path — it does both for you and
# returns the wrapper for runtime usage.
0.2 自定义扫描模式(USDA 发射器状态数组)
对于不在 SUPPORTED_LIDAR_CONFIGS 中的自定义传感器,请定义包含 OmniSensorGenericLidarCoreAPI 和发射器状态数组的 USDA prim。每束光由一个方位角、仰角和发射时间条目描述;固态激光雷达的数组可能达到数万个条目。
def Xform "Lidar" (
prepend apiSchemas = ["OmniSensorGenericLidarCoreAPI"]
)
{
float minRange = 0.1
float maxRange = 120.0
float horizontalFov = 360.0
float horizontalResolution = 0.1
float verticalFov = 45.0
float verticalResolution = 1.0
# Emitter state arrays define exact beam directions and timing.
float[] omni:sensor:Core:emitterState:s001:azimuthDeg = [0.0, 0.1, 0.2, ...]
float[] omni:sensor:Core:emitterState:s001:elevationDeg = [-22.5, -20.0, ...]
int[] omni:sensor:Core:emitterState:s001:fireTimeNs = [0, 55, 110, ...]
bool highLod = true
bool drawPoints = false
}
要从 Python 封装自定义 prim,请调用 Lidar("/World/.../my_lidar")(不传入 config= 参数);构造函数会封装现有 prim,而不是创建一个新 prim。
1. 摄像头(多 AOV 捕获)
RtxCamera + CameraSensor 是摄像头创建/捕获路径(不支持非 RTX 创建路径)。完整功能说明请参阅 isaac-camera。
create_camera_sensor(path, focal_length, resolution, annotators=None) — 创建 RtxCamera,通过 .camera 封装器设置其光学参数,并返回 CameraSensor(同时创建其渲染产品,并附加标准 RGB/深度/分割/边界框/法线/运动矢量标注器)。attach_annotators(sensor, annotators) — 对 CameraSensor.attach_annotators 的轻量封装,用于向现有传感器添加更多 AOV。resolution 遵循 OpenCV/NumPy 的 (height, width) 约定。
请参阅 scripts/create_camera_sensor.py。
平铺多视图/立体/镜头畸变:请使用 isaacsim.sensors.experimental.rtx.{TiledCameraSensor, SingleViewDepthCameraSensor, RtxCamera}。
2. Lidar(RTX)——基于 Writer 的 GMO 消费方式
RTX 传感器(Lidar、Radar、Acoustic)都会生成 GenericModelOutput(GMO)缓冲区,传感器调度器会在多帧更新期间异步发出该缓冲区——连续调用 simulation_app.update() / app_utils.update() 之间可能会产生零帧或多帧 GMO。每个 tick 都轮询 sensor.get_data("generic-model-output") 会导致帧丢失或重复。
使用 Writer 处理 GMO。 Replicator 调度器会对每个生成的渲染产品调用 Writer.write,因此消费者可以接收到每个事件,不会遗漏。这是所有标准 source/standalone_examples/api/isaacsim.sensors.experimental.rtx/* 示例(inspect_lidar_gmo.py、inspect_radar_gmo.py、inspect_acoustic_gmo.py、lidar_robot_integration.py、resolve_lidar_object_ids.py、apply_nonvisual_materials.py)采用的模式。以下模式可直接应用于 Radar / RadarSensor(第 3 节)以及 Acoustic / AcousticSensor(第 4 节)。
create_lidar_with_gmo_writer(path, config, variant, simulation_app)——创建 RTX lidar,定义一个附加 GenericModelOutput annotator 的 GmoInspectWriter,注册该 Writer,然后运行更新循环。
请参阅 scripts/lidar_gmo_writer.py。
如需实时视口可视化(而非数据采集),请改为附加内置的 draw-point-cloud writer:
sensor.attach_writer("draw-point-cloud", size=0.05, color=[0, 1, 0.5, 1.0])
isaacsim.sensors.experimental.rtx 中的 GMO 解码辅助函数:parse_generic_model_output_data、parse_stable_id_map_data、parse_object_ids、draw_annotator_data_to_image。
如需发布 ROS 2 lidar 扫描数据,请参阅 isaac-sim-ros2-bridge(ROS2PublishLaserScan、ROS2PublishPointCloud)。
3. Radar(RTX)
from isaacsim.sensors.experimental.rtx import Radar, RadarSensor
radar = Radar("/World/radar", tick_rate=20.0, aux_output_level="BASIC")
sensor = RadarSensor(radar, annotators=[])
附加一个 Writer 来消费 GMO——请参阅第 2 节。必须启用 Motion BVH(在 SimulationApp 初始化时设置 enable_motion_bvh=True,或设置 /renderer/raytracingMotion/enabled=true)。
4. Acoustic(RTX,超声波)
from isaacsim.sensors.experimental.rtx import Acoustic, AcousticSensor
acoustic = Acoustic(
"/World/acoustic",
tick_rate=30.0,
aux_output_level="BASIC",
attributes={
"omni:sensor:WpmAcoustic:centerFrequency": 51200.0,
"omni:sensor:WpmAcoustic:sensorMount:m001:position": (0.0, 0.0, 0.0),
},
)
sensor = AcousticSensor(acoustic, annotators=[])
附加一个 Writer 来消费 GMO——请参阅第 2 节。Acoustic GMO 对信号路径的编码方式为:gmo.x 是发射器安装 ID,gmo.y 是接收器安装 ID,gmo.z 是通道 ID,gmo.scalar 是振幅。
5. IMU(物理)
from isaacsim.sensors.experimental.physics import IMU, IMUSensor
import isaacsim.core.experimental.utils.app as app_utils
imu = IMU.create(path="/World/Robot/imu", tick_rate=200.0)
sensor = IMUSensor(imu, annotators=["linear_acceleration",
"angular_velocity",
"orientation"])
app_utils.play(commit=True)
frame = sensor.get_data() # IMUSensorReading
6. 接触 / 力(物理)
from isaacsim.sensors.experimental.physics import Contact, ContactSensor
contact = Contact.create(
path="/World/Robot/foot/contact",
min_threshold=0.0, max_threshold=1e6, radius=-1, # -1 = collision shape
)
sensor = ContactSensor(contact)
frame = sensor.get_data()
EffortSensor 和 JointStateSensor(位于同一模块)仅在运行时使用:按路径包装已有的关节 prim,然后在调用 app_utils.play(commit=True) 后调用 get_data()。这些传感器没有单独的构建类——该关节已在 URDF/MJCF 导入过程中创建。
from isaacsim.sensors.experimental.physics import EffortSensor, JointStateSensor
effort = EffortSensor("/World/Robot/joint_arm_1")
joint = JointStateSensor("/World/Robot/joint_arm_1")
7. Replicator 域随机化
通过 rep.functional.modify.semantics(现代函数式 API)或使用 isaacsim.core.experimental.utils.semantics.add_labels 为每个 prim 添加 UsdSemantics 架构,将 prim 标记为随机化目标。然后通过 rep.new_layer() 触发器驱动随机化。
import omni.replicator.core as rep
with rep.new_layer():
# Lights tagged with semantic ("type", "light")
lights = rep.get.prims(semantics=[("type", "light")])
with rep.trigger.on_frame(num_frames=100):
with lights:
rep.modify.attribute("intensity",
rep.distribution.uniform(500, 5000))
rep.modify.attribute("color",
rep.distribution.uniform((0.8,)*3, (1.0,)*3))
# Material swap on objects tagged ("class", "box")
objects = rep.get.prims(semantics=[("class", "box")])
with rep.trigger.on_frame():
with objects:
rep.randomizer.materials(rep.get.material("OmniPBR.*"))
rep.orchestrator.run()
如需使用预构建的随机化行为(散布、抖动、环境切换),请查看 isaacsim.replicator.domain_randomization 和 isaacsim.replicator.examples 独立示例。
8. Writers
omni.replicator.core 提供 BasicWriter、KittiWriter、CosmosWriter。isaacsim.replicator.writers 还提供 PoseWriter 和 DataVisualizationWriter。已弃用:DOPEWriter、YCBVideoWriter、PytorchWriter。
import omni.replicator.core as rep
writer = rep.WriterRegistry.get("KittiWriter")
writer.initialize(
output_dir="/output/synthetic_dataset",
semantic_types=["class"],
write_binary_pointcloud=False,
mapping={"box": "Car", "pallet": "Misc"},
)
writer.attach([render_product])
9. 工作流
| 工作流 | 模块 / 示例 |
|---|---|
| 带随机化的静态场景 SDG | data-collection-sim 技能 + isaacsim.replicator.examples(sdg_getting_started_0[1-5].py、sdg_workflow_0[12].py) |
| 移动机器人轨迹录制 + 回放 | mobility-gen 技能 + isaacsim.replicator.mobility_gen |
| 抓取数据集生成 | isaacsim.replicator.grasping(GraspingManager、GraspPhase)——参见 source/standalone_examples/api/isaacsim.replicator.grasping/grasping_workflow_sdg.py |
| Episode 录制 + 回放 | isaacsim.replicator.episode_recorder |
| 远程操控录制 + 回放 | isaacsim.replicator.teleop |
| Cosmos 仓库渲染 | isaacsim.replicator.examples/cosmos_writer_simple.py 和 source/standalone_examples/replicator/cosmos_writer_warehouse.py |
注意事项
- RTX-GMO 传感器(激光雷达、雷达、声学):使用
Writer,而非get_data。 在 multitick 模式下,传感器调度器会异步于simulation_app.update()发出 GMO 帧;轮询sensor.get_data("generic-model-output")会丢帧或重复帧。attach_writer由事件驱动,能够获取每个输出。对于CameraSensor的相机 AOV(rgb、distance_to_image_plane等)以及物理传感器(IMU、Contact、Effort、JointState),sensor.get_data(...)仍是文档规定的接口。 - 对于公开多个传感器变体的资源,
Lidar.create(config=..., variant=...)必须指定变体;注册表值会告知可用的变体集合。 aux_output_level的级别因模态而异:激光雷达支持NONE/BASIC/EXTRA/FULL;雷达 / 声学仅支持NONE/BASIC;RtxCamera仅支持NONE。- 高 LOD(
highLod=true)模式会生成更多点,但速度较慢。在无头模式下,设置drawPoints=false可提升性能。 - 设置
aux_output_level时,预期会出现这条“无害”的usdrt.population.plugin Unhandled attribute type VtArray<std::string>日志消息;Replicator 管线仍会获取该属性。 - 在运行
rep.orchestrator.run()之前附加 Replicator 标注器。 - 加载
isaacsim.sensors.experimental.rtx时,RTX 传感器会自动启用omni.sensors.nv.lidar/.nv.radar/.nv.acoustic;无需手动启用。 - 物理传感器需要先调用
app_utils.play(commit=True)(或timeline.play()),再调用get_data()。时间轴暂停时,传感器不会持续输出数据。 - 随机化触发器会累积;使用
rep.new_layer()隔离每次处理。 - 现代函数式 API 使用
rep.functional.modify.semantics(prim, {"class": "..."}, mode="add");旧版prims.create_prim(semantic_label=...)路径仍受支持,但不是当前文档推荐的路径。