Print Loop — Process Flow
The WAAM print loop is a closed-loop cycle that prints a layer of metal, measures the resulting surface error, and feeds that measurement back into the toolpath for the next layer. Each iteration drives the surface height closer to its nominal value.
┌──────────────────────────────────────────────────────┐│ ││ ┌─────────────────────────────────────────────┐ ││ │ 1. EXECUTE G-CODE + RECORD ROSBAG │ ││ │ gcode_file_parser_client │ ││ │ ros2 bag record … │ ││ └──────────────────┬──────────────────────────┘ ││ │ ││ ▼ ││ ┌─────────────────────────────────────────────┐ ││ │ 2. MAP SURFACE-Z ERROR │ ││ │ rosbag_parser │ ││ │ → plot.html + error_map.csv │ ││ └──────────────────┬──────────────────────────┘ ││ │ ││ ▼ ││ ┌─────────────────────────────────────────────┐ ││ │ 3. PROPORTIONAL CONTROL CORRECTION │ ││ │ simple_proportional_control │ ││ │ → corrected_layer.gcode │ ││ └──────────────────┬──────────────────────────┘ ││ │ ││ └───────────────────────────┘ ││ loop back to step 1 │└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐│ 4. AGGREGATE ERROR STACKUP (post-hoc, any time) ││ aggregate_error_stackup ││ → stackup.html + stackup_summary.csv ││ Reads all L*.csv from state_dir ││ Confirms controller convergence over layers │└──────────────────────────────────────────────────────┘Data Flow (type signatures)
Section titled “Data Flow (type signatures)”Using Haskell-style notation to express what each stage consumes and produces:
-- Step 1: execute toolpath, observe physical resultgcode_file_parser_client :: GCode -> IO PhysicalDeposition
-- (concurrently)ros2_bag_record :: [Topic] -> IO BagDirectory
-- Step 2: associate error with robot XYZrosbag_parser :: BagDirectory -> GCode -> (HTML, CSV)-- CSV schema: X, Y, Z, err_mm
-- Step 3: correct next layer feedratessimple_proportional :: GCode_next -> CSV_err -> K_p -> GCode_corrected-- F_corrected = F_nominal * (1 + K_p * z_err_mm)
-- Step 4: aggregate multi-layer error for convergence analysisaggregate_error_stackup :: StateDir -> (AggregateHTML, SummaryCSV)-- Reads all L{N}.csv, produces 3D stackup + error trend chartRecorded ROS Topics
Section titled “Recorded ROS Topics”Each layer print records the following topics into an MCAP bag:
| Topic | Purpose |
|---|---|
/TSO_1/image_raw/compressed | Thermal stickout camera 1 |
/TSO_0/image_raw/compressed | Thermal stickout camera 0 |
/TSO_2/image_raw/compressed | Thermal stickout camera 2 |
/cams/table_1/image_raw/compressed | Table-mounted camera 1 |
/cams/table_0/image_raw/compressed | Table-mounted camera 0 |
/kuka/pose | Robot TCP pose (PoseStamped) |
/wire_stickout/err_surface_mm | Surface height error (Float64) |
/kuka/velocity_cartesian | Cartesian velocity |
/therm/image_raw/compressed | Thermal camera |
/kuka/sequence_number | Motion sequence counter |
Quick-Reference Commands
Section titled “Quick-Reference Commands”Step 1 — Execute & Record
Section titled “Step 1 — Execute & Record”# start recording (in one terminal)ros2 bag record -o L<N>_Z<ZZ> \ --topics \ /TSO_1/image_raw/compressed \ /TSO_0/image_raw/compressed \ /TSO_2/image_raw/compressed \ /cams/table_1/image_raw/compressed \ /cams/table_0/image_raw/compressed \ /kuka/pose \ /wire_stickout/err_surface_mm \ /kuka/velocity_cartesian \ /therm/image_raw/compressed \ /kuka/sequence_number
# execute gcode (in another terminal)ros2 run gcode_file_parser_client gcode_file_parser_client <layer.gcode>Step 2 — Map Surface Error
Section titled “Step 2 — Map Surface Error”uv run python map_surface_err_to_xyz_pos.py \ <bag_directory>/ \ <layer.gcode> \ --nominal_z <ZZ> \ --no-gcode \ -o <STATE/ERR/L<N>.html> \ --smooth 12 \ --trim_first_n_err_vals 32 \ --trim_last_n_err_vals 32Step 3 — Correct Next Layer
Section titled “Step 3 — Correct Next Layer”uv run python simple_proportional.py \ <next_layer.gcode> \ <L<N>_error_map.csv> \ -k <K_p> \ -o <next_layer_corrected.gcode>Then go back to Step 1 with the corrected G-code.
Step 4 — Aggregate Error Stackup (post-hoc)
Section titled “Step 4 — Aggregate Error Stackup (post-hoc)”# from ros2_ws/lib/control/aggregate_error_stackup/uv run python aggregate_error_stackup.py <STATE/ERR/job_dir/>Run at any time during or after a print job. Reads all L*.csv in the
state directory and produces stackup.html (3D stackup + error trend)
and stackup_summary.csv (per-layer error statistics). Serve for remote
viewing with python3 -m http.server 8080.
Automated Orchestrator (print_loop)
Section titled “Automated Orchestrator (print_loop)”Instead of running each step manually, the print-loop orchestrator drives the entire cycle from a single YAML config file:
# from ros2_ws/lib/control/print_loop/uv run python print_loop.py my_job.yamlThe orchestrator:
- Resolves all gcode file paths from the
slices_dirautomatically. - Starts/stops bag recording and gcode execution as subprocesses.
- Runs
map_surface_err_to_xyz_pos.pyandsimple_proportional.py. - Opens the error-map HTML for visual inspection between layers.
- Waits for operator confirmation before printing the next layer.
- Saves resumable state to
{state_dir}/{job_name}_state.json.
Use --dry-run to verify path resolution without executing anything:
uv run python print_loop.py my_job.yaml --dry-runSee example_config.yaml in ros2_ws/lib/control/print_loop/ for a
template configuration.
See the sub-pages for detailed descriptions of each step.