Seeing the data and the labels
The scene and every round of labels are published. Both open in Foxglove with no custom panel and nothing to install.
Open it in the browser
The scene and every round of labels open in Foxglove on the demo site — nothing to download, nothing to install. The 100 MB recording is read over HTTP range requests, so playback starts without pulling the whole file.
Download
curl -O https://samples.magmalake.org/sitegen/v0.3.0/site_seed1_60s.mcap # 100 MB
curl -O https://samples.magmalake.org/sitegen/v0.3.0/labels_rounds.mcap # 347 KB
foxglove site_seed1_60s.mcap labels_rounds.mcap # or drag both in at once Foxglove merges multiple local files into a single playback timeline, so the labels line up with the recording frame for frame. Predictions live in their own file on purpose: the recording stays immutable, and one 100 MB scene serves any number of pipeline runs.
What to turn on
Add a 3D panel and set display frame to
map. Then:
| Topic | Schema | |
|---|---|---|
/lidar/points | foxglove.PointCloud | the sweep — set colour by to intensity |
/ego/joint_states | foxglove.JointStates | swing, boom, stick, bucket |
/camera/<name>/image | foxglove.CompressedImage | four cameras at the house corners |
/terrain/heightmap | foxglove.PointCloud | ground and stockpiles — at t₀, and again each time the bucket changes them |
/ground_truth/actors | foxglove.SceneUpdate | held out — the oracle cuboids |
/ground_truth/volumes | foxglove.JointStates | held out — cubic metres cut, carried, hauled and left standing; open it in a Plot panel |
/pred/* | foxglove.SceneUpdate | one topic per pipeline round, from the labels file |
Scrub to t ≈ 25 s: round 0 has objects standing on
the stockpile and round 2 does not. That is the 617 → 177 false-positive
drop, visible rather than tabulated. Add a Plot panel on
/ego/joint_states for the dig cycle — it repeats every 15 s, and
the flat stretch at t ≈ 26–34 s is the machine walking to its second station.
/ground_truth/* is the oracle. It is in the file so you can
see what a labeler was up against — a labeler must never read it.
Keeping the truth and the data in one recording is deliberate: the same
pass wrote both, so the truth cannot drift from what it describes.
What is in the scene
A 20-tonne excavator running a dig–swing–dump cycle, loading an articulated hauler that backs in, is loaded and hauls off before a second truck takes its place. Part-way through, the machine walks 6.5 m along the trench to a second dig station — house squared up, boom tucked — and the hauler repositions with it. A spotter holds station; a second worker crosses the swing radius. Two stockpiles sit at the angle of repose, a row of grade stakes runs along the north edge, and dust kicks up when the loaded truck pulls away.
Four things are deliberate:
The excavator is articulated. Base pose plus swing, boom, stick and bucket — four degrees of freedom on top of the body. Every link is its own ground-truth box, so a scorer can ask whether a labeler got the bucket right, which is the part that will actually hit something.
Proprioception is a published topic. The machine's own joint angles are free, exact labels. The LiDAR rides the house, so 27% of every sweep is the ego looking at itself — against 28% measured on a real excavator-mounted rig — and forward kinematics is what removes it before anything else runs.
The difficulty is in the sensor, not the scene. Points fall
off as 1/r², range noise grows with distance, dropout rises quadratically and
dust eats returns over a region. The numbers are measured, not invented: the
elevation band, range, ray budget and per-class intensity were calibrated
against GOOSE-Ex, 2,164 labelled
sweeps from four Ousters on a working Liebherr R924. At the default ray
budget a worker at 14 m gets 6 returns; at
--density real, the real rig's budget, 40
— against 141 on the real machine. The published v0.3.0 recording is the
first one made with it.
Nothing is balanced. Terrain is ~70% of returns, the machine's own body 27%, and the two workers together 0.08%. Real class imbalance, not a curated benchmark — and it got four times as severe once the worker was a person rather than a cuboid and the elevation band matched the real machine's.
Reproducing it
The scene is deterministic in its seed, and the part a pipeline reads is deterministic to the byte. Two runs produce identical sweeps, poses, oracle cuboids, per-point and per-pixel instance ids, volumes and heightmaps — every topic a labeler or a scorer touches, verified by checksum — so two pipelines under comparison consume exactly the same input.
The four Cycles colour images are the exception, and it is worth being precise about it. Path tracing is not bit-reproducible run to run, so between two otherwise identical runs about 1–5% of pixels differ, by at most 16 of 255 — sampling noise rather than a different picture, but enough to move the file's checksum. Pin the published file by URL when the images have to match too; regenerate when only the LiDAR and the truth matter.
git clone https://github.com/labelrefinery/sitegen
cd sitegen && make install
mkdir -p assets
curl -o assets/kloofendal_43d_clear_puresky_2k.hdr https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/kloofendal_43d_clear_puresky_2k.hdr
curl -o assets/gravel_diff_2k.jpg https://dl.polyhaven.org/file/ph-assets/Textures/jpg/2k/gravel/gravel_diff_2k.jpg
curl -o assets/gravel_rough_2k.jpg https://dl.polyhaven.org/file/ph-assets/Textures/jpg/2k/gravel/gravel_rough_2k.jpg
curl -o assets/gravel_nor_gl_2k.jpg https://dl.polyhaven.org/file/ph-assets/Textures/jpg/2k/gravel/gravel_nor_gl_2k.jpg
uv run sitegen generate --out site.mcap --seed 1 --duration 60 \
--camera-hz 1 --camera-renderer cycles --camera-assets assets
# 10 min, 100 MB
# sha256 5109120d... the published file. The LiDAR and every
# ground-truth topic reproduce exactly. sitegen overlay writes a label file from any tracker-schema CSV,
so your own pipeline's output can be viewed the same way.