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

[Discussion] Handling of junction speeds and jerk #9917

Closed
Sebastianv650 opened this issue Mar 3, 2018 · 89 comments
Closed

[Discussion] Handling of junction speeds and jerk #9917

Sebastianv650 opened this issue Mar 3, 2018 · 89 comments
Labels
T: Design Concept Technical ideas about ways and methods. T: Development Makefiles, PlatformIO, Python scripts, etc.

Comments

@Sebastianv650
Copy link
Contributor

This is a follow-up to a topic which already was here a long time ago, but I can't find it anymore. If someone remebers it and can find the issue, you might link it here.

During the research for strange jerk behaviour today I stumbled around the suboptimal handling of junction speeds again. In one sentence: Marlins way of handling jerk and junction speeds leads to exceeded jerk in some daily situations.
The attached test gcode and the results in the table should clarify things a bit. The gcode does the following things:

  • set the jerk speeds to the selected values
  • First it does 4 G1 travel moves
  • followed by 4 G1 print moves
  • in the last round it does a prime move (extruder only), followed by two print moves, a retract - travel - prime combination and again a print move.

I printed the following values over serial:

  • max junction speed as calculated by the jerk code inside the planner
  • initial and final step rate of each block as it gets executed
  • initial and final speed of each block (step rate / steps/mm), this one is calculated inside Excel by hand

I did two runs, first with X and Y jerk set to 5 and E jerk set to 1mm/s, and a second one switching the values. As you can see, as soon as we are switching between extruder only moves and XY moves things start to get wired. Same should be true for Z only moves and XY moves.
The problem is that Marlin connects each segment by one single junction speed, which is not always what is needed. A simple example like the one from H13 in the table, lets assume a X Jerk of 1, an E jerk of 5. Let's do a print move along X followed by a prime move. What we want ist:

  • Start with a jerk speed of 1
  • Accelerate to cruising speed
  • Decelerate to jerk speed 1. The extruder speed in this case is nearly 0 due to the low X jerk.
  • Now the prime move, start with a jerk speed of 5
  • accelerate, cruise and decelerate to jerk speed of 5 again.

The two axis X and E are not linked, also their junction speeds shouldn't be linked. What Marlin does is in this case is:

  • Start with a jerk speed of 1
  • Accelerate to cruising speed
  • Decelerate to jerk speed 5 -> Ignoring the needed final speed of 1!
  • Now the prime move, start with a jerk speed of 5
  • accelerate, cruise and decelerate to jerk speed of 1 -> Jerk value from next print move!

jerk

It becomes crucial when we replace the first print move by a Z move. Z axis often have 0.x jerk values, but the final speed would be also 5mm/s due to the following retract move.

Conclusion:

  • A junction speed in terms of final speed = next start speed is only needed to give a smooth movement along a 3D path. Retracts and prime movements does not fall into this, so their speeds should be decoupled.
  • Same is true for extruder speed changes due to variable width paths: the 3D movement XYZ has always a connected speed, but the extruder speed can jump at the junctions.
  • If we have to connect end and start speeds, we always have to check if all axis can follow the choosen final or start speed. We can't finish X at 5mm/s if it needs 1mm/s only because the next E move can start at 5mm/s.
  • That was the easy part. Any ideas how such a jerk implementation could look like? GRBL will not help, as this is a 3D printer specific problem.

Files:
Marlin Junction speeds.zip

@thinkyhead
Copy link
Member

thinkyhead commented Mar 7, 2018

GRBL will not help

Ah, well so much for my first suggestion…

Well, at some point we should try implementing a proper "junction deviation" and see whether it helps … and whether it's expensive to compute. We may be able to get away with using a table or some other cleverness to avoid having to do trigonometry.

But before we get into that, we should definitely figure out how to de-couple the E axis from the linear axes. And, it seems XY also needs to be less bothered by Z direction changes. Maybe for Z direction changes we can relax the Z jerk limit a bit. The thing is that Z seldom has anything like the same inertia as the XY axes. You'd think Z would be more amenable to direction changes, especially when going from raising to lowering.

