Skip to main content

Declaration

Each LiDAR or radar is one channel of foxglove.PointCloud messages, declared in the overlay’s point_clouds array with its kind, which a PointCloud message cannot carry:

Fields

Include intensity and ring whenever you have them. They cost only storage, and they cannot be added later without re-uploading.

Frames

Every LiDAR cloud is placed in the vehicle frame (x forward, y left, z up, z = 0 at the ground). Choose one of two shapes per cloud, by the message’s frame_id: A sensor-frame cloud without a transform is rejected, never used as is: a transform applied twice, or not at all, produces a plausible-looking and entirely wrong cloud. Positions, vectors and scalars transform differently, and mixing them up is silent:
  • positions (x, y, z) rotate, then translate;
  • velocities and directions (e.g. radar vx, vy) rotate only. Only positions are transformed at ingest, so publish per-point vectors already in the vehicle frame;
  • scalars (intensity, ring, rcs) are frame-invariant and pass through.
A sensor with no elevation channel (most automotive radar) shows a constant z equal to its mounting height after transformation. That is correct.

Several LiDARs

Publish either one already-merged LiDAR in the vehicle frame, or one channel per sensor in its own frame with its transform. Several lidar channels are merged by frame index: frame i of every sensor forms one cloud. Per-sensor channels MUST therefore be index-aligned: the same number of frames, frame i of each covering the same sweep. Unequal counts are merged up to the shortest channel, with a warning.

LiDAR-only recordings

A recording with no camera is valid when its first declared lidar carries x, y, z and ring: the LiDAR is rendered as a range-image video (one row per beam), which becomes the recording’s video. A recording with no camera and a LiDAR without ring is rejected, with an error naming the missing field. See A recording must have a video.