2017-04-15 21:22:50 +02:00
|
|
|
This document provides an overview of how Klipper implements robot
|
|
|
|
motion (its [kinematics](https://en.wikipedia.org/wiki/Kinematics)).
|
|
|
|
The contents may be of interest to both developers interested in
|
|
|
|
working on the Klipper software as well as users interested in better
|
|
|
|
understanding the mechanics of their machines.
|
|
|
|
|
|
|
|
Acceleration
|
|
|
|
============
|
|
|
|
|
|
|
|
Klipper implements a constant acceleration scheme whenever the print
|
|
|
|
head changes velocity - the velocity is gradually changed to the new
|
|
|
|
speed instead of suddenly jerking to it. Klipper always enforces
|
|
|
|
acceleration between the tool head and the print. The filament
|
|
|
|
leaving the extruder can be quite fragile - rapid jerks and/or
|
|
|
|
extruder flow changes lead to poor quality and poor bed adhesion. Even
|
|
|
|
when not extruding, if the print head is at the same level as the
|
|
|
|
print then rapid jerking of the head can cause disruption of recently
|
|
|
|
deposited filament. Limiting speed changes of the print head (relative
|
|
|
|
to the print) reduces risks of disrupting the print.
|
|
|
|
|
|
|
|
It is also important to enforce a maximum acceleration of the stepper
|
|
|
|
motors to ensure they do not skip or put excessive stress on the
|
|
|
|
machine. Klipper limits the acceleration of each stepper by virtue of
|
|
|
|
limiting the acceleration of the print head. Enforcing acceleration at
|
|
|
|
the print head naturally also enforces acceleration at the steppers
|
|
|
|
that control that print head (the inverse is not always true).
|
|
|
|
|
|
|
|
Klipper implements constant acceleration. The key formula for
|
|
|
|
constant acceleration is:
|
|
|
|
```
|
|
|
|
velocity(time) = start_velocity + accel*time
|
|
|
|
```
|
|
|
|
|
|
|
|
Trapezoid generator
|
|
|
|
===================
|
|
|
|
|
|
|
|
Klipper uses a traditional "trapezoid generator" to model the motion
|
|
|
|
of each move - each move has a start speed, it accelerates to a
|
|
|
|
cruising speed at constant acceleration, it cruises at a constant
|
|
|
|
speed, and then decelerates to the end speed using constant
|
|
|
|
acceleration.
|
|
|
|
|
|
|
|
![trapezoid](img/trapezoid.svg.png)
|
|
|
|
|
|
|
|
It's called a "trapezoid generator" because a velocity diagram of the
|
|
|
|
move looks like a trapezoid.
|
|
|
|
|
|
|
|
The cruising speed is always greater than or equal to both the start
|
|
|
|
speed and the end speed. The acceleration phase may be of zero
|
|
|
|
duration (if the start speed is equal to the cruising speed), the
|
|
|
|
cruising phase may be of zero duration (if the move immediately starts
|
|
|
|
decelerating after acceleration), and/or the deceleration phase may be
|
|
|
|
of zero duration (if the end speed is equal to the cruising speed).
|
|
|
|
|
|
|
|
![trapezoids](img/trapezoids.svg.png)
|
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
Look-ahead
|
|
|
|
==========
|
2017-04-15 21:22:50 +02:00
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
The "look-ahead" system is used to determine cornering speeds between
|
2017-04-15 21:22:50 +02:00
|
|
|
moves.
|
|
|
|
|
|
|
|
Consider the following two moves contained on an XY plane:
|
|
|
|
|
|
|
|
![corner](img/corner.svg.png)
|
|
|
|
|
|
|
|
In the above situation it is possible to fully decelerate after the
|
|
|
|
first move and then fully accelerate at the start of the next move,
|
|
|
|
but that is not ideal as all that acceleration and deceleration would
|
|
|
|
greatly increase the print time and the frequent changes in extruder
|
|
|
|
flow would result in poor print quality.
|
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
To solve this, the "look-ahead" mechanism queues multiple incoming
|
2017-04-15 21:22:50 +02:00
|
|
|
moves and analyzes the angles between moves to determine a reasonable
|
|
|
|
speed that can be obtained during the "junction" between two moves. If
|
2017-04-27 17:19:30 +02:00
|
|
|
the next move is nearly in the same direction then the head need only
|
|
|
|
slow down a little (if at all).
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
![lookahead](img/lookahead.svg.png)
|
|
|
|
|
2017-04-27 21:48:56 +02:00
|
|
|
However, if the next move forms an acute angle (the head is going to
|
|
|
|
travel in nearly a reverse direction on the next move) then only a
|
|
|
|
small junction speed is permitted.
|
2017-04-27 17:19:30 +02:00
|
|
|
|
|
|
|
![lookahead](img/lookahead-slow.svg.png)
|
|
|
|
|
2017-04-15 21:22:50 +02:00
|
|
|
The junction speeds are determined using "approximated centripetal
|
|
|
|
acceleration". Best
|
2017-04-27 17:19:30 +02:00
|
|
|
[described by the author](https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/).
|
2017-04-15 21:22:50 +02:00
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
Klipper implements look-ahead between moves contained in the XY plane
|
2017-04-27 17:19:30 +02:00
|
|
|
that have similar extruder flow rates. Other moves are relatively rare
|
|
|
|
and implementing look-ahead between them is unnecessary.
|
2017-04-15 21:22:50 +02:00
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
Key formula for look-ahead:
|
2017-04-15 21:22:50 +02:00
|
|
|
```
|
|
|
|
end_velocity^2 = start_velocity^2 + 2*accel*move_distance
|
|
|
|
```
|
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
Smoothed look-ahead
|
|
|
|
-------------------
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
Klipper also implements a mechanism for smoothing out the motions of
|
|
|
|
short "zig-zag" moves. Consider the following moves:
|
|
|
|
|
|
|
|
![zigzag](img/zigzag.svg.png)
|
|
|
|
|
|
|
|
In the above, the frequent changes from acceleration to deceleration
|
|
|
|
can cause the machine to vibrate which causes stress on the machine
|
|
|
|
and increases the noise. To reduce this, Klipper tracks both regular
|
|
|
|
move acceleration as well as a virtual "acceleration to deceleration"
|
|
|
|
rate. Using this system, the top speed of these short "zig zag" moves
|
|
|
|
are limited to smooth out the printer motion:
|
|
|
|
|
|
|
|
![smoothed](img/smoothed.svg.png)
|
|
|
|
|
|
|
|
In the above, note the dashed gray lines - this is a graphical
|
|
|
|
representation of the "pseudo acceleration". Where the two dashed
|
|
|
|
lines meet enforces a limit on the move's top speed. For most moves
|
|
|
|
the limit will be at or above the move's existing limits and no change
|
|
|
|
in behavior is induced. However, for short "zig-zag" moves the limit
|
|
|
|
comes into play and it reduces the top speed. Note that the grey lines
|
|
|
|
represent a pseudo-acceleration to limit top speed only - the move
|
|
|
|
continues to use it's normal acceleration scheme up to its adjusted
|
|
|
|
top-speed.
|
|
|
|
|
|
|
|
Generating steps
|
|
|
|
================
|
|
|
|
|
2017-04-20 02:28:37 +02:00
|
|
|
Once the look-ahead process completes, the print head movement for the
|
2017-04-15 21:22:50 +02:00
|
|
|
given move is fully known (time, start position, end position,
|
|
|
|
velocity at each point) and it is possible to generate the step times
|
|
|
|
for the move. This process is done within "kinematic classes" in the
|
|
|
|
Klipper code. Outside of these kinematic classes, everything is
|
|
|
|
tracked in millimeters, seconds, and in cartesian coordinate space.
|
|
|
|
It's the task of the kinematic classes to convert from this generic
|
|
|
|
coordinate system to the hardware specifics of the particular printer.
|
|
|
|
|
|
|
|
In general, the code determines each step time by first calculating
|
|
|
|
where along the line of movement the head would be if a step is
|
|
|
|
taken. It then calculates what time the head should be at that
|
|
|
|
position. Determining the time along the line of movement can be done
|
|
|
|
using the formulas for constant acceleration and constant velocity:
|
|
|
|
|
|
|
|
```
|
|
|
|
time = sqrt(2*distance/accel + (start_velocity/accel)^2) - start_velocity/accel
|
|
|
|
time = distance/cruise_velocity
|
|
|
|
```
|
|
|
|
|
|
|
|
Cartesian Robots
|
|
|
|
----------------
|
|
|
|
|
|
|
|
Generating steps for cartesian printers is the simplest case. The
|
|
|
|
movement on each axis is directly related to the movement in cartesian
|
|
|
|
space.
|
|
|
|
|
|
|
|
Delta Robots
|
|
|
|
------------
|
|
|
|
|
|
|
|
To generate step times on Delta printers it is necessary to correlate
|
|
|
|
the movement in cartesian space with the movement on each stepper
|
|
|
|
tower.
|
|
|
|
|
2017-04-27 17:19:30 +02:00
|
|
|
To simplify the math, for each stepper tower, the code calculates the
|
|
|
|
location of a "virtual tower" that is along the line of movement.
|
|
|
|
This virtual tower is chosen at the point where the line of movement
|
|
|
|
(extended infinitely in both directions) would be closest to the
|
|
|
|
actual tower.
|
|
|
|
|
2017-04-15 21:22:50 +02:00
|
|
|
![delta-tower](img/delta-tower.svg.png)
|
|
|
|
|
2017-04-27 17:19:30 +02:00
|
|
|
It is then possible to calculate where the head will be along the line
|
|
|
|
of movement after each step is taken on the virtual tower.
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
![virtual-tower](img/virtual-tower.svg.png)
|
|
|
|
|
2017-04-27 17:19:30 +02:00
|
|
|
The key formula is Pythagoras's theorem:
|
2017-04-15 21:22:50 +02:00
|
|
|
```
|
|
|
|
distance_to_tower^2 = arm_length^2 - tower_height^2
|
|
|
|
```
|
|
|
|
|
|
|
|
One complexity is that if the print head passes the virtual tower
|
|
|
|
location then the stepper direction must be reversed. In this case
|
|
|
|
forward steps will be taken at the start of the move and reverse steps
|
|
|
|
will be taken at the end of the move.
|
|
|
|
|
|
|
|
### Delta movements beyond simple XY plane ###
|
|
|
|
|
|
|
|
Movement calculation is a little more complicated if the move is not
|
|
|
|
fully contained within a simple XY plane. A virtual tower along the
|
|
|
|
line of movement is still calculated, but in this case the tower is
|
|
|
|
not at a 90 degree angle relative to the line of movement:
|
|
|
|
|
|
|
|
![xy+z-tower](img/xy+z-tower.svg.png)
|
|
|
|
|
|
|
|
The code continues to calculate step times using the same general
|
|
|
|
scheme as delta moves within an XY plane, but the slope of the tower
|
|
|
|
must also be used in the calculations.
|
|
|
|
|
|
|
|
Should the move contain only Z movement (ie, no XY movement at all)
|
|
|
|
then the same math is used - just in this case the tower is parallel
|
2017-04-27 17:19:30 +02:00
|
|
|
to the line of movement.
|
2017-04-15 21:22:50 +02:00
|
|
|
|
2017-04-20 01:46:41 +02:00
|
|
|
### Stepper motor acceleration limits ###
|
|
|
|
|
|
|
|
With delta kinematics it is possible for a move that is accelerating
|
|
|
|
in cartesian space to require an acceleration on a particular stepper
|
|
|
|
motor greater than the move's acceleration. This can occur when a
|
|
|
|
stepper arm is more horizontal than vertical and the line of movement
|
|
|
|
is near that stepper's tower.
|
|
|
|
|
|
|
|
Klipper does enforce a maximum ceiling on stepper acceleration that is
|
|
|
|
three times the maximum acceleration of a move in cartesian
|
|
|
|
space. (Similarly, the maximum velocity of the stepper is limited to
|
|
|
|
three times the maximum move velocity.) In order to enforce this
|
|
|
|
limit, moves at the extreme edge of the build envelope (where a
|
|
|
|
stepper arm may be nearly horizontal) will have a lower maximum
|
|
|
|
acceleration and velocity.
|
|
|
|
|
2017-04-15 21:22:50 +02:00
|
|
|
Extruder kinematics
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
Klipper implements extruder motion in its own kinematic class. Since
|
|
|
|
the timing and speed of each print head movement is fully known for
|
|
|
|
each move, it's possible to calculate the step times for the extruder
|
|
|
|
independently from the step time calculations of the print head
|
|
|
|
movement.
|
|
|
|
|
|
|
|
Basic extruder movement is simple to calculate. The step time
|
|
|
|
generation uses the same constant acceleration and constant velocity
|
|
|
|
formulas that cartesian robots use.
|
|
|
|
|
|
|
|
### Pressure advance ###
|
|
|
|
|
|
|
|
Experimentation has shown that it's possible to improve the modeling
|
|
|
|
of the extruder beyond the basic extruder formula. In the ideal case,
|
|
|
|
as an extrusion move progresses, the same volume of filament should be
|
|
|
|
deposited at each point along the move and there should be no volume
|
|
|
|
extruded after the move. Unfortunately, it's common to find that the
|
|
|
|
basic extrusion formulas cause too little filament to exit the
|
|
|
|
extruder at the start of extrusion moves and for excess filament to
|
|
|
|
extrude after extrusion ends. This is often referred to as "ooze".
|
|
|
|
|
|
|
|
![ooze](img/ooze.svg.png)
|
|
|
|
|
|
|
|
The "pressure advance" system attempts to account for this by using a
|
|
|
|
different model for the extruder. Instead of naively believing that
|
|
|
|
each mm^3 of filament fed into the extruder will result in that amount
|
|
|
|
of mm^3 immediately exiting the extruder, it uses a model based on
|
|
|
|
pressure. Pressure increases when filament is pushed into the extruder
|
|
|
|
(as in [Hooke's law](https://en.wikipedia.org/wiki/Hooke%27s_law)) and
|
|
|
|
the pressure necessary to extrude is dominated by the flow rate
|
|
|
|
through the nozzle orifice (as in
|
2017-04-27 17:19:30 +02:00
|
|
|
[Poiseuille's law](https://en.wikipedia.org/wiki/Poiseuille_law)). The
|
2017-04-20 02:28:37 +02:00
|
|
|
key idea is that the relationship between filament, pressure, and flow
|
|
|
|
rate can be modeled using a linear coefficient:
|
|
|
|
```
|
|
|
|
extra_filament = pressure_advance_coefficient * extruder_velocity
|
|
|
|
```
|
|
|
|
|
|
|
|
See the [pressure advance](Pressure_Advance.md) document for
|
|
|
|
information on how to find this pressure advance coefficient.
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
Once configured, Klipper will push in an additional amount of filament
|
2017-04-20 02:28:37 +02:00
|
|
|
during acceleration. The higher the desired filament flow rate, the
|
|
|
|
more filament must be pushed in during acceleration to account for
|
|
|
|
pressure. During head deceleration the extra filament is retracted
|
|
|
|
(the extruder will have a negative velocity).
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
![pressure-advance](img/pressure-advance.svg.png)
|
|
|
|
|
|
|
|
One may notice that the pressure advance algorithm can cause the
|
|
|
|
extruder motor to make sudden velocity changes. This is tolerated
|
|
|
|
based on the idea that the majority of the inertia in the system is in
|
|
|
|
changing the extruder pressure. As long as the extruder pressure does
|
2017-04-20 02:28:37 +02:00
|
|
|
not change rapidly the sudden changes in extruder motor velocity are
|
|
|
|
tolerated.
|
2017-04-15 21:22:50 +02:00
|
|
|
|
|
|
|
One area where sudden velocity changes become problematic is during
|
|
|
|
small changes in head speed due to cornering.
|
|
|
|
|
|
|
|
![pressure-cornering](img/pressure-cornering.svg.png)
|
|
|
|
|
|
|
|
To prevent this, the Klipper pressure advance code utilizes the move
|
2017-04-20 02:28:37 +02:00
|
|
|
look-ahead queue to detect intermittent speed changes. During a
|
|
|
|
deceleration event the code finds the maximum upcoming head speed
|
|
|
|
within a configurable time window. The pressure is then only adjusted
|
|
|
|
to this found maximum. This can greatly reduce (or even completely
|
|
|
|
eliminate) pressure changes during cornering.
|