Skip to content

Commit

Permalink
toolhead: Replace max_accel_to_decel with minimum_cruise_ratio
Browse files Browse the repository at this point in the history
The user facing max_accel_to_decel setting is complicated and
confusing.  Replace it with a new minimum_cruise_ratio parameter.
Internally this user-facing parameter will calculate the existing
low-level "accel_to_decel" mechanism.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
  • Loading branch information
KevinOConnor committed Mar 14, 2024
1 parent 18de421 commit 0105aa3
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 50 deletions.
1 change: 0 additions & 1 deletion config/printer-anycubic-4maxpro-2.0-2021.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ restart_method: arduino
kinematics: cartesian
max_velocity: 150
max_accel: 3000
max_accel_to_decel: 1500
max_z_velocity: 7
max_z_accel: 50
square_corner_velocity: 5
Expand Down
2 changes: 1 addition & 1 deletion config/printer-sovol-sv05-2022.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ restart_method: command
kinematics: cartesian
max_velocity: 300
max_accel: 1000
max_accel_to_decel: 1000
minimum_cruise_ratio: 0.0
max_z_velocity: 5
max_z_accel: 100

Expand Down
8 changes: 8 additions & 0 deletions docs/Config_Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ All dates in this document are approximate.

## Changes

20240313: The `max_accel_to_decel` parameter in the `[printer]` config
section has been deprecated. The `ACCEL_TO_DECEL` parameter of the
`SET_VELOCITY_LIMIT` command has been deprecated. The
`printer.toolhead.max_accel_to_decel` status has been removed. Use the
[minimum_cruise_ratio parameter](./Config_Reference.md#printer)
instead. The deprecated features will be removed in the near future,
and using them in the interim may result in subtly different behavior.

20240215: Several deprecated features have been removed. Using "NTC
100K beta 3950" as a thermistor name has been removed (deprecated on
20211110). The `SYNC_STEPPER_TO_EXTRUDER` and
Expand Down
25 changes: 18 additions & 7 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,22 @@ max_accel:
# will do so at the rate specified here. The value specified here
# may be changed at runtime using the SET_VELOCITY_LIMIT command.
# This parameter must be specified.
#max_accel_to_decel:
# A pseudo acceleration (in mm/s^2) controlling how fast the
# toolhead may go from acceleration to deceleration. It is used to
# reduce the top speed of short zig-zag moves (and thus reduce
# printer vibration from these moves). The value specified here may
# be changed at runtime using the SET_VELOCITY_LIMIT command. The
# default is half of max_accel.
#minimum_cruise_ratio: 0.5
# Most moves will accelerate to a cruising speed, travel at that
# cruising speed, and then decelerate. However, some moves that
# travel a short distance could nominally accelerate and then
# immediately decelerate. This option reduces the top speed of these
# moves to ensure there is always a minimum distance traveled at a
# cruising speed. That is, it enforces a minimum distance traveled
# at cruising speed relative to the total distance traveled. It is
# intended to reduce the top speed of short zigzag moves (and thus
# reduce printer vibration from these moves). For example, a
# minimum_cruise_ratio of 0.5 would ensure that a standalone 1.5mm
# move would have a minimum cruising distance of 0.75mm. Specify a
# ratio of 0.0 to disable this feature (there would be no minimum
# cruising distance enforced between acceleration and deceleration).
# The value specified here may be changed at runtime using the
# SET_VELOCITY_LIMIT command. The default is 0.5.
#square_corner_velocity: 5.0
# The maximum velocity (in mm/s) that the toolhead may travel a 90
# degree corner at. A non-zero value can reduce changes in extruder
Expand All @@ -116,6 +125,8 @@ max_accel:
# decelerate to zero at each corner. The value specified here may be
# changed at runtime using the SET_VELOCITY_LIMIT command. The
# default is 5mm/s.
#max_accel_to_decel:
# This parameter is deprecated and should no longer be used.
```

### [stepper]
Expand Down
2 changes: 1 addition & 1 deletion docs/G-Codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ The toolhead module is automatically loaded.

#### SET_VELOCITY_LIMIT
`SET_VELOCITY_LIMIT [VELOCITY=<value>] [ACCEL=<value>]
[ACCEL_TO_DECEL=<value>] [SQUARE_CORNER_VELOCITY=<value>]`: This
[MINIMUM_CRUISE_RATIO=<value>] [SQUARE_CORNER_VELOCITY=<value>]`: This
command can alter the velocity limits that were specified in the
printer config file. See the
[printer config section](Config_Reference.md#printer) for a
Expand Down
28 changes: 17 additions & 11 deletions docs/Kinematics.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Key formula for look-ahead:
end_velocity^2 = start_velocity^2 + 2*accel*move_distance
```

### Smoothed look-ahead
### Minimum cruise ratio

Klipper also implements a mechanism for smoothing out the motions of
short "zigzag" moves. Consider the following moves:
Expand All @@ -105,21 +105,27 @@ short "zigzag" moves. Consider the following moves:

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 "zigzag" moves
are limited to smooth out the printer motion:
and increases the noise. Klipper implements a mechanism to ensure
there is always some movement at a cruising speed between acceleration
and deceleration. This is done by reducing the top speed of some moves
(or sequence of moves) to ensure there is a minimum distance traveled
at cruising speed relative to the distance traveled during
acceleration and deceleration.

Klipper implements this feature by tracking both a regular move
acceleration as well as a virtual "acceleration to deceleration" rate:

![smoothed](img/smoothed.svg.png)

Specifically, the code calculates what the velocity of each move would
be if it were limited to this virtual "acceleration to deceleration"
rate (half the normal acceleration rate by default). In the above
picture the dashed gray lines represent this virtual acceleration rate
for the first move. If a move can not reach its full cruising speed
using this virtual acceleration rate then its top speed is reduced to
the maximum speed it could obtain at this virtual acceleration
rate. For most moves the limit will be at or above the move's existing
rate. In the above picture the dashed gray lines represent this
virtual acceleration rate for the first move. If a move can not reach
its full cruising speed using this virtual acceleration rate then its
top speed is reduced to the maximum speed it could obtain at this
virtual acceleration rate.

For most moves the limit will be at or above the move's existing
limits and no change in behavior is induced. For short zigzag moves,
however, this limit reduces the top speed. Note that it does not
change the actual acceleration within the move - the move continues to
Expand Down
10 changes: 5 additions & 5 deletions docs/Resonance_Compensation.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ First, measure the **ringing frequency**.
to 5.0. It is not advised to increase it when using input shaper
because it can cause more smoothing in parts - it is better to use
higher acceleration value instead.
2. Increase `max_accel_to_decel` by issuing the following command:
`SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
2. Disable the `miminum_cruise_ratio` feature by issuing the following
command: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0`
3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0`
4. If you have already added `[input_shaper]` section to the printer.cfg,
execute `SET_INPUT_SHAPER SHAPER_FREQ_X=0 SHAPER_FREQ_Y=0` command. If you
Expand Down Expand Up @@ -149,7 +149,7 @@ a few other related parameters.
Print the ringing test model as follows:

1. Restart the firmware: `RESTART`
2. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
2. Prepare for test: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0`
3. Disable Pressure Advance: `SET_PRESSURE_ADVANCE ADVANCE=0`
4. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=MZV`
5. Execute the command:
Expand Down Expand Up @@ -270,7 +270,7 @@ frequencies after enabling [input_shaper], this section will not help with that.
Assuming that you have sliced the ringing model with suggested
parameters, complete the following steps for each of the axes X and Y:

1. Prepare for test: `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
1. Prepare for test: `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0`
2. Make sure Pressure Advance is disabled: `SET_PRESSURE_ADVANCE ADVANCE=0`
3. Execute: `SET_INPUT_SHAPER SHAPER_TYPE=ZV`
4. From the existing ringing test model with your chosen input shaper select
Expand Down Expand Up @@ -331,7 +331,7 @@ with suggested parameters, print the test model 3 times as
follows. First time, prior to printing, run

1. `RESTART`
2. `SET_VELOCITY_LIMIT ACCEL_TO_DECEL=7000`
2. `SET_VELOCITY_LIMIT MINIMUM_CRUISE_RATIO=0`
3. `SET_PRESSURE_ADVANCE ADVANCE=0`
4. `SET_INPUT_SHAPER SHAPER_TYPE=2HUMP_EI SHAPER_FREQ_X=60 SHAPER_FREQ_Y=60`
5. `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`
Expand Down
2 changes: 1 addition & 1 deletion docs/Status_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ The following information is available in the `toolhead` object
limit value (eg, `axis_minimum.x`, `axis_maximum.z`).
- For Delta printers the `cone_start_z` is the max z height at
maximum radius (`printer.toolhead.cone_start_z`).
- `max_velocity`, `max_accel`, `max_accel_to_decel`,
- `max_velocity`, `max_accel`, `minimum_cruise_ratio`,
`square_corner_velocity`: The current printing limits that are in
effect. This may differ from the config file settings if a
`SET_VELOCITY_LIMIT` (or `M204`) command alters them at run-time.
Expand Down
10 changes: 5 additions & 5 deletions klippy/extras/resonance_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ def run_test(self, axis, gcmd):
systime = self.printer.get_reactor().monotonic()
toolhead_info = toolhead.get_status(systime)
old_max_accel = toolhead_info['max_accel']
old_max_accel_to_decel = toolhead_info['max_accel_to_decel']
old_minimum_cruise_ratio = toolhead_info['minimum_cruise_ratio']
max_accel = self.freq_end * self.accel_per_hz
self.gcode.run_script_from_command(
"SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.3f" % (
max_accel, max_accel))
"SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=0"
% (max_accel,))
input_shaper = self.printer.lookup_object('input_shaper', None)
if input_shaper is not None and not gcmd.get_int('INPUT_SHAPING', 0):
input_shaper.disable_shaping()
Expand All @@ -108,8 +108,8 @@ def run_test(self, axis, gcmd):
gcmd.respond_info("Testing frequency %.0f Hz" % (freq,))
# Restore the original acceleration values
self.gcode.run_script_from_command(
"SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.3f" % (
old_max_accel, old_max_accel_to_decel))
"SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=%.3f"
% (old_max_accel, old_minimum_cruise_ratio))
# Restore input shaper if it was disabled for resonance testing
if input_shaper is not None:
input_shaper.enable_shaping()
Expand Down
47 changes: 29 additions & 18 deletions klippy/toolhead.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,19 @@ def __init__(self, config):
# Velocity and acceleration control
self.max_velocity = config.getfloat('max_velocity', above=0.)
self.max_accel = config.getfloat('max_accel', above=0.)
self.requested_accel_to_decel = config.getfloat(
'max_accel_to_decel', self.max_accel * 0.5, above=0.)
self.max_accel_to_decel = self.requested_accel_to_decel
self.min_cruise_ratio = config.getfloat('minimum_cruise_ratio', None,
below=1., minval=0.)
if self.min_cruise_ratio is None:
self.min_cruise_ratio = 0.5
req_accel_to_decel = config.getfloat('max_accel_to_decel', None,
above=0.)
if req_accel_to_decel is not None:
config.deprecate('max_accel_to_decel')
self.min_cruise_ratio = 1. - min(1., (req_accel_to_decel
/ self.max_accel))
self.square_corner_velocity = config.getfloat(
'square_corner_velocity', 5., minval=0.)
self.junction_deviation = 0.
self.junction_deviation = self.max_accel_to_decel = 0.
self._calc_junction_deviation()
# Input stall detection
self.check_stall_time = 0.
Expand Down Expand Up @@ -561,7 +568,7 @@ def get_status(self, eventtime):
'position': self.Coord(*self.commanded_pos),
'max_velocity': self.max_velocity,
'max_accel': self.max_accel,
'max_accel_to_decel': self.requested_accel_to_decel,
'minimum_cruise_ratio': self.min_cruise_ratio,
'square_corner_velocity': self.square_corner_velocity})
return res
def _handle_shutdown(self):
Expand Down Expand Up @@ -600,8 +607,7 @@ def get_max_velocity(self):
def _calc_junction_deviation(self):
scv2 = self.square_corner_velocity**2
self.junction_deviation = scv2 * (math.sqrt(2.) - 1.) / self.max_accel
self.max_accel_to_decel = min(self.requested_accel_to_decel,
self.max_accel)
self.max_accel_to_decel = self.max_accel * (1. - self.min_cruise_ratio)
def cmd_G4(self, gcmd):
# Dwell
delay = gcmd.get_float('P', 0., minval=0.) / 1000.
Expand All @@ -615,29 +621,34 @@ def cmd_SET_VELOCITY_LIMIT(self, gcmd):
max_accel = gcmd.get_float('ACCEL', None, above=0.)
square_corner_velocity = gcmd.get_float(
'SQUARE_CORNER_VELOCITY', None, minval=0.)
requested_accel_to_decel = gcmd.get_float(
'ACCEL_TO_DECEL', None, above=0.)
min_cruise_ratio = gcmd.get_float(
'MINIMUM_CRUISE_RATIO', None, minval=0., below=1.)
if min_cruise_ratio is None:
req_accel_to_decel = gcmd.get_float('ACCEL_TO_DECEL',
None, above=0.)
if req_accel_to_decel is not None and max_accel is not None:
min_cruise_ratio = 1. - min(1., req_accel_to_decel / max_accel)
elif req_accel_to_decel is not None and max_accel is None:
min_cruise_ratio = 1. - min(1., (req_accel_to_decel
/ self.max_accel))
if max_velocity is not None:
self.max_velocity = max_velocity
if max_accel is not None:
self.max_accel = max_accel
if square_corner_velocity is not None:
self.square_corner_velocity = square_corner_velocity
if requested_accel_to_decel is not None:
self.requested_accel_to_decel = requested_accel_to_decel
if min_cruise_ratio is not None:
self.min_cruise_ratio = min_cruise_ratio
self._calc_junction_deviation()
msg = ("max_velocity: %.6f\n"
"max_accel: %.6f\n"
"max_accel_to_decel: %.6f\n"
"minimum_cruise_ratio: %.6f\n"
"square_corner_velocity: %.6f" % (
self.max_velocity, self.max_accel,
self.requested_accel_to_decel,
self.square_corner_velocity))
self.min_cruise_ratio, self.square_corner_velocity))
self.printer.set_rollover_info("toolhead", "toolhead: %s" % (msg,))
if (max_velocity is None and
max_accel is None and
square_corner_velocity is None and
requested_accel_to_decel is None):
if (max_velocity is None and max_accel is None
and square_corner_velocity is None and min_cruise_ratio is None):
gcmd.respond_info(msg, log=False)
def cmd_M204(self, gcmd):
# Use S for accel
Expand Down

0 comments on commit 0105aa3

Please sign in to comment.