Intensity variance in RTX Lidar due to BSDF

6.0.0
5.1.0
5.0.0
4.5.0
4.2.0
4.1.0
4.0.0
4.5.0
2023.1.1
2023.1.0-hotfix.1
Other (please specify):

Operating System

Ubuntu 24.04
Ubuntu 22.04
Ubuntu 20.04
Windows 11
Windows 10
Other (please specify):

GPU Information

  • Model: RTX PRO 5000 Blackwell
  • Driver Version: 580.142

Topic Description

Detailed Description

I am using a RTX lidar model with single emitter being shot at a wall at 4.0 m distance. The intensity keeps varying across the frames. The simulator should produce the physical link-budget output (range, defocus, incidence angle, material reflectance) repeatably - i.e., I want intensity that varies with the scene, not from a stochastic component re-rolled every frame.

Setup

omni:sensor:Core:rayType = “IDEALIZED”
omni:sensor:Core:azimuthErrorStd = 0.0
omni:sensor:Core:elevationErrorStd = 0.0
omni:sensor:Core:intensityProcessing = “RAW”

Target authored with the SimReady non-visual material schema:

omni:simready:nonvisual:base = “aluminum”
omni:simready:nonvisual:coating = “paint”
omni:simready:nonvisual:attributes = “none”

Resolves to materialId = 257 end-to-end (verified via outputMaterialId=True on IsaacCreateRTXLidarScanBuffer). USD-attribute resolver is enabled via /rtx/materialDb/nonVisualMaterialCSV/enabled = False.

Questions

Is there a supported way to disable the randomState / cuRand variance injection in the stock DefaultMaterial / CoreMaterial / CompositeMaterial / RetroReflectiveMaterial BSDFs? Is ConstantMaterial expected to be available at runtime in 5.1, or is it strictly a build-only debug BSDF? Here is the full USDA File:

Full USDA

#usda 1.0
(
defaultPrim = “SingleBeamFMCW”
upAxis = “Z”
metersPerUnit = 1.0
)

