Sensor-LiDAR Profile USD Authoring Guide#
This document describes how to author a USD asset that conforms to the
Sensor-LiDAR profile.
Sensor-LiDAR is a sensor profile: it validates the LiDAR sensors an asset
carries, not the asset itself. Stamp it alongside the asset’s primary profile
(Robot-Body, Robotics-Prop, or whichever profile matches the host asset — see the profile index).
LiDAR is an RTX rendering sensor. It fires rays and produces point cloud data
through the GPU render pipeline, which is why its capability sits under
nonvisual_sensors/ — the output is rendered data rather than physics
simulation state. A LiDAR that writes through a RenderProduct is also
covered by Sensor-Camera, which owns the render product
and compression rules; stamp both.
Validating an asset against this profile requires both the Sensors tier and the Core tier:
pip install simready-validate simready-foundation-tier-sensors simready-foundation-tier-core
Profile definition#
The Sensor-LiDAR profile contains a single feature (see profiles.toml
alongside this document, and the
feature dependency graph):
[Sensor-LiDAR]
"1.0.0" = {features = [
{"FET_036_RTX" = {version = "0.1.0"}}, # "LiDAR (OmniLidar RTX)"
]}
FET_036_RTX defines the schema and parameter
consistency contract for OmniLidar sensor prims.
What the profile checks#
All four requirements belong to the Non-Visual Sensors/LiDAR capability.
Requirement |
Summary |
|---|---|
A LiDAR must be an |
|
Every emitter state array must have the same length as |
|
|
|
For solid-state LiDARs, the elements of |
These checks apply only to the OmniLidar prims a stage actually contains.
An asset with no LiDAR passes this profile without asserting anything, and
LI.004 additionally does not apply to rotary sensors. A passing result
therefore means “every LiDAR present is configured consistently”, not “this
asset produces a point cloud” — confirm the sensor exists before treating
conformance as evidence that it does.
Required USD authoring#
Use the OmniLidar schema#
def OmniLidar "Lidar" (
prepend apiSchemas = ["OmniSensorGenericLidarCoreAPI"]
)
{
uint omni:sensor:Core:numberOfEmitters = 1
}
The legacy pattern of a UsdGeom.Camera prim carrying
cameraSensorType = "lidar" is rejected by LI.001. Assets migrating from
that pattern need the prim retyped, not just re-tagged.
Keep the emitter arrays consistent#
omni:sensor:Core:numberOfEmitters declares how many laser emitters the
sensor has. Per-emitter configuration is stored in parallel arrays named
omni:sensor:Core:emitterState:<instance>:<attr>, for example:
omni:sensor:Core:emitterState:s001:azimuthDeg
omni:sensor:Core:emitterState:s001:elevationDeg
omni:sensor:Core:emitterState:s001:channelId
Each of these must contain exactly numberOfEmitters elements, and they must
agree with one another (LI.002). The one exception is isRoiState, which
may have a different length. A mismatch hands the sensor runtime malformed
parameters and the output is wrong rather than absent.
Respect the scan rate floor#
omni:sensor:Core:scanRateBaseHz must be at least 0.466 Hz (LI.003). The
reason is a hard limit rather than a style preference: the runtime stores
per-point time offsets in GenericModelOutput as signed 32-bit nanosecond
integers, which top out at roughly 2.147 seconds. Below 0.466 Hz a single
scan cycle exceeds that, and timeOffsetNs overflows, corrupting the timing
data in the point cloud.
Match rays per line to emitter count on solid-state sensors#
Solid-state LiDARs (omni:sensor:Core:scanType = "SOLID_STATE") arrange a
fixed 2-D emitter array into lines, with omni:sensor:Core:numRaysPerLine
declaring how many emitters fire per line. Those values must sum to
numberOfEmitters (LI.004). For example, numberOfEmitters = 4 with
numRaysPerLine = [2, 2] is consistent.
This does not apply to rotary LiDARs (scanType = "ROTARY"), which do not use
the attribute. A mismatch on a solid-state sensor makes the simulation reject
the configuration at startup, so validating it early turns a runtime error
into an authoring-time one.
Validation#
A sensor profile is validated in its own run. “Stamping both profiles” means validating the asset against each one; there is no combined invocation:
simready-validate --profile Robotics-Prop --version 4.0.0 path/to/asset.usd
simready-validate --profile Sensor-LiDAR --version 1.0.0 path/to/asset.usd
Both runs must pass. The sensor profile is not a substitute for the primary one — on its own it says nothing about units, hierarchy, physics, materials, or packaging.
If you record the result in the optional validation dictionary under
SimReady_Metadata, note that the documented form holds a single profile
and profile_version. Record the primary profile there and track sensor
conformance alongside it; the metadata has no multi-profile form today.
Runtime verification#
Static validation confirms the schema and parameter consistency. It cannot
confirm the sensor measures accurately. The Benchmark test
lidar_point_cloud surrounds each sensor with 16 cubes at asymmetric known
distances, runs 120 RTX scan frames, and checks each return against the
expected wall distance. It passes when fewer than 1% of returns exceed 2%
range error, measured across non-edge returns:
pip install "simready-foundation-tier-sensors[benchmark]"
simready-benchmark --features FET_036_RTX
The [benchmark] extra installs the Benchmark engine; a validator-only tier
install does not include it.
This test requires GPU driver 576.x or newer for RTX LiDAR CUDA 12.9 support in Isaac Sim 6.0.1. On an older driver every scan buffer comes back empty and the test skips rather than fails, so confirm it actually ran before treating a clean report as evidence that the sensor measures correctly.
Samples#
Passing:
sample_content/common_assets/sensors/lidar/OmniLidarCheckerPass.usdasample_content/common_assets/sensors/lidar/OmniLidarSolidStateCheckerPass.usdasample_content/common_assets/sensors/lidar/OmniLidarSolidStateRTXPass.usda
Failing, one per rule:
OmniLidarCheckerFail.usda(LI.001)OmniLidarEmitterStateCheckerFail.usda(LI.002)OmniLidarScanRateCheckerFail.usda(LI.003)OmniLidarSolidStateCheckerFail.usda(LI.004)OmniLidarRangeCountCheckerFail.usda
All under sample_content/common_assets/sensors_fails/lidar/.
References#
profiles.toml, the profile definition alongside this document