Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Junction velocity limits: sharp corners and smooth traversal of circles are mutually exclusive #4228

Closed
richfelker opened this issue Apr 28, 2021 · 38 comments
Labels

Comments

@richfelker
Copy link

After encountering rapidly oscillations in speed along what should be smooth curves at high max speed, I began investigating the math behind junction velocity limits, and found what I believe are two problems. One is related to the centripetal velocity limit, but this issue report will focus on the square corner velocity (junction deviation algorithm) limit, which is currently the limiting factor and source of the oscillations I saw with reasonable values for square_corner_velocity (abbreviated scv from here on).

Under the JD algorithm, the maximal allowed velocity for a junction varies with angle as sin(theta/2) / (1-sin(theta/2)), where theta is the interior angle (180° being no turn at all). Plugging in values of 90° and 170° for theta, one can compute that the allowed junction velocity for 36-gon approximation of a circle is only 10× the value for a 90° turn (i.e. 10×scv). If one follows the Input Shaper guidelines for using a low scv like 5, that puts an extremely low hard limit of 50 mm/s on the velocity the toolhead can traverse a circle - much lower than the centripetal velocity once you're beyond a few millimeters of radius. Moreover, between junctions the toolhead will accelerate and decelerate, creating oscillating extruder pressure and, with pressure advance, rapid E-axis swings back and forth. If the pressure advance smooth time window is sufficient to smooth out these swings, then extrusion thickness will just oscillate instead as the toolhead velocity oscillates while extruder velocity remains constant.

To get smooth motion around a circle at even a moderate print speed like 150 mm/s one would need scv>=15, which produces considerable ringing with input shaper disabled, or severely rounded-off corners with input shaper enabled.

I have done a good deal of experimenting with hacks to solve the problem, and the right approach seems to be smoothly transitioning away from using the junction deviation/scv limit as the junction angle gets large enough to be participating in a curve. At such angles the centripetal velocity limit should suffice to keep the motion reasonable.

The current trick I'm using is applying a power to the (1-sin(theta/2)) in the denominator of the computed virtual radius R. A power of 1.5 (scaling up by a factor of 1/sqrt(1-sin(theta/2))) seems to work well but might be execesive. It increases the radius nearly 4x at an external angle of 45°, and roughly 16x at an external angle of 10° (allowing a 36-gon 'circle' to be traversed at up to 800 mm/s with scv=5). This is of course also throwing off 90° junction velocity by a bit (making it about 20% higher) which could be fixed with renormalization or just interpolating to a different sort of limit.

@richfelker
Copy link
Author

Here's a video showing stutter at 90 mm/s, 5000 mm/s², scv=5:

https://vimeo.com/542801875

The audio is the most telling - those are rapid pressure advance moves. Here is the file: klipper_scv_test.gcode.txt It lacks any G28 command so home before printing.