def OmniLidar “SingleBeamFMCW” (
prepend apiSchemas = [“OmniSensorGenericLidarCoreAPI”]
)
{
# Required xform ops so hydra can compute the lidar camera matrix.
double3 xformOp:translate = (0, 0, 0)
quatd xformOp:orient = (1, 0, 0, 0)
double3 xformOp:scale = (1, 1, 1)
uniform token
 xformOpOrder = [“xformOp:translate”, “xformOp:orient”, “xformOp:scale”]

# ----- Scan topology --------------------------------------------------
token   omni:sensor:Core:scanType              = "SOLID_STATE"
uint    omni:sensor:Core:numberOfEmitters      = 4
uint    omni:sensor:Core:numberOfChannels      = 4
uint    omni:sensor:Core:numLines              = 1
uint[]  omni:sensor:Core:numRaysPerLine        = [4]
uint    omni:sensor:Core:scanRateBaseHz        = 60
uint    omni:sensor:Core:reportRateBaseHz      = 60
uint    omni:sensor:Core:stateResolutionStep   = 1
token   omni:sensor:Core:rotationDirection     = "CW"
# Physical Gaussian profile so spot size, defocus, and aperture truncation
# actually feed the link budget. Requires Msquared + divergence values below.
token   omni:sensor:Core:rayType               = "IDEALIZED"
float   omni:sensor:Core:beamWaistHorM         = 0.002
float   omni:sensor:Core:beamWaistVerM         = 0.002

# ----- Range ----------------------------------------------------------
float   omni:sensor:Core:nearRangeM            = 0.5
float   omni:sensor:Core:farRangeM             = 200.0
float   omni:sensor:Core:rangeResolutionM      = 0.0002
float   omni:sensor:Core:rangeAccuracyM        = 0.00
uint    omni:sensor:Core:maxReturns            = 1
uint    omni:sensor:Core:rangeCount            = 1
float[] omni:sensor:Core:rangesMinM            = [0.5]
float[] omni:sensor:Core:rangesMaxM            = [200.0]

# ----- FMCW optical ---------------------------------------------------
# 10 mW average per emitter is realistic for an eye-safe 1550 nm coherent
# FMCW channel (e.g. Aeva / SiLC class chips run 10-40 mW per lane).
float   omni:sensor:Core:avgPowerW             = 0.020
float   omni:sensor:Core:waveLengthNm          = 1550.0
# Effective measurement-window width. For coherent FMCW the receiver is
# not pulsed, but this controls the per-shot SNR / range-resolution floor.
uint    omni:sensor:Core:pulseTimeNs           = 5
# Beam quality. Single-mode fiber laser is essentially TEM00 -> M^2 ~= 1.1.
float   omni:sensor:Core:Msquared              = 1.1
# Full-angle 1/e^2 divergence. 0.06 deg ~= 1 mrad, which gives a ~5 cm
# footprint at 50 m -- typical for a small solid-state FMCW unit.
float   omni:sensor:Core:divergenceHorDeg      = 0.06
float   omni:sensor:Core:divergenceVerDeg      = 0.06
# 10% reflectance still detectable at 250 m is a competitive (but not
# heroic) coherent-detection sensitivity curve.
float   omni:sensor:Core:minReflectance        = 0.1
float   omni:sensor:Core:minReflectionRangeM   = 250.0
# 25 mm receive aperture -- ~3x more collected photons than 14.5 mm.
float   omni:sensor:Core:effectiveApertureSizeM = 0.02
# Focus near the middle of the useful range, not 16 cm in front of the
# sensor. Old 0.16 m left the wall at 5 m heavily defocused.
float   omni:sensor:Core:focusDistM            = 50.0
# InGaAs APD / coherent receiver QE at 1550 nm is typically 0.3-0.5.
float   omni:sensor:Core:quantumEfficiency     = 1.0

# ----- Angular noise (deterministic) ----------------------------------
# Small solid-state pointing jitter: ~0.01 deg std (~175 urad), which is
# at the floor of what good MEMS / OPA scanners achieve.
float   omni:sensor:Core:azimuthErrorMean      = 0.0
float   omni:sensor:Core:azimuthErrorStd       = 0.0
float   omni:sensor:Core:elevationErrorMean    = 0.0
float   omni:sensor:Core:elevationErrorStd     = 0.0

# ----- Intensity processing ------------------------------------------
# Keep the raw radiometric value so range, defocus, incidence and material
# actually move the intensity column. NORMALIZATION would mask all of it.
token   omni:sensor:Core:intensityProcessing   = "RAW"
token   omni:sensor:Core:intensityMappingType  = "LINEAR"

# ----- Output enables ------------------------------------------------
token   omni:sensor:Core:auxOutputType         = "FULL"
token   omni:sensor:Core:outputFrameOfReference = "SENSOR"
bool    omni:sensor:Core:skipDroppingInvalidPoints = true

# ----- Emitter line (azimuth = -1..+1 deg, elevation = 0) -------------
# 4 emitters evenly spaced across +/-1 deg (step = 2/3 deg). Fire times
# are evenly spaced across the 1/30 s = 33,333,333 ns scan period.
float[] omni:sensor:Core:emitterState:s001:azimuthDeg   = [0.0, 0.0, 0.0, 0.0]
float[] omni:sensor:Core:emitterState:s001:elevationDeg = [0.0, 0.0, 0.0, 0.0]
uint[]  omni:sensor:Core:emitterState:s001:fireTimeNs   = [0, 10000, 20000, 30000]
uint[]  omni:sensor:Core:emitterState:s001:channelId    = [1, 2, 3, 4]
uint[]  omni:sensor:Core:emitterState:s001:rangeId      = [0, 0, 0, 0]
# bank == line index per emitter; must be < numLines. All 4 emitters are
# on the single line 0, so bank is all zeros.
uint[]  omni:sensor:Core:emitterState:s001:bank         = [0, 0, 0, 0]
# float[] omni:sensor:Core:emitterState:s001:distanceCorrectionM = [0.205, 0.205, 0.205, 0.205]
}

@vikram37

I reproduced the issue on a Isaac Sim 6.0.0 internal version using your exact SingleBeamFMCW USDA (4 emitters at (0,0) deg, 1550 nm FMCW, IDEALIZED, RAW, aluminum+paint wall at 4 m, materialId = 257 confirmed).

With your 4-emitter config (4 rays per frame, 68 frames analyzed):

  • Cross-frame CV: 112.6% (mean intensity varies wildly frame-to-frame)
  • Within-frame CV: 153.9% (among 4 rays hitting the same flat surface at the same distance)
  • Min frame mean: 0.0, Max frame mean: 0.000234

With a dense Example_Solid_State config (~16,330 rays per frame, same wall):

  • Within-frame CV: 89%, min 0.000016, max 0.000777 (~49x spread)

For a uniform flat wall with zero noise, all rays should return identical intensity. The variance is entirely from the BSDF cuRand injection.

(Note: your fireTimeNs = [0, 10000, 20000, 30000] exceeded the 27777 ns period for scanRateBaseHz=60 on my hardware, producing a maxFireTime > patternFiringRateHz error. Adjusted to [0, 6000, 12000, 18000] for the reproduction – this does not affect the BSDF variance finding.)

We will check internally and update you.

An internal ticket (OMPE-95365) has just been created to track this feature request: Expose option to disable stochastic BSDF sampling for RTX lidar sensor rays.