Skip to content

print_loop

-- The closed-loop WAAM print cycle, orchestrated.
print_loop :: PrintJobConfig -> IO ()
-- For each layer N in [start..end]:
-- 1. record_bag + execute_gcode :: GCode -> IO BagDirectory
-- 2. map_surface_error :: BagDirectory -> (HTML, CSV)
-- 3. proportional_correction :: (CSV, GCode_next) -> GCode_corrected
-- [operator inspects HTML, confirms]
-- loop.

Interactive CLI orchestrator that drives the three-step WAAM print loop from a single YAML config file. Eliminates manual path copy-pasting between steps; the only human input required is a visual sanity-check of the error-map plot before each subsequent layer prints.

Terminal window
# from ros2_ws/lib/control/print_loop/
uv run python print_loop.py my_job.yaml

Verify path resolution without touching the robot:

Terminal window
uv run python print_loop.py my_job.yaml --dry-run
Manual step you used to doNow handled by
Compose ros2 bag record with ~10 topic flagsConfig YAML topics list
Copy-paste long gcode pathsAuto-resolved from slices_dir using *_layers_{N}-{N}_1layers.gcode naming convention
Remember bag dir name, feed to Step 2Derived: {bag_output_dir}/L{N}_Z{nominal_z}
Derive CSV path from HTML outputDerived: {state_dir}/L{N}.csv
Increment layer numbers, compute nominal Znominal_z(layer) = z_base + layer * z_per_layer
Run Step 2 + Step 3 as manual uv run invocationsSubprocess orchestration with error handling

Copy example_config.yaml and fill in your job parameters:

job_name: mayor_1
slices_dir: /path/to/layer_slices/
bag_output_dir: /path/to/BAGS/
state_dir: ~/PhotogrammetryWAAM/STATE/ERR/
start_layer: 21
end_layer: 43
z_base: 5.0
z_per_layer: 2.0
error_mapping:
smooth: 12
trim_first: 32
trim_last: 32
control:
k_p: 0.25
lower_bounds_corrected_feed: 4.2

Per layer, the orchestrator runs Steps 1-2 automatically, then:

Error map: ~/STATE/ERR/L21.html
Opening in browser...
Review the error map. Continue? [Y/n/q]

On confirmation it runs Step 3 and prompts once more before printing the next layer. Answering q at any prompt saves state and exits; rerunning the same command resumes from where you left off.

Progress is persisted to {state_dir}/{job_name}_state.json after every step. If the process is interrupted (Ctrl-C, SSH drop, power loss), relaunch the same command and it picks up at the last incomplete step.

The orchestrator calls the existing scripts as subprocesses (uv run / ros2 run) rather than importing them, keeping the uv environments independent:

  • Step 1: ros2 bag record (Popen + SIGINT) and ros2 run gcode_file_parser_client
  • Step 2: uv run python map_surface_err_to_xyz_pos.py (in shared/rosbag_parser/)
  • Step 3: uv run python simple_proportional.py (in ros2_ws/lib/control/simple_proportional/)
FilePurpose
print_loop.pyMain orchestrator CLI
models.pyPrintJobConfig, LayerState, PrintLoopState (Pydantic)
example_config.yamlTemplate job configuration
tests/test_print_loop.pyConfig loading, path resolution, state persistence

Full specification (../spec/)