[ovrtx 0.4.0] OmniLidar returns 0 points when numberOfEmitters is authored — is the explicit emitter table supported?

Hello,

I am evaluating `ovrtx` as a Kit-free RTX lidar harness and hit a wall importing an existing vendor lidar profile. I have reduced it to a two-line change against your own shipped example, so I hope this is easy to check.

**Summary**

Adding two `omni:sensor:Core:` attributes to the `OmniLidar` prim in `examples/python/lidar/lidar_example.usda` drops the returned point count from 275,027 to 0. Either of the following is independently sufficient:

- `numberOfEmitters` + `numberOfChannels`

- `emitterState:s001:azimuthDeg` + `emitterState:s001:elevationDeg`

The more telling detail: it is not that rays are cast and the returns are then rejected. The `PointCloud` tensor allocation itself collapses from 921,600 to 1.

```

scene Counts[0] valid(0x40) Flags alloc

----------------------------------------------------------------------------------

stock example 275027 275027 921600

+ numberOfEmitters=64, numberOfChannels=64 0 0 1

+ 8-entry azimuthDeg / elevationDeg 0 0 1

```

That reads to me as the sensor model computing Nmax as 0 from the emitter table rather than scaling the output buffer to it. No error or warning is emitted at `log_level=“info”`, and the sensor is otherwise recognised and scheduled normally:

```

[Info] [omni.sensorscheduling] Added sensor … with tick rate 10.00 Hz, exposure time 0.100000 s

[Info] [omni.rtx.sensors] Sensor Type is eOmniLidar

[Info] [omni.rtx.sensors] LIDAR: AuxiliaryOutputType: 0, Enabled compaction: 1

```

The failing log is structurally identical to the working one.

**Reproduction**

All files are in the attached `ovrtx_lidar_repro.zip` (self-contained, no external assets).

```

pip install ovrtx ovstage numpy

python run_repro.py --all

```

```

scene valid points

----------------------------------------

scene_A_stock 275027

scene_B_emitter_counts 0

scene_C_emitter_arrays 0

```

Scene B in full. This is the only difference from your shipped example:

```

def OmniLidar “Lidar” (

prepend apiSchemas = \["OmniSensorGenericLidarCoreAPI"\]

)

{

token omni:sensor:Core:elementsCoordsType = "CARTESIAN"

uint omni:sensor:Core:numberOfEmitters = 64      # <-- added

uint omni:sensor:Core:numberOfChannels = 64      # <-- added

double2 omni:sensor:frameRate = (10, 1)



double3 xformOp:translate = (0, 0, 1)

float3 xformOp:rotateXYZ = (90, 0, -90)

uniform token\[\] xformOpOrder = \["xformOp:translate", "xformOp:rotateXYZ"\]

}

```

`diagnose_sceneB.py` in the archive reproduces the allocation table above.

**What I already ruled out**

Applied on top of scene B, none of these restore the allocation. All stay at `alloc=1`, `Counts=0`:

- `includeInvalidPoints = 1`, so this is not a case of returns being generated and then dropped as invalid

- `instantLidar = 1`

- `partialOutputs = 0`

- `numRows` / `numCols`, individually and together

- `rotPatternFiringResDeg = 0.1`

- `numLines = 64` together with `numRaysPerLine = [3600]`

- explicitly applying `OmniSensorGenericLidarCoreEmitterStateAPI:s001`. It is already auto-applied: `OmniSensorGenericLidarCoreAPI` lists it in its own `apiSchemas` at `generatedSchema.usda` line 403.

Tested independently on top of a working default-config lidar, the following are harmless and still return points. This is what narrows the cause to the emitter counts and the azimuth/elevation arrays specifically:

- `emitterStatesFile = “”`

- `stateResolutionStep = 1`

- the empty emitter arrays: `bank`, `distanceCorrectionM`, `focalDistM`, `focalSlope`, `horOffsetM`, `reportRateDiv`, `roi`, `vertOffsetM`

Also ruled out as a cause: missing non-visual material labels. Per `docs/sensors/nonvisual_materials.rst`, unlabeled surfaces fall back to `DefaultMaterial`, and empirically a default-config lidar does return points in the very same scene.

**Why I suspect a gap rather than my own mistake**

A recursive grep over the whole `ovrtx` repository returns zero matches for `emitterState`, `numberOfEmitters`, `numberOfChannels`, and `EmitterStateAPI`. No example, doc page, docs-test, or skill exercises the explicit emitter-table path. Both shipped lidar examples set exactly one `omni:sensor:Core:` attribute and rely on defaults for everything else.

The published docs I checked, namely `sensors/lidar.html`, `sensors/pointclouds.html`, `sensors/nonvisual_materials.html` and `sensors/configuration.html`, document the output attributes and channels thoroughly but say nothing about emitter tables.

The only mention anywhere is a single sentence in `skills/configuring-lidar-sensors/SKILL.md`: “Add emitter-state API schemas only when authoring custom firing patterns with explicit emitter state arrays.” There is no worked example of what a complete explicit emitter table requires.

**Questions**

1. Is the explicit emitter-table path, meaning `numberOfEmitters` plus per-channel `emitterState:sNNN:*` arrays, supported in ovrtx 0.4.0? Or is it schema surface that is not yet wired to the sensor model?

2. If it is supported, which additional attributes must accompany `numberOfEmitters` so the model can size the `PointCloud` output? A minimal working USDA would resolve this completely.

3. Is there a supported path to import an Isaac Sim RTX lidar profile, in the `omni:sensor:Core:*` form such as a 64-channel Hesai or Livox calibration table, into ovrtx? That is my actual goal: reproducing an existing sensor’s real firing geometry outside Kit.

Happy to test patches or provide more logs.

**Environment**

```

ovrtx 0.4.0.346409 (PyPI)

ovstage 0.1.0.346039 (PyPI)

Python 3.10.12

OS Ubuntu, Linux 6.8.0-124-generic

GPU 2x NVIDIA GeForce RTX 3090 Ti

Driver 580.159.04

numpy 2.2.6

```

Note: the README states Python 3.11+, but the wheel is `py3-none` and installs and runs correctly on 3.10.12.