@thinkyhead thinkyhead added T: Development Makefiles, PlatformIO, Python scripts, etc. T: Design Concept Technical ideas about ways and methods. labels Mar 7, 2018
@Sebastianv650
Copy link
Contributor Author

I think the way we calculating jerk at the moment is already quite good. Check for all axis jerk limitation, reduce entry / exit speed if one axis is exceeding the limit. But as we have to check entry and exit speed for jerk, we need to know about the previous and (that would be new) the next segment. At the moment, the planner assumes exit speed = next entry speed is always OK. So it needs to go into the forward or reverse planner. And it has to make a decision if the junction speed has to be linked or not. Some draft ideas:

  • Never link extruder only moves to other moves than e-only moves.
  • print moves has to be always linked to print moves.
  • The transition between print and travel moves is an intresting one. With retraction, this combination will never happen but without a retraction (like in a short travel move) it could create a noticeable difference in visual print quality. For example, if we come from a high speed travel move to a print move, the XY movement only has to go down to speed of print move. But this would mean E has to start at full print speed. Even if e jerk isn't violated, this means a sudden jump in nozzle pressure without acceleration, likely causing a ringing like artefact as pressure stabilizes.

Clearly we need to do test prints to simulate some of the effects before start coding. I think I could have some fun doing that, but it's something for the middle future - we don't want to release such a big planner change without intensive tests..

@Sebastianv650
Copy link
Contributor Author

Sebastianv650 commented Mar 8, 2018

I want to put some questions here to think about them. Maybe there are some intresting answers comming?

  • Why do we link the junctions speeds at all? (Think about a XY moving print head like on Ultimaker vs X for extruder and Y for bed separated)
  • If we link junction speeds, why do we link the XYZ vector speed and not E speed for 3d printing?
  • If we link junction speeds (XYZ or E), is it meaningful to do this in every case or might it be useful to seperate end and start speeds in some situations?

I'm looking forward to read your opinions!

@thinkyhead
Copy link
Member

thinkyhead commented Mar 9, 2018

Why do we link the junctions speeds at all?

This seems to be a legacy of the XY gantry design of the Ultimaker that probably should not apply to Mendel X carriage / Y bed setups. And neither of those should be linked to Z. Before bed leveling came along, in 3D printing Z moves were almost always isolated Z or Z/E moves.

The theory of XY gantries seems sound — you do want to limit the inertial load of the carriage block, even though XY each have their own separate inertial loads too. I think you're onto something in pointing out that separated axes should only apply load limits on a per-axis basis and not in terms of the combined motion in the XY plane.

Better not to think too hard about deltas.

@ruevs
Copy link

ruevs commented Mar 24, 2018

Hi,
I apologize for barging in on the conversation, but I think I have some relevant information. In my opinion deltas are an important group of machines and Marlin has treated them as "second class citizens" long enough.

