GRBL's cornering algorithm

Updated on .

Cornering is how a machine tool head follows a path through a vertex at speed given a machine’s physical constraints. Sonny Jeon’s article on improving GRBL’s cornering algorithm describes a heuristic that keeps a machine’s centripetal acceleration constant by approximating the corner with a circle. It’s implemented in GRBL’s planner C code and widely copied by other motion planning systems.

GRBL is a G-code interpreter and receives high-level instructions for where to move the tool and converts them to low-level stepper motor movements. In contrast, EiBotBoard’s “low-level move” commands and Klipper leave motion planning up to control software running on more powerful devices and communicate detailed moves to simple firmware. Regardless, any open source motion planning system I could find use Jeon’s algorithm to lower speed going into corners.

Theory

This algorithm finds a cornering velocity based on the maximum acceleration the machine is capable of and a user-defined constant factor. In mathematical terms, cornering velocity vcv_c with constant centripetal acceleration aa around a circle of radius rr is given by vc=arv_c = \sqrt{ar}. This is derived from analyzing the change in velocity for circular motion.

The algorithm uses a circle that touches the edges of the corner and a deviation factor δ\delta to control the minimum distance between the corner and the circle. A smaller δ\delta translates to a smaller rr and a proportionally smaller vcv_c. Bisecting the angle θ\theta of the two edges creates a right triangle with the opposite side having length rr and the hypotenuse length r+δr + \delta. From trigonometry:

sinθ2=rr+δ\sin{\theta \over 2} = {r \over {r + \delta}}

And rearranging the terms to solve for rr:

r=rsinθ2+δsinθ2r = r \sin{\theta \over 2} + \delta \sin{\theta \over 2}rrsinθ2=δsinθ2r - r \sin{\theta \over 2} = \delta \sin{\theta \over 2}r(1sinθ2)=δsinθ2r (1 - \sin{\theta \over 2}) = \delta \sin{\theta \over 2}r=δsinθ21sinθ2r = \delta {\sin{\theta \over 2} \over {1 - \sin{\theta \over 2}}}

The angle θ\theta is given by the dot product of the incoming edge ei\vec e_i and the outgoing edge eo\vec e_o:

cosθ=eieoeieo\cos{\theta} = {\vec e_i \cdot \vec e_o \over |\vec e_i| |\vec e_o|}

To avoid the expensive cos1\cos^{-1} and sin\sin operations, Sonny used the half-angle identity for sin\sin:

sinθ2=±1cosθ2\sin{\theta \over 2} = \pm \sqrt{1 - \cos{\theta} \over 2}

Where the sign of the expression is the sign of:

2πθ+4πθ4π2 \pi - \theta + 4 \pi {\left\lfloor {\theta \over 4 \pi} \right\rfloor}

For an angle θ\theta in [θ,2π][\theta, 2 \pi], the expression is always positive. Keeping the expression in terms of cosine allows substitution of the dot product, which is just a sum of products, which in 2-dimensions is:

eieo=eixeox+eiyeoy\vec e_i \cdot \vec e_o = e_{ix} e_{ox} + e_{iy} e_{oy}

To compute the cosine:

cosθ=eixeox+eiyeoyeieo\cos{\theta} = {e_{ix} e_{ox} + e_{iy} e_{oy} \over |\vec e_i| |\vec e_o|}

Combining the equations above to find vcv_c:

c=1eixeox+eiyeoyeieo2c = \sqrt{1 - {e_{ix} e_{ox} + e_{iy} e_{oy} \over |\vec e_i| |\vec e_o|} \over 2}r=δc1cr = \delta {c \over 1 - c}vc=aδc1cv_c = \sqrt{a \delta {c \over 1 - c}}

This approach requires just two square root operations for each vertex. The division by the two vector’s magnitudes are usually avoided by normalzing the vectors to the unit vectors.

The cornering velocity is used as the ending and starting velocities for the motion pieces leading to and from the vertex in Constant acceleration motion planning.

Implementations

GRBL’s code is particularly terse, but benefits from thorough commenting. Instead of discrete operators for the vector components of motion, the operations are done incrementally, without any wasted steps.

Saxi overall has a more understandable structure to the code, with ASCII art comments to describe trapezoidal motion planning.

Klipper’s code is accompanied by a Kinematics document.