Python: SPG Composite AOV#
An SPG node whose input is a lidar rather than a camera. A lidar PointCloud is a
composite AOV: several named channels published together under one render var, instead of
the single image a camera AOV gives you. This node reads the Coordinates and Counts
channels, counts the sweep’s returns by distance, and publishes a bar chart on its own AOV.
The scene the sensor sweeps, from a second render product with an ordinary camera. The orange post marks the lidar; the grey box is 6 m away and the tan box 12 m away and twice as wide:
What the node made of that sweep, one bar per box:
Prerequisites#
Python 3.10-3.13
An NVIDIA RTX-capable GPU and a supported driver
Running#
uv run main.py # CUDA
uv run main.py --scene lidar_scene_slang.usda # Slang
One renderer.step() fills two render products: the lidar and its histogram, and an
ordinary camera view of the same scene. A successful run writes _output/histogram.png, the
node’s chart with axes and labels drawn around it, and _output/scene.png, the camera’s view.
Binding the Channels#
Each channel binds like any other buffer:
outputs["Histogram"] = cuda.image(WIDTH, HEIGHT, cuda.uchar4)
return cuda.kernel({
args = {
cuda.int(WIDTH), -- -> int width
cuda.int(HEIGHT), -- -> int height
cuda.int(maxPoints), -- -> int maxPoints
cuda.int(numBins), -- -> int numBins
cuda.float(inputs["maxRange"]), -- -> float maxRange
cuda.float(inputs["maxCount"]), -- -> float maxCount
cuda.array(coordinates), -- -> const float* coordinates
cuda.array(counts), -- -> const int* counts
cuda.SurfaceObject(outputs["Histogram"]), -- -> cudaSurfaceObject_t histogram
},
-- One thread per output column, each counting its own bin.
block = { THREADS },
grid = { math.ceil(WIDTH / THREADS) },
})
See Read a Sensor Composite for what a composite AOV is and how the channels are found.