Step 3 — Proportional Control Correction
The error map from Step 2 is fed into a proportional controller that adjusts the G-code feedrates for the next layer to compensate for measured surface-height deviations. This closes the control loop.
Control Law
F_corrected = F_nominal * (1 + K_p * z_err_mm)
Where:
F_nominal— the feedrate in the original (uncorrected) G-code for the next layer.K_p— proportional gain (default: 1.0). Tuned experimentally.z_err_mm— the surface height error at the nearest measured point from the previous layer's error map.
Intuition
- Positive error (surface too high) → increase feedrate → robot moves faster → deposits less material → surface drops.
- Negative error (surface too low) → decrease feedrate → robot moves slower → deposits more material → surface rises.
Spatial Matching
For each extruding G-code point (E > 0) in the next layer's toolpath,
the controller finds the nearest point in the error map CSV (by 3D
Euclidean distance) and applies that point's err_mm value to the
feedrate formula. Only extruding moves are modified; travel moves are
passed through unchanged.
Command
uv run python simple_proportional.py \
<next_layer.gcode> \
<L<N>_error_map.csv> \
-k <K_p> \
-o <next_layer_corrected.gcode>
Working directory: ros2_ws/lib/control/simple_proportional/
Arguments
| Flag | Default | Purpose |
|---|---|---|
| Positional 1 | — | Next layer's nominal G-code file |
| Positional 2 | — | Previous layer's error_map.csv |
-k, --proportional_constant | 1.0 | Proportional gain K_p |
-o | — | Output path for corrected G-code |
--lower_bounds_corrected_feed | 3.2 | Minimum allowed corrected feedrate |
--preview | — | Generate an HTML 3D plot of the feedrate corrections (path auto-derived if flag given without value) |
Inputs
1. Next Layer G-Code (nominal)
Standard slicer output. Only G1 moves with non-zero E values have
their F parameter adjusted.
G1 X-7.119 Y-17.261 E24.0 F3.4 ;N4
G1 X-5.676 Y-16.964 E24.0 F3.4 ;N5
2. Previous Layer Error Map (CSV)
X,Y,Z,err_mm
12.2021,47.3637,43.2479,4.0644
10.7972,47.6810,43.2649,4.0644
Output
A corrected G-code file identical to the input except that feedrate (F)
values on extruding moves have been scaled according to the control law.
This file becomes the input to Step 1 for the next iteration.
Future Work
The current controller is purely proportional (P-only). Planned extensions include:
- Integral (I) term — accumulate historical error across multiple layers to eliminate steady-state offset.
- Derivative (D) term — respond to the rate of error change between consecutive layers.
- Full PID tuning with per-region gain scheduling.