Since all junctions in the whole print have the same angle, you can see the effect of my solution just by increasing scv by 16x (or just 2-3x). Lowering the speed factor to 50% eliminates the stutter as well. Visually (I'll add a pic soon), the 50% speed and high-scv versions (without the stutter) look more similar while the stuttering version has pronounced extrusion difference at the junctions.

@richfelker
Copy link
Author

Pics: left is with stutter, right without (scv boosted):

IMG_20210428_144701

And overhead, this time with pressure advanced turned off, to show the resulting oscillation in extrusion width:

IMG_20210428_150620

@richfelker
Copy link
Author

Also following up with some notes from IRC where @KevinOConnor raised some good points (which I hope I've paraphrased ok):

  1. There should definitely not be any discrete cutoff angle where SCV is no longer applied. I'm in complete agreement here; if something is done it should be a smooth transition so that there are not artifacts at the cutoff point.
  2. With axes being independent, making even a slight turn can be a big change in velocity for the other axis, that might be undesirable.

In particular, I computed, a 10° turn at 200 mm/s is only a 3 mm/s instantaneous slowdown along the original direction of motion, but it's a 35 mm/s start in the perpendicular direction.

Part of the problem here is that the scv limit may be reflecting either some hard limit of the machine (when users set it very high, like 25-100, for speedboats and such) or a threshold at which print quality problems become unacceptable (when it's set according to the input shaper recommendations, for example). In the latter case it's almost certainly okay to violate it for the sake of improving quality of slight turns (and print time). In the former, it's less clear, but I think it would take a really large print with really high acceleration limits in order for the centripetal velocity limit not to come into play here and sufficiently limit the cornering speed.

If it does end up being unacceptable to phase out svc limits at slight turns, the other potential way to address this issue is to suppress the acceleration. I think this can be done by deducting the arc length (or some approximation of it) from the junction deviation algorithm's "virtual arc" from the length of the move, and limiting the max cruising v² for the move to the max starting v² plus the v² obtainable from accelerating the remaining length of the move. This is roughly the fix I already want to make for the corresponding stuttering issue that the centripetal velocity limit can cause, and there's something to be said for using the same fix for both.

@KevinOConnor
Copy link
Collaborator

Thanks. Can you also provide the klipper log files from your test prints? (I'd like to know the software versions and configuration.)

-Kevin

@dmbutyugin
Copy link
Collaborator

Plugging in values of 90° and 170° for theta, one can compute that the allowed junction velocity for 36-gon approximation of a circle is only 10× the value for a 90° turn (i.e. 10×scv).

I am not sure how you came to that conclusion. According to the formulas you quote (which, I believe, are correct),
sin(170/2) / (1-sin(170/2)) ~= 262
and
sin(90/2) / (1-sin(90/2)) ~= 2.4
so it is 100x larger. That should be sufficient for all practical purposes. And FWIW, 36-gon isn't that smooth approximation of a circle.

@richfelker
Copy link
Author

richfelker commented Apr 30, 2021

@dmbutyugin, those values are in units of velocity squared. Once you take the square root, you get my factor of just over 10.

As for whether a 36-gon is a decent approximation of a circle, I'm not sure, but most real-world models people try to print use fewer segments. The OpenSCAD default $fa is 12° (at most a 30-gon, fewer according to $fs at small sizes) and diameter somewhere around 10 mm or below it becomes pointless to use more sides with FDM. (Note: at 3000 mm/s² the centripetal velocity limit for diameter 10 mm is 122 mm/s, far over the scv=5 limit of 10x5=50.)

@dmbutyugin
Copy link
Collaborator

@dmbutyugin, those values are in units of velocity squared. Once you take the square root, you get my factor of just over 10.

Right, my bad. Well, that formula is based on the concept of virtual acceleration. So, the toolhead supposedly will experience the same acceleration turning 10 degrees at 50 mm/s as turning 90 degrees at 5 mm/s. I'm not sure if it can be compared to centripetal acceleration directly, as centripetal acceleration is continuous, while this is just 10 points.

But in principle, that's just a model. Maybe it is a good opportunity to improve Klipper motion planning and choose some different model instead.

@richfelker
Copy link
Author

I'm not sure if it can be compared to centripetal acceleration directly, as centripetal acceleration is continuous, while this is just 10 points.

Right. My point in making the comparison was to highlight that, interpreting the 36-gon of diameter 10 as a circle, you'd want to traverse it at 122 mm/s given a 3000 mm/s² acceleration setting, but scv=5 is limiting you to much lower speed (in addition to possiblt making the speed oscillate rapidly, depending on your acceleration settings).

But in principle, that's just a model. Maybe it is a good opportunity to improve Klipper motion planning and choose some different model instead.

I think the current model is largely successful, but just has conflicting undesirable behavior in opposite extremes when you take it to moderately to very high speeds and accelerations. Maybe some sort of curve fitting model would do better here, but it's a very big change for the sake of improving something that I think can be improved comparably with much less work. Moreover, I'm not 100% sure, but I strongly suspect the result of doing what I'm doing, then applying input shaper, produces very similar step results to what you'd get with fancy curve fitting.

@richfelker
Copy link
Author

@KevinOConnor OK, I'll run some logs again when I have printer idle and a chance to revert patch and test.

@dmbutyugin
Copy link
Collaborator

Well, there are 2 parts of that junction deviation model. One part is the principle that the velocity of traversing the angle theta depends only on the value of theta. The other part is the exact formula for v = v(theta). The currently used formula offers some advantages over more simple axis jerk model, but has some hiccups of its own.

For example, let's assume a cartesian printer, that prints 90 degrees angle by first going in the direction (1, 1), and then (1, -1) after the angle. Let's assume that the velocity for both moves was set to 5 mm/sec (==scv). Then the X axis will move at the same constant speed of 5/sqrt(2), and Y axis will first move at the constant speed 5/sqrt(2) in the positive direction, then abruptly change its speed to -5/sqrt(2). This is how the junction deviation model will pass this corner.

Now let's assume a different scenario - the toolhead moves in Y direction, and there is a 180 degrees turn on Y axis. Let's assume that the speed for both moves was set to 5/sqrt(2). In this case, if we use the junction deviation model, X axis does not move at all. Y axis, on the other hand, starts at 5/sqrt(2) speed, decelerates to 0, and then accelerates to -5/sqrt(2). Note that for Y axis, the situation is not different than the previous case - physically, the printer could go at 5/sqrt(2) speed, and then abruptly change it to -5/sqrt(2), as what happens in the previous case. But the junction deviation model does not allow that and requires the printer to come to a complete stop at the angle, which slows down the print.

My point is, this model has its own hiccups. Generally, the function v(theta) can be somewhat different. v(0) = 0 is not, in principle, a strict requirement, and v(90) = 5 value was chosen somewhat arbitrarily.

One simple alternative that I could think of is a momentum model: we may want to fix how much momentum a printer can instantaneously take from a toolhead to change its direction. For a turn theta (angle between segments) the momentum change is 2 * m * v * cos(theta/2). If we set scv == 5mm/s, we could use that formula to determine an appropriate speed for other angles. It is v = scv * cos(45) / cos(theta/2)

Below is the chart that compares the two models:

junction-deviation-momentum

Incidentally, for theta=170 the junction deviation model gives v = 10.4 * scv, and the momentum model gives v = 8.1 * scv.

I find it very interesting that the two models that are based on very different physical principles give very close predictions. Unfortunately, that increases the confidence that the current model is working correctly: contrary to your desire, it is indeed more "difficult" for the printer to turn 10 degrees (170 degrees angle between path segments) at 100 mm/sec than to turn 90 degrees at 5 mm/sec, and the junction deviation model does not permit that.

@KevinOConnor What is your take on this?

As for whether a 36-gon is a decent approximation of a circle, I'm not sure, but most real-world models people try to print use fewer segments. The OpenSCAD default $fa is 12° (at most a 30-gon, fewer according to $fs at small sizes) and diameter somewhere around 10 mm or below it becomes pointless to use more sides with FDM. (Note: at 3000 mm/s² the centripetal velocity limit for diameter 10 mm is 122 mm/s, far over the scv=5 limit of 10x5=50.)

I'm not sure that the default OpenSCAD value is a good argument here. It is probably chosen for performance rather than for the quality of the resulting part. The analysis above suggests that neither 12°, nor 10° is sufficient for fast and quality printing.

So, I think the only good way to alleviate your issue is to choose some different model. Still, I don't think that 'patching' an existing formula is the right way to go - in that case, it is no longer based on any physical model or assumptions. Instead, one may say that the junction deviation model does not really reflect the physical constraints of the printer. At least, the current scv was chosen somewhat arbitrarily - there could be some printers with very heavy print bed or gantry, for which it is too much, and there are many printers that could take much more than that. So, maybe we shouldn't bother trying to limit the virtual acceleration during the cornering or the toolhead momentum change, but instead try to limit something else. Just as an example, one may choose v = v(theta) such that the input shaper smoothing is the same for all theta. Could be something completely different though.

@richfelker
Copy link
Author

Contrary to your desire, it is indeed more "difficult" for the printer to turn 10 degrees (170 degrees angle between path segments) at 100 mm/sec than to turn 90 degrees at 5 mm/sec, and the junction deviation model does not permit that.

I don't dispute that, but I claim that neither is "difficult" at all. If scv were 30 or so, we might be talking about something that's difficult, but at scv=5 we're well within the bounds of what's not difficult, and purely aiming to avoid the effects of vibrations (or, perhaps more importantly, the effects of compensation for them).

Still, I don't think that 'patching' an existing formula is the right way to go - in that case, it is no longer based on any physical model or assumptions.

I agree, but the only "patching" I've proposed is simply not using it at shallow turns angles, but with a window function to phase it out smoothly rather than having a discrete, discontinous cutoff, which would have unstable behavior at the cutoff point. My claim is that, for these angles, the centripetal velocity limit model suffices to keep the junction speed reasonable.

At least, the current scv was chosen somewhat arbitrarily - there could be some printers with very heavy print bed or gantry, for which it is too much, and there are many printers that could take much more than that.

Yes, the JD model does not reflect the physical limits of a machine well at all. The classic jerk model of Marlin was better for that, except that it didn't accumulate cost of discontinuous changes in velocity over a short time, thereby letting a large number of tiny moves grossly exceed the intended limits. If the goal were modeling the physical limits of the machine, one could start over from there and just try to do it right. But that has a lot of undesirable properties too. It's hard to work with in a machine-independent model for the first stage of kinematics, like Klipper does, and it makes acceleration behavior dependent on orientation (and for a delta, position) in space, which can lead to orientation-specific artifacts.

JD is desirable not as an attempt to directly model the machine's limits, but as a way of producing reasonable behavior, and works very well for that as long as your JD limit is sufficiently far below the machine's physical limits. But at such low values it does have problems dealing with curves. That's what I want to solve.

@KevinOConnor
Copy link
Collaborator

Some random thoughts - in no particular order:

  1. For me, the main features of the junction deviation algorithm are:
    1. It's output doesn't depend on the low-level kinematics. This was important to me, as in my experience, the main limiting factor to quality prints is the interface between nozzle and print. In general, the steppers have oodles of torque. Getting plastic in the rice place and getting it to adhere is the challenge. So, I felt the "jerk" model was not a good choice, and the JD algorithm is more appropriate.
    2. It is a widely deployed and battle tested algorithm.
    3. It results in slower speeds with acute angles, much higher speeds when going in nearly the same direction, and the change of cornering velocity limit with respect to angle is smooth.
    4. It is efficient to calculate.
  2. Klipper has a few minor customizations to the JD algo, but they're pretty basic: we configure via square_corner_velocity instead of junction_deviation, there is an additional check for really tiny segments, and there is also the accel_to_decel limit.
  3. Any time the nozzle is extruding it is imparting force on the print. If nothing else, the mass of the filament itself will be travelling at the speed of the toolhead and will impart a force on the print when it makes contact. Thus, there must be some limit to cornering speeds even if one had "perfect steppers".
  4. I would recommend against using a large 36-gon for testing "curves". I'd say that if a side is longer than ~1mm then we're no longer dealing with a "curve" and instead are dealing with a large polygon. When printing a large polygon, I don't see anyway to avoid accelerating and decelerating - I don't think the challenge there is with the lookahead algorithm - I think the challenge is with extruder hardware that can rapidly and accurately change flow rate. (FWIW, I always add $fs=0.5 to the top of my openscad files.)
  5. The default of square_corner_velocity=5 is basically an arbitrary choice. That said, I feel pretty confident that an "ideal" value (if there is such a thing) is not an order of magnitude from that (eg, it's not less than 1mm/s nor greater than 25mm/s).
  6. In my investigations, I concluded that a cartesian printer could result in an instantaneous velocity change of up to 8*square_corner_velocity on one of its motors. This extreme could occur at a very high move speed with an angle near 180 degrees.
  7. I agree that for curves (I'm thinking many small line segments each less than 1mm) the current code may be producing pointless acceleration and deceleration. The accel_to_decel code was intended to limit the magnitude of that acceleration, but it doesn't avoid acceleration. It's possible input_shaper and pressure_advance may magnify the remaining acceleration to no real gain.

-Kevin

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented May 1, 2021

Some more random thoughts..

FWIW, I think of square_corner_velocity as a mechanism for managing extruder flow rate. If the printer decelerates to zero on each corner then we get terrible results because the extruder can't completely stop the flow of plastic. The pressure_advance system can help with managing flow, but PA works best when there is still some flow - the pressure model doesn't scale linearly all the way to zero pressure. At the other extreme, if the printer goes too fast through corners then the filament may not adhere well to previous layers and at some point the physical stepper may not have sufficient torque.

So, I know some people try to tune square_corner_velocity for print times, but in my experience that doesn't really do much. If needed, I'd look to tune square_corner_velocity based on extruder performance.

FWIW, long ago when I used Marlin, I had problems with first layer adhesion that I now attribute (in part) to its "jerk" algorithm. No matter how slow I went, it seemed to move through sharp corners too fast - leading to those corners not sticking to glass.

Interestingly, the junction deviation algorithm was originally designed for CNC machines. So, although it's useful for managing flow rate on 3d printers, that wasn't its original goal. As I understand it, on a CNC mill, a quality result depends on having a consistent cutting rate. If the cutting rate changes rapidly it alters the finish of the final product (likely due to changes in heat in the part and cutting tool).

-Kevin

@richfelker
Copy link
Author

I would recommend against using a large 36-gon for testing "curves". I'd say that if a side is longer than ~1mm then we're no longer dealing with a "curve" and instead are dealing with a large polygon.

While diameter 40 was more convenient for showing it, I'm pretty sure we get the same problem with diameter ~11 (circumference 36, i.e. each segment 1 mm). At that size it really does not make sense to use more than 36 segments. I think I could also make it happen with a 72-gon of larger size, but beyond that it probably gets hard - the virtual junction radius grows pretty quick I think.

FWIW, I always add $fs=0.5 to the top of my openscad files.

That doesn't have an effert by itself because of the way the logic works. You also need $fa sufficiently high. OpenSCAD will never make segments longer than $fs and will never make more than 360/$fa segments.

The default of square_corner_velocity=5 is basically an arbitrary choice. That said, I feel pretty confident that an "ideal" value (if there is such a thing) is not an order of magnitude from that (eg, it's not less than 1mm/s nor greater than 25mm/s).

At least with default damping ratios (and I don't know how to tune them), input shaper makes it impossible to go over scv=5 or so. Much beyond that, squares turn into something that doesn't look at all like a square.

I agree that for curves (I'm thinking many small line segments each less than 1mm) the current code may be producing pointless acceleration and deceleration. The accel_to_decel code was intended to limit the magnitude of that acceleration, but it doesn't avoid acceleration

I don't use accel_to_decel because it produces significantly slower prints for certain things I care about (gears, threads, etc.) and the vibration it mitigates is non-problematic and better mitigated by input shaper. But I don't think it fixes this problem anyway, as you say.

Would you like to see the solution I have in mind for avoiding the acceleration? I've written and tested a version of this already for the corresponding issue with centripetal velocity limit, so it'll take a little more work to adapt it to scv and confirm that it works there too, but I think it will. I don't like this approach as much because it slows down prints considerably vs my preferred one, but I'd prefer it to having the issue go entirely unfixed upstream (and I can still keep my own fix as a local hack if I like). The reason I'm trying to get this fixed upstream is largely for others' anyway; I started really looking at it to the level needed to make a good bug report and discussion after seeing what looked like the same issue in a number of speedboatraces.

@dmbutyugin
Copy link
Collaborator

@richfelker
FWIW, I also tried to make a formula v=v(theta) such that the projected smoothing of the ZV input shaper - the simplest one - is constant for all angles. Incidentally, the formula is the same that makes the toolhead momentum change constant - it is v = scv * cos(45) / cos(theta/2). That makes me arrive to the following conclusion.

There is no reason to raise the junction velocity for theta > 90 degrees than it currently is - if anything, it is actually even a bit too high for input shaper smoothing. The firmware currently attempts to print the object as requested, and from your pics it seems that it succeeds in doing so (it indeed prints a polygon). And when you raise the junction velocity by 2-3x (even if only for larger theta angles), you actually get a smooth circle, but this is not because now it "prints well", but because you actually get too much smoothing from the input shaper, which smooths out the corners of the polygon. But the real problem is that you are making one object in stl, but you want the firmware to second guess and print something different. I'm not sure if that's the right approach in the general case.

FWIW, the problem in your case is exacerbated by the remote direct drive extruder, I suspect. From my personal experience, large magnitude accelerations and decelerations with the enabled Pressure Advance put a lot of stress on such extruders, and they cope with it pretty poorly. So the clicking noise one can hear is likely coming from the extruder. Unfortunately, it seems that this is their limitation due to very high gear reduction ratio.

@KevinOConnor

FWIW, long ago when I used Marlin, I had problems with first layer adhesion that I now attribute (in part) to its "jerk" algorithm. No matter how slow I went, it seemed to move through sharp corners too fast - leading to those corners not sticking to glass.

Thanks, this is an interesting perspective. The JD model makes the toolhead to decelerate up to 0 speed for sharp angles (well, to 0 at 180 degrees turn, and to small non-zero values for other sharp corners). From the point of view of managing the extruder flow, do you think it would be beneficial to keep some small'ish non-zero velocity of the toolhead even for very sharp angles?

It's possible input_shaper and pressure_advance may magnify the remaining acceleration to no real gain.

Actually, it is not possible for the input_shaper to magnify accelerations. As long as all its coefficients are positive, that is (and Klipper supports only such input shapers right now). So, the commanded stepper acceleration/deceleration after input shaper is always not greater than what it is without input shaping. However, if max_accel_to_decel is set to the same value as max_accel, then indeed there will be 'pointless' accelerations and decelerations while printing. And if the Pressure Advance is enabled, this will put more stress onto extruder. FWIW, even though I also print with higher max_accel_to_decel value than the default, I tend to set it to 2/3 or 3/4 of max_accel.

@richfelker
Copy link
Author

The firmware currently attempts to print the object as requested, and from your pics it seems that it succeeds in doing so (it indeed prints a polygon).

The "polygon" you're seeing better in the stuttering print is not from straighter sides. It's inconsistent extrusion. My pressure advance constant should probably be a little higher than 0.05, but that's enough to mitigate the worst effects of inconsistent extrusion rate, and going up higher is a tradeoff in other areas. And I don't think higher could really solve the problem here - Klipper's PA with smooth_time is such that it can't handle really rapid pressure adjustments, and going to higher PA generally needs either longer smooth_time or lower acceleration.

But the real problem is that you are making one object in stl, but you want the firmware to second guess and print something different.

That's not the case. I'm perfectly fine with it coming out either way (corners getting smoothed over or not). I'm just not fine with the extrusion stuttering from unnecessary oscillations in speed. I could try it again with input shaper disabled to see how it looks without the smoothing, if that would be interesting to anyone.

FWIW, the problem in your case is exacerbated by the remote direct drive extruder, I suspect. From my personal experience, large magnitude accelerations and decelerations with the enabled Pressure Advance put a lot of stress on such extruders, and they cope with it pretty poorly. So the clicking noise one can hear is likely coming from the extruder. Unfortunately, it seems that this is their limitation due to very high gear reduction ratio.

The clicking noise is from the 1:4 step-up gearbox on top of the motor to compensate for the high (40:1) reduction at the extruder end of the flex cable. It has some tiny amount of backlash, which is irrelevant to print quality thanks to the 40:1 reduction after it, but still relevant to noise level. Without this gearing, the motor would just be stalling trying to do this kind of rapid adjustment to PA offset, requiring a much longer smooth_time and thereby getting the same result as the pic with PA disabled. Note that all this is far worse on bowden extruders, where I got the same kind of pulsing with with 10x the offset. Somewhere I still have videos of my Ender 3's original bowden extruder rapidly spinning back and forth with PA on high acceleration. So it's not just an issue specific to my printer's unique setup.

@dmbutyugin
Copy link
Collaborator

The firmware currently attempts to print the object as requested, and from your pics it seems that it succeeds in doing so (it indeed prints a polygon).

The "polygon" you're seeing better in the stuttering print is not from straighter sides. It's inconsistent extrusion. My pressure advance constant should probably be a little higher than 0.05, but that's enough to mitigate the worst effects of inconsistent extrusion rate, and going up higher is a tradeoff in other areas. And I don't think higher could really solve the problem here - Klipper's PA with smooth_time is such that it can't handle really rapid pressure adjustments, and going to higher PA generally needs either longer smooth_time or lower acceleration.

I'd think lower acceleration. From my very limited understanding of the processes happening in the hotend, smooth_time should depend on the inertia of the processes in the hotend for the most part. If you increase it, it may happen that you'll start getting inconsistent extrusion during acceleration and deceleration, because PA will start to kick in too early. It is possible to tune this parameter to better match the hotend, however it is rarely needed.

Klipper's PA with smooth_time is such that it can't handle really rapid pressure adjustments

From my experience, it is not entirely accurate. A lot depends on the magnitude of said adjustments. And smooth_time isn't the problem here. If a toolhead accelerates from 50 mm/sec to 100 mm/sec at 3000 mm/sec^2, it only takes 16 msec to do that. Normally, the extruder needs to push all the extra filament in that time frame. If it is a direct drive extruder with a low PA value, it only needs to push a little extra. If it is a bowden setup with a high PA value - it may simply be physically impossible to push those extra few mm of the filament through the tube into the hotend in those 16 msec. And if it's an RDD extruder with a high gearing ratio - even though the amount of extra filament is small, the exruder stepper still has to make a lot of steps to achieve that. And it may still fail to do that because of non-zero inertia of the stepper rotor and the cable.

But the real problem is that you are making one object in stl, but you want the firmware to second guess and print something different.

That's not the case. I'm perfectly fine with it coming out either way (corners getting smoothed over or not). I'm just not fine with the extrusion stuttering from unnecessary oscillations in speed.

I see. You could still try using the default accel_to_decel value and see how that works in this case.

But generally, I mean, Klipper tries to print an object exactly as it is. And it seems that it is simply not possible to print that polygon object precisely at high speed without any decelerations due to various constraints.

I could try it again with input shaper disabled to see how it looks without the smoothing, if that would be interesting to anyone.

You could also give that a try. At the very least, it could be a practical demonstration of input shaper smoothing at high velocities (or not, depending on the results of the test).

The clicking noise is from the 1:4 step-up gearbox on top of the motor to compensate for the high (40:1) reduction at the extruder end of the flex cable. It has some tiny amount of backlash, which is irrelevant to print quality thanks to the 40:1 reduction after it, but still relevant to noise level. Without this gearing, the motor would just be stalling trying to do this kind of rapid adjustment to PA offset, requiring a much longer smooth_time and thereby getting the same result as the pic with PA disabled.

Note that all this is far worse on bowden extruders, where I got the same kind of pulsing with with 10x the offset. Somewhere I still have videos of my Ender 3's original bowden extruder rapidly spinning back and forth with PA on high acceleration. So it's not just an issue specific to my printer's unique setup.

Yes, of course, I did not mean it like that. Bowden setups are even more susceptible. But the point is: bowden setups may be not practical for printing at high accelerations with PA enabled. So either acceleration needs to be reduced, PA disabled (which impacts the dimensional accuracy of the parts and consistency of extrusion), or the extruder made such as to be able to handle the excessive load. There is no easy all-round solution to print very fast and accurately with bowden extruders. The same applies to RDD extruders as well, for the most part.

@richfelker
Copy link
Author

But generally, I mean, Klipper tries to print an object exactly as it is. And it seems that it is simply not possible to print that polygon object precisely at high speed without any decelerations due to various constraints.

If that's the case then it should just inhibit the acceleration and stay at the lower speed between junctions. However I have not seen any indication that it prints the polygon "more accurately" at lower speed. The visible sides appear only because of inconsistent extrusion. If I just lower the speed significantly to make the stutter go away, it looks just as circular as the one with high-speed junctions.

@dmbutyugin
Copy link
Collaborator

dmbutyugin commented May 2, 2021

The visible sides appear only because of inconsistent extrusion. If I just lower the speed significantly to make the stutter go away, it looks just as circular as the one with high-speed junctions.

I am sorry, but I will have to disagree with you here for the general statement. I tried to print your gcode on my Ender3 Pro with a direct drive extruder. I printed at accel=3000, accel_to_decel=3000. The bottom half was printed at 40% of the feed rate (so 36 mm/sec I assume?). The upper half was printed at 100% of the feed rate (90 mm/sec it appears). As I have 0.5 mm nozzle I bumped the extrusion multipler to 120% soon after the start of the print. Here's what I've got:
PXL_20210502_110345011
The bottom half has very distinct visible sides from the polygon. The upper half has them too, but the edges are a bit smoothed out, and they are, shifted a bit, maybe? The latter I attribute to not very well tuned Pressure Advance for 0.5 mm nozzle and this particular PLA filament. To confirm this, I tried to make a picture of it when the light passes through it:
PXL_20210502_120958804
It is harder to catch it on the camera, but you can probably tell that the bottom half has mostly consistent thickness of the extrusion, but the upper one has little inconsistencies in the extrusion width on the sides and near the edges. So, if I wanted to get it print very well at high velocity, I should really tune PA instead of using some default PA value for PLA for 0.4 mm nozzle that I've got.

This makes me thinking that if you observe a smooth circle when printed at lower speed, perhaps this means that you already have a bit too much smoothing from the input shaper? I would suggest to tune the maximum acceleration based on your particular printer. Perhaps 3000 mm/sec^2 is too much for the lowest resonance frequency that you have on your Ender3? You should be getting a clear polygon in this case, at least at lower speeds. The low polygonality of the model is very pronounced when you print it, I can tell you that much.

As for whether a 36-gon is a decent approximation of a circle, I'm not sure, but most real-world models people try to print use fewer segments.

FWIW, this is sad in my opinion - I've seen a good deal of otherwise great models that have been exported with too poor refinement, and that makes their aesthetic look suffer quite a bit.

The visible sides appear only because of inconsistent extrusion.

Maybe you should try to dial your PA value for how it should be more precisely.

The clicking noise is from the 1:4 step-up gearbox on top of the motor to compensate for the high (40:1) reduction at the extruder end of the flex cable. It has some tiny amount of backlash, which is irrelevant to print quality thanks to the 40:1 reduction after it, but still relevant to noise level.

Since I do not know what kind of gearbox that is and which part of it has the backlash exactly, I cannot say anything definitive here. However, I would not just brush away the possibility that the backlash could impact the consistency of extrusion. Depending on which part of the gearing has the backlash, you may get the backlash at effectively 10:1 reduction ratio. Also note that RDD extruders have the high reduction ratio for a reason. That reason is to reduce the torsional forces on the cable. The typical reduction rates AFAIK are 40:1 or 30:1 (there was one attempt to make 20:1, but it wasn't quite successful, though for other reasons). Now if you effectively use 10:1 reduction rate, this might very well affect the quality of extrusion. *And even if you have the gearbox right at the stepper motor before the cable, the backlash could still affect the consistency of extrusion.

@KevinOConnor
Copy link
Collaborator

@richfelker

Would you like to see the solution I have in mind for avoiding the acceleration?

FWIW, this isn't something I, personally, plan to work on. As high-level feedback, if you have an improvement to the lookahead algorithm then I'd say the next steps are:

  1. Let others know about it and encourage them to run tests and report their findings. Ideally, we'd want at least 10 or so people getting results on a variety of real-world prints with common 3d printers using common printer settings
  2. Gather "before and after pictures" of those results that show a noticeable improvement in quality. For example, "with the new code my real world prints get noticeably improved print quality with similar print time", or "with the new code I can get the same print quality in a 9 hour print that used to take 10 hours".

A change from junction_deviation to a new algorithm would require widespread test results showing noticeable improvement. The JD algo is a heuristic and I don't doubt it can be improved, but for all its faults, it is a widely used and "battle tested" algorithm.

I don't use accel_to_decel

Okay, but it seems you have customized your printer configuration in an unusual way and your extruder hardware is very uncommon. My high-level feedback is that I'm not able to draw conclusions about general benefits from the results obtained on your hardware / settings.

Cheers,
-Kevin

@KevinOConnor
Copy link
Collaborator

@dmbutyugin

The JD model makes the toolhead to decelerate up to 0 speed for sharp angles (well, to 0 at 180 degrees turn, and to small non-zero values for other sharp corners). From the point of view of managing the extruder flow, do you think it would be beneficial to keep some small'ish non-zero velocity of the toolhead even for very sharp angles?

Not sure I understand your question. FWIW, the red line in your picture at:

junction-deviation-momentum

looks generally like what I'd expect for cornering speeds. That is, the cornering speed of a zero angle (next move goes directly backwards) should be zero, the cornering speed of a 180 angle (no direction change) should be "infinite", and the cornering speed of a 90 degree angle should be a small finite number (eg, ~5mm/s). And, the curve itself should be smooth.

Beyond those points though, it's hard for me to say what's ideal. The JD algorithm is also symmetric and is mostly "flat in the middle" - I'm not sure if that could be improved or not.

Actually, it is not possible for the input_shaper to magnify accelerations.

Yes. Sorry. I worded that poorly.

I meant that input_shaper may magnify a negative impact of acceleration changes - not that the acceleration itself would be greater. For example, if the look-ahead algo results in a speed change from 90mm/s to 95mm/s followed shortly after by a change from 95mm/s to 90mm/s, then input_shaper may turn those 2 speed changes into 6 or more speed changes. I don't know if that would negatively impact print quality, but if the speed change is pointless, then, well, it's pointless. If nothing else, it's more work for the rpi cpu to calculate more speed changes that aren't actually helping overall print time.

Cheers,
-Kevin

@richfelker
Copy link
Author

richfelker commented May 8, 2021

As for whether a 36-gon is a decent approximation of a circle, I'm not sure, but most real-world models people try to print use fewer segments.

FWIW, this is sad in my opinion - I've seen a good deal of otherwise great models that have been exported with too poor refinement, and that makes their aesthetic look suffer quite a bit.

It is sad, but what's even sadder is this: when I increased it to a 72-gon, Cura sliced it with a tiny move on the order of 0.001 mm on one axis and 0.01 mm on the other at 90° and 270° around the circle, seemingly due to numerical instability reasons with its representation of coordinates as integer microns. As a result, Klipper received the path as 2 rapid ~90° corners and thus slowed all the way down to scv and re-accelerated. So that's one reason folks aren't using better approximations of circles: slicers doing stupid things.

Note that Klipper is doing exactly the right thing with this gcode. Any attempt to paper over the tiny move would break printing of tiny detail, for example my microstep-accuracy test print.

@dmbutyugin
Copy link
Collaborator

As for whether a 36-gon is a decent approximation of a circle, I'm not sure, but most real-world models people try to print use fewer segments.

FWIW, this is sad in my opinion - I've seen a good deal of otherwise great models that have been exported with too poor refinement, and that makes their aesthetic look suffer quite a bit.

It is sad, but what's even sadder is this: when I increased it to a 72-gon, Cura sliced it with a tiny move on the order of 0.001 mm on one axis and 0.01 mm on the other at 90° and 270° around the circle, seemingly due to numerical instability reasons with its representation of coordinates as integer microns. As a result, Klipper received the path as 2 rapid ~90° corners and thus slowed all the way down to scv and re-accelerated. So that's one reason folks aren't using better approximations of circles: slicers doing stupid things.

What you describe sounds like a slicer bug. Such issues should be reported and fixed in the slicer itself, wouldn't you agree? I mean, there is really no good reason for any slicer to break on circles (BTW, I suspect that neither Cura nor any other slicer uses fixed-point micron representation internally - only exporting GCode in such format).

For example, there was indeed recently a bug in Cura, introduced in 4.7 version, which broke GCode generation for any smooth curves, including circles. This resulted in slow-downs on curves, in any firmware, and zits and blobs there as a result. Devs claimed to fix it in 4.8, but if I got it correctly, if you imported your print profiles from any previous version, you needed to update some parameters related to resolution, otherwise the fix wouldn't work. But newly created profiles would work fine. Note that I wasn't following that issue too closely, so this may be my [mis-]interpretation of the fix. After staying for a while on the version 4.6.2 I switched to SuperSlicer for reasons unrelated to this bug.

@richfelker
Copy link
Author

What you describe sounds like a slicer bug. Such issues should be reported and fixed in the slicer itself, wouldn't you agree?

Absolutely. I'm just suggesting a reason people publishing models might be using lower precision approximations - if they had bad experience with slicers botching higher-precision ones and don't want users to have to deal with that and blame them.

BTW, I suspect that neither Cura nor any other slicer uses fixed-point micron representation internally - only exporting GCode in such format

It really does. It uses integer coordinates, at least at the phase of generating paths. I actually started writing my comment claiming it had used %.3f to optimize serial transmission, but when I grepped the source for that I couldn't find it, and it turned out the code is using integer microns and emitting a decimal point before the last 3 digits after calling sprintf.

Anyway I'll try to make a good test case to report this one. Note that it only happens with an actual single-wall circle where Cura is trying to fit the extrusion between approximated inner and outer circles. There's no problem if you have a solid region with circular boundary.

None of this negates the Klipper issue I'm trying to find a solution to here; it's just stuff I hit while seeing how practical it is to mitigate with better approximations in the model file.

@dmbutyugin
Copy link
Collaborator

Anyway I'll try to make a good test case to report this one. Note that it only happens with an actual single-wall circle where Cura is trying to fit the extrusion between approximated inner and outer circles. There's no problem if you have a solid region with circular boundary.

Oh well, I suspect you'll need to reproduce it with their new Arachne engine then. There were some notable improvements for such cases there, but there could be some regressions too.

None of this negates the Klipper issue I'm trying to find a solution to here; it's just stuff I hit while seeing how practical it is to mitigate with better approximations in the model file.

Well, the original report is about printing a prism. As was shown, Klipper is perfectly capable of printing that prism so that it looks like a prism, without smoothing it out to the circle. I'm afraid that's the right behavior. Any improvements in the cornering velocity calculation should retain that. Though my rough estimations show that the current cornering velocity for small turns is perhaps already a bit too optimistic in Klipper, at least for input shaper smoothing. Therefore, I suspect there isn't that much room for further improvements.

@richfelker
Copy link
Author

Well, the original report is about printing a prism. As was shown, Klipper is perfectly capable of printing that prism so that it looks like a prism, without smoothing it out to the circle. I'm afraid that's the right behavior.

For the Nth time, I'm not complaining about that. The bug report is about the rapidly oscillating accel/decel. If cornering faster produces smoothing that makes the output inaccurate, then the solution is not to keep doing the oscillating accel/decel, but to maintain a consistent speed at the junction velocity for the segments between junctions.

Though my rough estimations show that the current cornering velocity for small turns is perhaps already a bit too optimistic in Klipper, at least for input shaper smoothing.

I think that's likely true, and likely a problem that needs to be addressed in input shaper, likely by making the strength of the filter tunable. Otherwise it can't be used without limiting print acceleration to the point that prints are really slow (a case that was already fine without input shaper).

@dmbutyugin
Copy link
Collaborator

For the Nth time, I'm not complaining about that. The bug report is about the rapidly oscillating accel/decel. If cornering faster produces smoothing that makes the output inaccurate, then the solution is not to keep doing the oscillating accel/decel, but to maintain a consistent speed at the junction velocity for the segments between junctions.

You mentioned that you increased max_accel_to_decel from its default value. That is the feature designed to limit that behavior. Did you try printing at the default value? I imagine it will still be not perfect, but may offer some improvements.

Though my rough estimations show that the current cornering velocity for small turns is perhaps already a bit too optimistic in Klipper, at least for input shaper smoothing.

I think that's likely true, and likely a problem that needs to be addressed in input shaper, likely by making the strength of the filter tunable. Otherwise it can't be used without limiting print acceleration to the point that prints are really slow (a case that was already fine without input shaper).

Unfortunately, that appears to be not possible. It seems that due to their design principles, the amount of smoothing you get depends on the lowest frequency the input shaper can compensate for. The exact amount varies a bit from shaper to shaper, but the general principle holds. So what really matters for input shaper smoothing is the lowest resonance frequency of the printer. If you still wish to reduce smoothing, even if it means more ringing - just set the input shaper frequency to a higher value. And if you are using the accelerometer, the auto-tuning scripts already have --max_smoothing parameter that you can tune to your liking.

So indeed an input shaper is not a silver bullet. For many printers, it does offer improvements in both speed and quality, but on some occasions you might be facing a tradeoff - printing fast and have ringing but no smoothing, print fast and have smoothing instead or print slower and have little ringing and smoothing. And if you are already printing fine and fast without the input shaper - I don't think there is a good reason to enable it.

@richfelker
Copy link
Author

You mentioned that you increased max_accel_to_decel from its default value. That is the feature designed to limit that behavior. Did you try printing at the default value? I imagine it will still be not perfect, but may offer some improvements.

I can try and report back. Based on the documentation, I expect what I'll find is that it significantly increases print time by slowing down nearly all moves. My max speed is typically 120-200 mm/s (and 500 mm/s for travel), and almost no moves are able to reach that speed even at full acceleration, so they'd be capped to the speed they could reach at the lower virtual acceleration. Paradoxically, it sounds like using max_accel_to_decel makes it so setting a higher nominal/max print speed actually slows down the print; if I lowered the max print speed to something attainable with full acceleration, no capping would occur. This just sounds broken to me.

The problem with the accel_to_decel model seems to be that "short zigzag" is defined in terms of time rather than distance. At very high speeds and accelerations, traversing a giant square around the whole bed looks like a "zigzag" to it.

If you still wish to reduce smoothing, even if it means more ringing - just set the input shaper frequency to a higher value.

That's not how it works. The frequency is not a strength parameter, it's the frequency of the vibrations you're trying to suppress. Setting it to a higher frequency where you don't have ringing present is just going to make it worse than useless, possibly smoothing meaningful detail at that frequency while not doing anything about the ringing. The problem is that there's no way to configure it to "reduce ringing by 50%" or something. It's a full band-[non]pass filter.

@dmbutyugin
Copy link
Collaborator

I can try and report back. Based on the documentation, I expect what I'll find is that it significantly increases print time by slowing down nearly all moves.

It will slow down the prints indeed. But you will not have useless accelerations and decelerations. It will work as expected. The exact slow down - it depends, maybe 10-15%? Depends on the model. I was thinking about suggesting to increase max_accel_to_decel in the documentation for the input shaper, but batch simulations show limited improvements in print times. I still want to spend a bit more time on it though.

My max speed is typically 120-200 mm/s (and 500 mm/s for travel), and almost no moves are able to reach that speed even at full acceleration, so they'd be capped to the speed they could reach at the lower virtual acceleration.

Depends on your max_accel, but sounds about right.

Paradoxically, it sounds like using max_accel_to_decel makes it so setting a higher nominal/max print speed actually slows down the print; if I lowered the max print speed to something attainable with full acceleration, no capping would occur.

No, that's not how it works. You will never get slower print by setting higher commanded velocity - but after a certain point the print time will no longer decrease, so at some point, further increasing the commanded velocity makes no difference.

If you still wish to reduce smoothing, even if it means more ringing - just set the input shaper frequency to a higher value.

That's not how it works. The frequency is not a strength parameter, it's the frequency of the vibrations you're trying to suppress.

Trust me, I do have some understanding of how it works :)

Take a look at the shaper calibration graphs that are generated by the script processing accelerometer output - it shows the remaining vibrations at different frequencies for each shaper (as a ratio from 0 to 1). Or you can play with scripts/graph_shaper.py script. It is not all-or-nothing.

Setting it to a higher frequency where you don't have ringing present is just going to make it worse than useless, possibly smoothing meaningful detail at that frequency while not doing anything about the ringing. The problem is that there's no way to configure it to "reduce ringing by 50%" or something. It's a full band-[non]pass filter.

That's really not how it works. The thing is, the toolhead pretty much almost never moves at the resonance frequency in the real prints - the resonance frequencies are usually too high for that. So in practice the smoothing has very different reason - because the input shaper computes the weighted average of the toolhead position over some period of time (and over fixed set of points). And that period depends on the frequency of the shaper - the lower the frequency - the bigger the period. That averaging makes the fine details and corners smooth at high printing speeds (and high accelerations, because that gives bigger average speeds). The solution is either printing slower (or at lower accelerations) or reduce the averaging period, so that the average deviates less from the original trajectory.

@richfelker
Copy link
Author

It will slow down the prints indeed. But you will not have useless accelerations and decelerations. It will work as expected

No. It will just reduce the magnitude of the useless acceleration/deceleration cycles; it won't eliminate them. They might appear to be eliminated if the max_accel_to_decel is so low that the possible delta_v2 over these small moves is negligible, but if it's that low, long moves that should accelerate up to some very high speed, but not all the way to the max speed of the move, will be capped to a much lower speed.

In short, it will fail to eliminate useless accelerations and decelerations, but will severely limit the most useful ones. Going on this from the documentation:

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.

If I have a 200 mm move requested at 500 mm/s, max_accel 2000 and max_accel_to_decel 1000, it would take 125 mm of motion to reach 500 mm/s at 1000 mm/s², and since that's more than half the move length, it wouldn't be achievable. Thus, instead of accelerating all the way to 500 mm/s, cruising for nearly 80 mm, and decelerating back down, in a total of 0.65 seconds, it would accelerate only up to a much lower speed and take 0.89 seconds.

No, that's not how it works. You will never get slower print by setting higher commanded velocity

OK, that seems correct, but not much of a condolance when it failed to get rid of oscillating acceleration on curves but made my travel nearly 50% slower....

The thing is, the toolhead pretty much almost never moves at the resonance frequency in the real prints - the resonance frequencies are usually too high for that.

I don't get what you're claiming. If the actual resonance frequency is something like 45 Hz (my value, measured with test model not with accelerometer analysis), the toolhead does indeed move at that frequency quite a bit - not in a sine wave at that frequency, but in motions that have a very strong component of that frequency in their fourier decomposition.

@dmbutyugin
Copy link
Collaborator

If I have a 200 mm move requested at 500 mm/s, max_accel 2000 and max_accel_to_decel 1000, it would take 125 mm of motion to reach 500 mm/s at 1000 mm/s², and since that's more than half the move length, it wouldn't be achievable. Thus, instead of accelerating all the way to 500 mm/s, cruising for nearly 80 mm, and decelerating back down, in a total of 0.65 seconds, it would accelerate only up to a much lower speed and take 0.89 seconds.

It will accelerate to "only" 447 mm/sec (sqrt(2 * 100 * 1000)), accelerating over 50 mm, cruising for 100 mm, and then decelerating, completing the move in 0.67 seconds total, if I did the math right.

The thing is, the toolhead pretty much almost never moves at the resonance frequency in the real prints - the resonance frequencies are usually too high for that.

I don't get what you're claiming. If the actual resonance frequency is something like 45 Hz (my value, measured with test model not with accelerometer analysis), the toolhead does indeed move at that frequency quite a bit - not in a sine wave at that frequency, but in motions that have a very strong component of that frequency in their fourier decomposition.

At 45 Hz and 2000 mm/sec^2 max accel the toolhead can oscillate by (and thus produce any meaningful details of the size of) ~0.03 mm. These are some very fine details. "in motions that have a very strong component of that frequency in their fourier decomposition" - I am not sure which function of the motion you are talking about (position, velocity, acceleration, etc.) and what integral effect it will have on the positional accuracy of the toolhead. Anyway, if you set mzv to, say, 60 Hz instead of 45 Hz in your configuration, you should not get more smoothing, but you will get much less ringing compensation, like only ~4x instead of ~20x.

@richfelker
Copy link
Author

It will accelerate to "only" 447 mm/sec (sqrt(2 * 100 * 1000)), accelerating over 50 mm, cruising for 100 mm, and then decelerating, completing the move in 0.67 seconds total, if I did the math right.

Indeed, I messed up the math, but I was trying to make an example where the effect was clearly unwanted. Unless there's something I'm missing where the scale between the two accelerations limits the badness, I think you can just scale speeds, accelerations, or distances to make a much worse example, no? I guess the ratio of max speed is bounded by sqrt(max_accel_to_decel/max_accel), so 1/sqrt(2) with the default ratio. And then if the distance and acceleration are such that more than 41% of the move is at max speed at full acceleration, the full speed can still be attained at the reduced virtual acceleration, and no slowdown occurs. This seems to bound the cost somewhat.

On the other hand I'm not convinced it helps the oscillation on curves. If you have a 3mm segment (1.5mm to accelerate) from 50 mm/s at 2000 mm/s², it could achieve 77 mm/s, but only 55 mm/s at 1000 mm/s². That seems to help, but it's entirely dependent on the absolute magnitude of the accelerations. If you change it to 3000 and 1500 or 4000 and 2000, you still have huge oscillations (up to 67 or 77 mm/s, respectively, if I did the math right).

At 45 Hz and 2000 mm/sec^2 max accel the toolhead can oscillate by (and thus produce any meaningful details of the size of) ~0.03 mm. These are some very fine details.

I don't understand that derivation, but also I think you're omitting junctions, which are the whole topic of this issue report. At square corners you have instantaneous velocity jumps of scv (e.g. 5 mm/s) and at 10° turns you have instantaneous jumps of
about 10*sin(10°) or 1.75 times that much (e.g. 8.6 mm/s) on the axis perpendicular to the previous move. These will necessarily have large high frequency components.

@dmbutyugin
Copy link
Collaborator

dmbutyugin commented May 9, 2021

@KevinOConnor

Not sure I understand your question. FWIW, the red line in your picture at:

junction-deviation-momentum

looks generally like what I'd expect for cornering speeds. That is, the cornering speed of a zero angle (next move goes directly backwards) should be zero, the cornering speed of a 180 angle (no direction change) should be "infinite", and the cornering speed of a 90 degree angle should be a small finite number (eg, ~5mm/s). And, the curve itself should be smooth.

I meant that for 90 degrees, the toolhead maintains some small speed (5 mm/s), and so does the filament flow. However, at very sharp corners, the toolhead comes to almost a complete stop currently, which may negatively affect the filament flow in the hotend, and that PA may not be able to deal with it that well. I wanted to ask your opinion about this, and whether maintaining some non-zero velocity even for very sharp corners could be beneficial. Or maybe you see it as more important for the toolhead to slow down completely, e.g. for better filament adhesion.

Actually, it is not possible for the input_shaper to magnify accelerations.

Yes. Sorry. I worded that poorly.

I meant that input_shaper may magnify a negative impact of acceleration changes - not that the acceleration itself would be greater. For example, if the look-ahead algo results in a speed change from 90mm/s to 95mm/s followed shortly after by a change from 95mm/s to 90mm/s, then input_shaper may turn those 2 speed changes into 6 or more speed changes. I don't know if that would negatively impact print quality, but if the speed change is pointless, then, well, it's pointless. If nothing else, it's more work for the rpi cpu to calculate more speed changes that aren't actually helping overall print time.

Input shaper affects only the toolhead kinematics, so it shouldn't adversely affect the extruder. Only the accelerations and decelerations from the lookahead algorithm have effect on extruder kinematics, including PA. On the print quality, any acceleration, deceleration, or any other deviation from the constant speed motion will indeed result in some amount of smoothing by the input shaper. So, any turns even without acceleration or deceleration are affected by input shaper to some degree. But relatively sharp corners, where this effect could be visible, are traversed at low speed, and that reduces smoothing. So, scv=5 mm/sec seems to be a good choice for input shaping as well, and not just for the extruder, because it gives little smoothing even up to quite low resonance frequencies.

@Piezoid
Copy link
Contributor

Piezoid commented May 10, 2021

On a side note, but somewhat related to this issue:

Some users use ArcWelder to recover curves after slicing or from coarse STL models. One reason is aesthetics, the other is avoiding slowdown on segment junctions.
From my limited testing, I gathered that the latter requires reducing [gcode_arcs] resolution quite a bit from the 1mm default. One potential alternative would be passing down the arc radius to the junction deviation algorithm, replacing the local approximation for these specific segments. Using the intent of tracing a curve allows greater speeds where the smoothing/deviation of the segmented curve doesn't really matter. That is, if we can ensure that the centripetal forces and smoothing don't alter the radius.

Klipper has a few minor customizations to the JD algo, but they're pretty basic: we configure via square_corner_velocity instead of junction_deviation.

I've sort of reverted this customization: I scale SqCV by the square root of the acceleration specified by M204. The rationale is obtaining more precision during the first layer, while allowing higher deviation for travel moves. Not that I have hopes of seeing something of this sort on the master branch, I'm just curious if you have an opinion on this.

@richfelker
Copy link
Author

Using the intent of tracing a curve allows greater speeds where the smoothing/deviation of the segmented curve doesn't really matter. That is, if we can ensure that the centripetal forces and smoothing don't alter the radius.

I'm starting to doubt my initial premise that it makes sense to traverse curves at the centripetal velocity whose acceleration matches the acceleration limit. A centripetal based limit probably makes sense, but I think it should be based on a much lower acceleration than the liner acceleration limit, possibly 10x lower or so. This works out to a much weaker growth of the limit than JD gives; you have tan(theta/2) instead of sin(theta/2)/(1-sin(theta/2)), so cancelling common factors, it's 1/cos(theta/2) vs 1/(1-sin(theta/2)), or letting u=sin(theta/2), 1/sqrt(1-x**2) vs 1/(1-x).

As for the reason for my doubts, the centripetal velocity at linear acceleration limit seems to have adhesion problems for me, pulling the material inward before it can adhere, at least with some materials and acceleration values that work fine for linear acceleration. So I'm turning my attention on this issue to just mitigating the oscillations rather than getting rid of the speed limits that caused them.

The rationale is obtaining more precision during the first layer, while allowing higher deviation for travel moves.

This is something I was thinking about yesterday, but taking it further, I concluded that if you want speed, you just don't put junctions in travel; you make all travel moves straight lines from the previous to the next extrusion move. And you can crank acceleration through the roof because, assuming you're doing proper retraction, there're a few [tens of] ms window for any vibrations to damp out during unretract before you start extruding again.

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented May 10, 2021

I meant that for 90 degrees, the toolhead maintains some small speed (5 mm/s), and so does the filament flow. However, at very sharp corners, the toolhead comes to almost a complete stop currently, which may negatively affect the filament flow in the hotend, and that PA may not be able to deal with it that well. I wanted to ask your opinion about this, and whether maintaining some non-zero velocity even for very sharp corners could be beneficial. Or maybe you see it as more important for the toolhead to slow down completely, e.g. for better filament adhesion.

My impression is that going to zero speed on a 0 degree turn (and near-zero speeds for sharp angles) is the desired behaviour. The basic idea is that if it is a "sharp corner" then getting good adhesion is more important than preventing blobbing. To be clear though, I have not done any particular stress tests to verify this impression.

For example, if the look-ahead algo results in a speed change from 90mm/s to 95mm/s followed shortly after by a change from 95mm/s to 90mm/s,

Input shaper affects only the toolhead kinematics, so it shouldn't adversely affect the extruder. Only the accelerations and decelerations from the lookahead algorithm have effect on extruder kinematics, including PA. On the print quality, any acceleration, deceleration, or any other deviation from the constant speed motion will indeed result in some amount of smoothing by the input shaper. So, any turns even without acceleration or deceleration are affected by input shaper to some degree. But relatively sharp corners, where this effect could be visible, are traversed at low speed, and that reduces smoothing. So, scv=5 mm/sec seems to be a good choice for input shaping as well, and not just for the extruder, because it gives little smoothing even up to quite low resonance frequencies.

Agreed.

FWIW, though, in a move of 90->95->90mm/s (as an example), it may be the case that just staying at 90mm/s produces better overall results.

Said another way, max_accel_to_decel prevents instantaneous acceleration to deceleration (when enabled, there will always be some cruising time between accel and decel). It may be worthwhile to also avoid some cases of instantaneous deceleration to acceleration by lowing the cruising velocity of some moves. I haven't tested this though.

Cheers,
-Kevin

@richfelker
Copy link
Author

Over the past couple days I worked out some explicit numbers with various models, and found that the only ideas I had that made some physical sense for locally limiting the velocity in ways that prevent the oscillating accel/decel cycles fail to do what's needed. Moreover, any local model is inherently bound to fail if you just split up each move into 2 moves at their midpoints with a 180° junction. At least as I understand it, the max_accel_to_decel model already fails in this way.

I think the right path forward here is just making use of the lookahead we already have. In particular, for each move, it's possible to look at a window (time-based or distance-based) of some delta into the future, and query what the min junction velocity limit is within that window. As stated, that's unstable with respect to a slow junction being just outside the window, so for the min, also include a limit calculated as follows: take the first junction past the end of the window, and compute the maximum attainable velocity for the move leading up to it, starting from the previous junction and reducing the move length by the remainder of the window length.

I need to work out a few more examples to make sure this is viable and does what's needed, but I think it achieves what was intended by max_accel_to_decel much better than the current system, and I think it's efficiently computable just by propagating limits back from the end of the queue the same way acceleration is done now. If it works I'll try to whip up a proof of concept for testing. If we have a general solution to the oscillation problem, tuning the junction velocity limits themselves then becomes an independent problem where I don't have to worry about how it impacts oscillations.

@github-actions
Copy link

Hello,

It looks like there hasn't been any recent updates on this
Klipper github issue. If you created this issue and no
longer consider it open, then please login to github and
close the issue. Otherwise, if there is no further activity
on this thread then it will be automatically closed in a few
days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants