Skip to content

Step 4 — Aggregate Error Stackup

The per-layer error CSVs produced by Step 2 accumulate in the state directory over the course of a print job. Step 4 aggregates them into a single interactive visualization that confirms the proportional controller’s performance: error should diminish as layers progress.

An interactive Plotly scene showing every layer’s robot path and error surface at their physical Z heights — a literal “pancake stack” of the build. Each layer has two traces:

TraceVisualData
Robot pathCool→warm gradient by layer progressionX, Y, Z from CSV
Error surfaceRed-Yellow-Green colorscale by error magnitudeX, Y, Z + err_mm

Layers are toggle-able via the legend. Hover reveals coordinates and error values.

A 2D subplot below the 3D scene charting per-layer error statistics against layer number:

SeriesMetric
RMS errorsqrt(mean(err_mm²))
Meanerr
Maxerr

A downward slope confirms the controller is converging.

stackup_summary.csv — one row per layer with columns: layer, nominal_z, n_samples, mean_abs_err, rms_err, max_abs_err, std_err

Terminal window
# from ros2_ws/lib/control/aggregate_error_stackup/
uv run python aggregate_error_stackup.py <state_dir> [options]

Working directory: ros2_ws/lib/control/aggregate_error_stackup/

FlagDefaultPurpose
Positional 1State directory containing L*.csv files
-o, --output<state_dir>/stackup.htmlOutput HTML path
--summary<state_dir>/stackup_summary.csvSummary CSV path
--titleauto from dir nameCustom plot title
--layersall discoveredComma-separated layer subset
--no-trendfalseOmit the 2D trend subplot

All L{N}.csv files in the state directory, each with schema:

X,Y,Z,err_mm
12.2021,47.3637,43.2479,4.0644
10.7972,47.6810,43.2649,4.0644

These are produced by Step 2 (map_surface_err_to_xyz_pos.py) and accumulate naturally as the print loop runs.

  • During a print job — run between layer batches to check that error is trending downward. If not, consider adjusting k_p.
  • After a completed job — produce a final report of controller performance across all layers.
  • Comparing configurations — run on state directories from different print jobs to compare k_p values or other parameter changes.

The output HTML is self-contained (Plotly JS is inlined). Serve it over the network from the robot host:

8080/stackup.html
cd /path/to/STATE/ERR/job_dir/
python3 -m http.server 8080 --bind 0.0.0.0

Steps 1–3 form the real-time closed loop. Step 4 is a post-hoc analysis tool that reads the same artifacts the loop produces. It does not modify any state and can be run repeatedly as new layers become available.

Steps 1–3 (per layer, real-time) Step 4 (aggregate, any time)
│ │
▼ ▼
state_dir/L{N}.csv ──────────────→ stackup.html
stackup_summary.csv