Normalize the junction direction vector over XYZE (#15308)

* Normalize the junction direction vector over XYZE

calc_vmax_junction_deviation() treats the dot product of two jd_unit_vec as a
cosine, but the vectors were scaled by 1 / block.distance, which is the XYZ
length. On an extruding move the E component then pushes the 4D norm above 1 and
the dot product below -1, so the corner reads as straighter than it is and is
planned too fast -- the more so the higher the flow. Measured on a 6 degree
corner at scv 5: 86.9mm/s with no extrusion, 94.4mm/s at 0.029mm/mm, 150.0mm/s
at 0.1mm/mm.

Neither firmware does that. Marlin normalizes over XYZE for any extruding move
(planner.cpp: `if (... || esteps > 0) normalize_junction_vector(unit_vec)`) and
Klipper leaves E out of the cosine entirely, dotting only axes_r[0..2]
(toolhead.py::Move.calc_junction). Normalizing satisfies both: with E normalized
in, the cosine differs from the XYZ-only one by ~1e-5 at printing flow rates.

This is a deliberate divergence from PrusaSlicer, which still scales by
1 / distance -- it carries an older Marlin's behaviour.

Travel moves are unaffected, their vector was already unit length.

Reported by Copilot in review of #15304.

* Test that extrusion rate does not change corner planning

The junction deviation tests were all travel-only, which is exactly why the E
component of the junction vector went unchecked. Cover it: the same corner has
to be planned the same whether nothing, an ordinary 0.42 x 0.2 line, or a fat
large-nozzle line is extruded through it, on both Klipper and Marlin 2.

Reported by Copilot in review of #15304.
This commit is contained in:
Ian Bassi
2026-08-20 18:50:23 -03:00
committed by GitHub
parent 87ca2bc42e
commit ca65f0fd8e
3 changed files with 55 additions and 19 deletions
+2 -3
View File
@@ -637,9 +637,8 @@ class Print;
//For line move, there are same. For arc move, there are different.
Vec3f enter_direction;
Vec3f exit_direction;
// Orca: move direction over all four axes, scaled by 1 / block.distance. Used by
// calc_vmax_junction_deviation(), which needs E to see extrusion-rate changes
// between collinear moves the way Marlin and Klipper do.
// Orca: move direction over all four axes, unit length. Used by
// calc_vmax_junction_deviation(); see there for why E is normalized in.
Vec4f jd_unit_vec;
void reset();