Getting range bias when using GAUSSIAN_BEAM as ray-type for RTX LiDAR

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 RTX lidar model with a few emitters facing a wall at 2.0m. When using GAUSSIAN_BEAM as the choice of omni:sensor:Core:rayType the reported range is 2.20499992370605, instead of 2.0. However, changing the ray type to IDEALIZED gets rid of this issue, and I do see 2.0 range.

Questions:

  1. I wonder what is the cause of such huge variation by simply changing the ray-type?
  2. Even if there is some variation due to Gaussian beam physics, I wouldn’t expect such a high deviation at 2 meters range. Is this a bug?
  3. Also, for omni:sensor:Core:numberOfEmitters being 6, I am getting only 3 timestamps using the IsaacCreateRTXLidarScanBuffer annotator. Shouldn’t that be 6?

Full USDA to reproduce the issue

#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      = 6
uint    omni:sensor:Core:numberOfChannels      = 6
uint    omni:sensor:Core:numLines              = 1
uint[]  omni:sensor:Core:numRaysPerLine        = [6]
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               = "GAUSSIAN_BEAM"
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            = 0
float[] omni:sensor:Core:rangesMinM            = []
float[] omni:sensor:Core:rangesMaxM            = []

# ----- FMCW optical ---------------------------------------------------
# 10 mW average per emitter is realistic for an eye-safe 1550 nm coherent
float   omni:sensor:Core:avgPowerW             = 0.1
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           = 1
# 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.03
float   omni:sensor:Core:divergenceVerDeg      = 0.03
# 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.1
# 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            = 10000.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 = false

# ----- 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.1, 0.1, 0.2, 0.2]
float[] omni:sensor:Core:emitterState:s001:elevationDeg = [0.0, 0.1, 0.0, 0.1, 0.0, 0.1]
uint[]  omni:sensor:Core:emitterState:s001:fireTimeNs   = [0, 2500, 5000, 7500, 10000, 12500]
uint[]  omni:sensor:Core:emitterState:s001:channelId    = [1, 2, 3, 4, 5, 6]
# uint[]  omni:sensor:Core:emitterState:s001:rangeId      = [0, 0, 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, 0, 0]
# float[] omni:sensor:Core:emitterState:s001:distanceCorrectionM = [0.205, 0.205]
}

Hi @vikram37,

Thanks for the detailed report.

Issue 1: Range Bias with GAUSSIAN_BEAM (~10% offset)

The ~0.205m offset (2.205m reported vs 2.0m actual) when using GAUSSIAN_BEAM is significant and likely a bug.

Can you try with Isaac Sim 6.0 and see if this issue persists?
If this issue still exists in Isaac Sim 6.0, could you please try:

  1. Setting rangeAccuracyM to a non-zero value (e.g., 0.01) to see if the bias changes
  2. Testing at different ranges (e.g., 5m, 10m) to see if the bias is constant (offset) or proportional (scale factor)
  3. Checking if beamWaistHorM/VerM values affect the bias

This will help determine if it’s a fixed offset bug or something in the Gaussian beam propagation model.

Issue 2: Timestamps (3 instead of 6)

Other users have reported similar issue for Isaac Sim 5.1. Could you please try Isaac Sim 6.0 and see if this issue still persists for you?

If this range bias is confirmed as a bug, we can file an additional internal ticket to track it.

Hello!

We noticed that this topic hasn’t received any recent updates from anyone reporting this issue, so we are closing it for now to help keep the forum organized.

If you are still experiencing this issue or have related questions, please create a GitHub Discussion or Issue in the Isaac Sim repository and include a link to this topic along with updated details. Mentioning or linking to this original topic provides helpful context and makes it easier for others to assist you.

Thank you for being part of the NVIDIA Isaac Sim community.

Best regards,
The NVIDIA Isaac Sim Forum Team