I have been trying Marlin 1.1.8 (https://github.com/ruevs/Marlin_Anycubic_Kossel) and Repetier 0.92.9 (https://github.com/ruevs/repetier_anycubic_kossel) on the same delta printer. The configurations are as close as possible to each other. Max speeds and accelerations are the same. The jerk is 10 in Marlin and 20 in Repetier. As I understand that after this #8888 those values should lead to similar results.
And now the interesting part. I tested the printer with this G-Code SpeedTest.zip with both firmwares.
And here is the result:
https://youtu.be/JCflNCotl70?t=1758
Repetier drives the steppers "smoother" (the sound is softer and less "scratchy"), finishes the test a bit faster and with less vibration/jerk.
In my opinion something in the way Marlin drives the steppers in deltas is... different and not optimal.

@Sebastianv650
Copy link
Contributor Author

Sebastianv650 commented Mar 25, 2018

@ruevs please try the current bugfix-1.1.x. We patched a basic fault in the delta planner code which resulted in real speeds (and all derived values) way off the defined value and I'm quite sure this PR was done quite some time after 1.8 was released.

@thinkyhead
Copy link
Member

thinkyhead commented Mar 29, 2018

In my opinion deltas are an important group of machines and Marlin has treated them as "second class citizens" long enough.

We continue to incrementally improve Marlin's delta support, and have done loads of optimization in recent releases and in the upcoming release. If someone brings us a comprehensive overhaul that addresses delta concerns in the form of a nice PR we would be more than thrilled.

@Roxy-3D
Copy link
Member

Roxy-3D commented Mar 29, 2018

In my opinion deltas are an important group of machines and Marlin has treated them as "second class citizens" long enough.

Perhaps nobody decided to treat Deltas as "Second Class Citizens". Maybe there is another explanation.

Deltas have only a small percentage of the users that Cartesian machines have. So this means first of all, it is much harder to get code developed and tested on Deltas. But it also means there are less people even interested in writing code for them. With that said, we do try hard to make the code work well on all machine types.

@ruevs
Copy link

ruevs commented Mar 30, 2018

Please do not take my comment the wrong way. I realize that Marlin has improved a lot in 1.1.x in terms of delta support. I only said it in response to thinkyhead's comment:

Better not to think too hard about deltas.

As for a pull request - if I ever have enough time to understand the code deep enough to actually improve or revamp the planner and stepper motor control logic for deltas I would certainly do so. Unfortunately this is unlikely.

@thinkyhead
Copy link
Member

thinkyhead commented Mar 30, 2018

Better not to think too hard about deltas.

That is to say, for any indirect kinematic system Jerk and Acceleration apply to the movement of the steppers, and not to the linear movement of the tool. Thinking about this too hard may lead to headaches.

@Sebastianv650
Copy link
Contributor Author

@thinkyhead Just retested the initial test pattern of this issue with the new junction code (#10650, JUNCTION_DEVIATION_INCLUDE_E is disabled) , this is the result:

new_jerk

I see some intresting results compared to the initial results:

  • The junction speeds for print moves are a lot lower than travel moves (9.1 to 15.5). Strange, as JUNCTION_DEVIATION_INCLUDE_E is disabled?
  • For e-only moves, the calculated speed values are even worse than with original jerk code. Keep that in mind if we see "extruder is skipping steps" issues in the near future.

Enabling JUNCTION_DEVIATION_INCLUDE_E increases the jerk speed for print moves and e-only moves slightly.

@thinkyhead
Copy link
Member

Thanks for bringing this back on topic. I definitely want to make the junction behavior more sensible, whether using the old jerk method or junction deviation. What we really need is to decide what the ideal behavior should be first, and then make needed adjustments to get it to produce those results as closely as possible. Your earlier points can act as a starting guide.

@Sebastianv650
Copy link
Contributor Author

Just a short addition to my last post:
Not only e-only moves suffer due to the new jerk code, also z moves (layer shifts) are affected. As z-axis often uses very low jerk limitations (0.x), this can definitly result in missed z steps. Maybe even worse, on a system which uses 2 z steppers, only one might miss a step resulting in a skewed axis.

The code change was a good first step, but some more work is necessary to make it secure and fully usable.

@thinkyhead
Copy link
Member

Not only e-only moves suffer due to the new jerk code,

@Sebastianv650 — Which "new jerk code" are you referring to in your comment? We have the sort-of-new jerk code related to the planner refactor (though it should be essentially the same limit-per-axis method) and then we have the new (but optional) JUNCTION_DEVIATION jerk code. The Bézier S-Curve acceleration is also new, but it follows after the main jerk calculations.

@Sebastianv650
Copy link
Contributor Author

I'm refering to JUNCTION_DEVIATION.

@thinkyhead
Copy link
Member

Should Z be excepted from the Junction Deviation technique? It's certainly not like the XY axes. Likewise, with any move not involving X and/or Y…

@p3p
Copy link
Member

p3p commented May 29, 2018

Should Z be excepted from the Junction Deviation technique

Only if you want to disregard 3D CNC Routing, my Z axis is the same as XY (velocity and acceleration wise) and in finishing passes on organic geometry can be moving pretty fast.

@thinkyhead
Copy link
Member

I think we probably want to disregard any axes that have low top speeds. That would filter Z and E on typical 3D printers, while allowing you to use CNC and arcs in vertical workspace planes.

@Sebastianv650
Copy link
Contributor Author

Maybe we need a two-step approach. For example on acceleration we already use a print acceleration and a max. acceleration per axis. If one axis max. acceleration is violated by the print acceleration, it will get lowered.

Same procedure can be applied on junction jerk. If the speed change on an axis from current to previous is bigger than axis max. jerk, limit the junction speed.
If the user sets all max. jerk per axis values to a high number (as we already have it for max. acceleration on many printers), this limit will never engage. So no problem for 3D CNC for example.

This might also solve the problem with wrong junction speeds which I pointed out at the start of this issue?

@thinkyhead
Copy link
Member

What is Grbl doing to mitigate the issue? Have we failed to fully duplicate their approach?

@Sebastianv650
Copy link
Contributor Author

I asked myself the same question, how GRBL sets limits for each axis, when I did my small Excel sheet for junction speed calculation. After reading their docs and code, I came to the conclusion that there is actualy no way to do this in GRBL since they use this jerk method.

@Sebastianv650
Copy link
Contributor Author

OK I have to correct what I just wrote. It's not very obvious, but I guess @thinkyhead we are realy missing an important piece of GRBL for JUNCTION_DEVIATION.

See https://github.com/gnea/grbl/blob/master/grbl/planner.c#L446, the key is junction_acceleration which is an acceleration value based on used acceleration (we would call it travel or print acceleration) and the junction_unit_vec. What they do is to calculate an acceleration which will not violate the acceleration limit per axis. For Z, which has the low jerk problem, we also use low accelerations. I checked that on my machines and the example configs inside Marlin. So, a low max jerk means also a low max acceleration on an axis.
Given that, a lower junction_acceleration and therefore block->max_junction_speed_sqr is the result.

In the Marlin implementation, we use a fixed JUNCTION_ACCELERATION. This completely ignores the axis acceleration limits!

Should be easy to fix, lets see if I can patch it..

@Squid116
Copy link
Contributor

@Sebastianv650 there is a hint in the comments in the main fork of the grbl that it should take the minimum acceleration of the two blocks, I think you might need this to cover off both sides of this problem.

@Squid116
Copy link
Contributor

Squid116 commented May 31, 2018

I am completely on board with @Sebastianv650's suggestion of using the actual junction acceleration (I never really understood why we moved to a fixed value). In normal movement this means that junction deviation will factor a heavy slow moving accelerating axis (y) in the calculations. This would mean that the nonagon example (#10341 (comment)) might not always produce the same junction speed - a move with more acceleration on a slower accelerating axis (i.e. mostly y) should slow down more.

However, I'm not completely convinced that it will solve this problem completely. Could it be as simple as hard setting the junction speed to 0 for E or Z only moves (with an option to not do this on Z for our CNC friends)? This method could also be applied to both Jerk and Junction Deviation solving the problem in both scenarios.

Edit: If done, how would setting a 0 junction speed work (or not work) for the z-hop in fwretract?

@Sebastianv650
Copy link
Contributor Author

@Squid116

there is a hint in the comments in the main fork of the grbl that it should take the minimum acceleration of the two blocks.

I read that, but this note is no longer present in the recent 1.1 GRBL code with the use of junction_acceleration. But I have that in mind to try it out. Basicaly it should make

Could it be as simple as hard setting the junction speed to 0 for E or Z only moves

not necessary.

I got the junction_acceleration to work yesterday and I will create a PR for testing purposes in the next minutes or hours depending on my test results satisfaction.

@Squid116
Copy link
Contributor

Squid116 commented May 31, 2018

But I have that in mind to try it out.

I think it would really be needed in order to get this working in all cases. Take the heavy Y bed as an example, if you go from a move along Y to a 90deg corner travelling along X, then this is only going to consider the acceleration on X for this junction, not the lower deceleration needed for stopping Y. The result will be a faster junction speed than Y can sensibly handle.

@thinkyhead
Copy link
Member

At this point I think we've got it sorted in both branches! Anything more to discuss or should we close this thread?

@gloomyandy
Copy link
Contributor

I think there are still some documentation issues around. Like for instance when should you enable JUNCTION_DEVIATION_INCLUDE_E? Does this interact with linear advance? Does it make sense to enable both?

@thinkyhead
Copy link
Member

Sounds like we will need to gain more experience to be able to answer those questions.

@Squid116
Copy link
Contributor

@Sebastianv650 mentioned removing the JUNCTION_DEVIATION_INCLUDE_E here: #10906

I tend to agree, I think it should always be enabled and the option removed.

@lrpirlet
Copy link
Contributor

lrpirlet commented Jun 29, 2018

@Sebastianv650

I am somewhat puzzled… I used to have in my working configuration the following acceleration setting…

#define DEFAULT_MAX_ACCELERATION      { 3000, 3000, 100, 10000 } //tuning lrp 3000, 3000, 100, 10000 } Tested ok except E axis

/**
 * Default Acceleration (change/s) change = mm/s
 * Override with M204
 *
 *   M204 P    Acceleration
 *   M204 R    Retract Acceleration
 *   M204 T    Travel Acceleration
 */
#define DEFAULT_ACCELERATION                  1500    // X, Y, Z and E acceleration for printing moves
#define DEFAULT_RETRACT_ACCELERATION  3000    // E acceleration for retracts
#define DEFAULT_TRAVEL_ACCELERATION    3000    // X, Y, Z acceleration for travel (non printing) moves 

/**
 * Default Jerk (mm/s)
 * Override with M205 X Y Z E
 *
 * "Jerk" specifies the minimum speed change that requires acceleration.
 * When changing speed and direction, if the difference is less than the
 * value set here, it may happen instantaneously.
 */
#define DEFAULT_XJERK                 10.0 
#define DEFAULT_YJERK                 10.0
#define DEFAULT_ZJERK                  0.3
#define DEFAULT_EJERK                  5.0

I put your formula in excel
max_ejerk [mm/s] = SQRT((SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5)))

For a junction deviation = 0.02, this formula gives me
either
a max acceleration of 517,9 for an ejerk of ~5,0
or
an ejerk of ~12,0 for a max acceleration of 3000

Obviously, one or several of my values were out of tune… Max acceleration was too high, the sloop of speed change was ok for the retract… should I conclude that my ejerk was too small??? I am driving a 3mm abs filament thru a greg wade extruder with a couple of gears with a ratio of 37-13...

I feel uneasy, did I miss something??? is that "calculated ejerk" value anything but limit or is that value actively used?? Of course I will conduct some testing and learn from my mistakes, but if you could help me make some educated guess, I would be quite thankful.

@lrpirlet
Copy link
Contributor

lrpirlet commented Jun 29, 2018

@Sebastianv650
Typing my question above led me to think from another perspective… Could it be that a 2mm retract is not enough of a move to go past the physical acceleration induced by the ejerk value???

If so, should I limit the max acceleration to 1500 leading to an Ejerk of 8,5???? I will be using S-curve-acceleration so this should allow my printer to allow higher number for moves (not higher overall speed I now predict)

ejerk funtcion of junction deviation.xlsx

@Sebastianv650
Copy link
Contributor Author

Sebastianv650 commented Jun 30, 2018

@lrpirlet I'm not sure if I understand you problem. Is it because your initial max acceleration values don't result in the ejerk values you had before junction_deviation using the equation? That's fine, as they were not linked in any means by the "legacy" jerk / acceleration code.

You can think of the junction deviation = 0.02 being the new jerk value. Given an acceleration, it results in junction jerk speeds. So you can still tune jerk and acceleration separate from each other, but linked by this value.

For linear advance, this ejerk speed value is used as the upper speed limit at which pressure corrections can occur.

Could it be that a 2mm retract is not enough of a move to go past the physical acceleration induced by the ejerk value???

The length of a move and the acceleration are not linked. If you mean top speed: With 3000mm/s² you can reach about 110mm/s even when starting from 0mm/s speed after 2mm.

If so, should I limit the max acceleration to 1500 leading to an Ejerk of 8,5?

A typical retract speed of 40mm/s is reached after 0.25mm @ 3000mm/s² even without any jerk. So if you want to reach an ejerk of 8.5mm, even an max. e acceleration of 1500mm/s² will not limit your printing speed noticeable.

@lrpirlet
Copy link
Contributor

lrpirlet commented Jul 2, 2018

@Sebastianv650
Thanks, what makes me wonder, is that we use to be able to set INDEPENDENTLY max speed and jerk… When coming from a well tuned version 1.? to the bugfix_2.0.x version I did try to match my old parameters to the new… And here is a hardcoded relation...

Using the new features, I feel like facing a completely new firmware with nearly no relation with the old one… Trying to understand the interaction between the new features is quite a challenge… I do not want to keep hanging on the "good old way of doing things" when what I see could really solve some of the problems I am facing today…

Question was and is really: what is a good approach when the examples do NOT use the new features, I did try to understand from a theorycal side… I better have to jump in practical side and make mistakes, I guess…

Anyway, I do appreciate your help… thanks again.

@thinkyhead
Copy link
Member

thinkyhead commented Jul 2, 2018

I presume we'll have to document the updated (i.e., corrected) meaning of the jerk parameters for 1.1.9 and give recommendations for the appropriate values to use. And we should also update the configurations with reasonable values. @lrpirlet — What values are working well for you now, and what values were you using before?

@lrpirlet
Copy link
Contributor

lrpirlet commented Jul 4, 2018

@thinkyhead

Sorry, I have no experience yet… My heated bed shorted, the FET melted shorted, the RAMPS printed board heavily smoked, the fuse did not (completely) fuse… I am waiting a new bed, a new RAMPS... Not sure to get it before the holliday so not before 3 weeks or so...

I can still move the axis of the printer, I think I could extrude, but with ABS, there is no chances to get anything but a big mess…

To answer your question, the max acceleration for X, Y Z seems to be compatible (I did run a dryrun print). At completion, I was able to move the hot end back to the exact same place marked before execution. So no steps lost…

For E, I will limit the DEFAULT_MAX_ACCELERATION to 1500 giving an equivalent ejerk of about 8,5... I hope the extruder will bear with it… I may have to drop down to 500 if I really need an équivalent ejerk of 5... For what concerns retraction, that used to need 40*60 (2400), I was thinking to use LA and completely forget retraction…

AGAIN, NO EXPERIENCE YET... but I feel uneasy with E axis

@Itox001
Copy link

Itox001 commented Sep 9, 2018

I was starting to use junction deviation, currently set my initial parameters according to the equation:

max_ejerk [mm/s] = SQRT((SQRT(0.5) * max_acceleration_mm_per_s2[E_AXIS] * junction_deviation_mm) / (1 - SQRT(0.5)))

Using my old jerk values and the default junction deviation value of 0.02 I derived my accelerations, this seemed to work fine for x, y and e, it resulted in sensible values and printer seems to be pretty happy with it. But what hapens with the Z axis? Using my old jerk of 0.4, the formula results in an acceleration of 3.3 mm/s^2. This doesn´t seem right. Is this calculated differently?

The older acceleration I used in Z, 1500 mm/s^2, leads to a jerk of 8.5. I see on a post above that it was said that this values are fine if they are different becuase they are not linked to previous value. But then, what should it be set to?

@Sebastianv650
Copy link
Contributor Author

@Itox001 your z axis will most likely be just happy with the values. Prior to all this changes even if you had set the z jerk to 0.4 the real jerk in about 50% of the situations was the XY jerk value. That's because this jerk was only applied to the entry speed, but the end of the move should have ended at z jerk speed also.

@boelle
Copy link
Contributor

boelle commented Oct 24, 2019

@Sebastianv650 @Roxy-3D

has the new JD calc's not made this one "surplus" or is it still relavant?

@boelle
Copy link
Contributor

boelle commented Nov 24, 2019

this one has gone stale and discussion could continue on discord

Marlin Discord server. Join link: https://discord.gg/n5NJ59y

@boelle boelle closed this as completed Nov 24, 2019
@github-actions
Copy link

github-actions bot commented Jul 4, 2020

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 4, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
T: Design Concept Technical ideas about ways and methods. T: Development Makefiles, PlatformIO, Python scripts, etc.
Projects
None yet
Development

No branches or pull requests