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

Significant path deviation using arc interpolation with large R and small theta #21856

Closed
FormerLurker opened this issue May 9, 2021 · 9 comments

Comments

@FormerLurker
Copy link

Did you test the latest bugfix-2.0.x code?

Yes, and the problem still exists.

Bug Description

The arc interpolation algorithm produces paths that vary from the G2/G3 command significantly if theta_per_segment is very small (less than 0.001 radians). Here is a sample gcode sequence that can be used to replicate the issue:

G0 X122.404 Y139.732 E1128.24666
G2 X148.247 Y136.998 I-7179.760 J-67989.836 E1129.15389 ; This line causes the issue
G3 X171.844 Y149.342 I2.033 J24.839 E1130.13467

This gcode was taken from an issue on my ArcWelderLib repository, which includes pictures of a benchy showing the artifacts I was able to discover from the interpolated gcode.

Here is an overlay of the interpolated path (which I generated from my arc straightener project, which uses the Marlin 2.0 interpolation algorithm to produce G1 commands from G2/G3 commands) and the original G2/G3 path:

image

The path towards the bottom is the G2/G3, and I've zoomed into the bit where the issue is occurring, and have circled the endpoint of the deviation:

image

Here is an overlay of the original path from Cura and the path that was generated from arcwelder:

image

As you can see, there is no significant deviation.

I also experimented with adding a check to this line of G2_G#.cpp:

      if (--arc_recalc_count && ABS(theta_per_segment) > 0.001) {
        // Apply vector rotation matrix to previous rvec.a / 1
        const float r_new_Y = rvec.a * sin_T + rvec.b * cos_T;
        rvec.a = rvec.a * cos_T - rvec.b * sin_T;
        rvec.b = r_new_Y;
      }

Which fixed the issues I was seeing. Note that theta_per_segment = -0.0000146 in the example, which is quite small. The arc has a very large radius, and I think the combination of a large radius and a small theta_per_segment is causing the issue.

I'm not sure how exactly to check theta_per_segment for these kinds of deviations, but my initial thoughts would be to find a way to compare the arc radius and theta_per_segment to approximate the deviation, and bypass the small angle approximation if it would create substantial deviation. I will continue to think about this, and will test some solutions if I come up with any. I mostly wanted to post this issue here to generate some ideas for a resolution, since this is quite tricky.

I also know that disabling n_arc_correction would do the trick, but that seems like overkill. As long as r is not huge and theta_per_segment is not terribly small, the interpolation works well. This seems to be an edge case, but since it seems to affect the outside of benchy, an important edge case. You might also be interested to know that MANY other firmwares have this same issue, so it's not just Marlin, and it's not a bug that was introduced recently.

Please let me know if I can provide ANY additional useful data, like test cases, photos, more detailed explanations, etc, and THANK YOU SO MUCH for your hard work on this amazing project!

Bug Timeline

This has been around in every version that included arc interpolation, so probably all of them.

Expected behavior

Hopefully there would be no noticeable (visible) deviation. Something on the order of 0.025mm would NOT have been noticed, but this deviation was off by approximately 0.086MM, which is plainly seen on the outer shell.

Actual behavior

The interpolated arc (starting from point X122.404 Y139.732 and using G2 X148.247 Y136.998 I-7179.760 J-67989.836 E1129.15389) should have matched the requested arc to an accuracy that can't be seen with the naked eye.

Steps to Reproduce

  1. Run the following gcode through marlin:
G0 X122.404 Y139.732 E1128.24666
G2 X148.247 Y136.998 I-7179.760 J-67989.836 E1129.15389 ; This line causes the issue
G3 X171.844 Y149.342 I2.033 J24.839 E1130.13467
  1. Compare the last interpolated point with the point along the arc generated with the G2 command (can be done in ncviewer.com) and notice the large deviation.

You could also use the ArcStraightener.exe to see the results, though it doesn't match the current G2_G3.cpp code exactly. I'm working to add this to the project. Let me know if that's useful enough that I should expedite it.

Version of Marlin Firmware

Latest Bugfix

Printer model

NA

Electronics

NA

Add-ons

NA

Your Slicer

Other (explain below)

Host Software

SD Card (headless)

Additional information & file uploads

Since this issue is related to the interpolation algorithm itself, there should be no difference what slicer or printer is used. Also, I've verified that using true sin and cos (not the small angle approximation) at the beginning of the algorithm, and this made no difference. If N_ARC_CORRECTIONS = 0, however, and only this code is used to calculate X and Y, then the path is true to the original.

@XDA-Bam
Copy link
Contributor

XDA-Bam commented May 11, 2021

Hi. I quickly looked at the code. I don't have a full understanding of G2/G3 (yet), but these lines look mighty suspicious if we are talking about errors adding up for small theta:

sin_T = theta_per_segment - sq_theta_per_segment * theta_per_segment / 6,
cos_T = 1 - 0.5f * sq_theta_per_segment; // Small angle approximation

Did you also try to replace the approximation in those two lines with a precise solution? In the end, only calculating with higher precision for very small angles (like your did in your code snippet) might be enough to fix the problem. But for diagnostics, it would be good to know where it originates.

@FormerLurker
Copy link
Author

Did you also try to replace the approximation in those two lines with a precise solution?

Yes, I buried that nugget in the Additional information & file uploads, but should have probably included it at the top. The resulting path using sin instead of the small angle approximation above is indistinguishable from the path using the approximation.

The approximation of sin above is, for example, approximately 99.9999883 percent accurate. It's the actual interpolation step that is causing the issue here from what I can tell. Turning off interpolation (setting N_ARC_CORRECTION = 0) is the only thing that seems to work.

@XDA-Bam
Copy link
Contributor

XDA-Bam commented May 11, 2021

Sorry, didn't see that. Yes, looks like an accumulated numerical error due to the repeated application of the rotation matrix, specifically in the case where sin_T is very small. I'm not that knowledgeable in numerics, but my guess would be that in those cases, the rvec.# * cos_T-term is so much bigger, that we lose significant digits in the rvec.# * +-sin_T-term, which increases our accumulated error in each step.

One possible fix would certainly be your suggestion to ignore the subdivision for very small theta_per_segment.

Extending that idea: Looking at the code, the N_ARC_CORRECTION subdivisions look a bit arbitrary. Does it have to be a fixed config parameter? Would it perhaps be better to determine the number of subdivisions on a per-segment basis, depending on how big theta_per_segment happens to be?

@FormerLurker
Copy link
Author

Would it perhaps be better to determine the number of subdivisions on a per-segment basis, depending on how big theta_per_segment happens to be?

Yes, definitely. If we could very quickly calculate the error involved, corrections could be applied whenever a deviation threshold is met, but I'm not sure how to estimate the drift of this operation. I'm guessing that calculation will be rather slow, but I could be mistaken. This kind of math is above my pay grade.

@github-actions
Copy link

This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.

@FormerLurker
Copy link
Author

It might be good to keep this open a bit longer. I have not figured out a good solution yet, but am still working on it

@thisiskeithb thisiskeithb added the no-locking Prevent Lock-bot from locking the issue. label Jul 11, 2021
@fedetony
Copy link
Contributor

fedetony commented Sep 20, 2021

I've noticed the deviations in my machine. I attached a pen to the head and made the following Gcode test:

g1 z20 F1000
g1 X0 Y0 F1000
g1 z0 F1000
g1 x50 y50 F1000
g1 X0 Y0 F1000
g1 x50 y0 F1000
g1 x50 y50 F1000
g1 x0 y50  F1000
g1 x50 y0  F1000
g1 x0 y50  F1000
g1 x0 y0 F1000
g2 X50 Y50 R25 F1000
g1 X50 Y50 F1000
g1 x0 y0 F1000
g1 z20 F1000

and as you can see in the following images the paths deviate in diagonals and the circles are not ended in the exact position.

IMG_20210918_133036
IMG_20210918_134023

Is this expected or normal? What can I do for the paths to be overlapped in the diagonal directions?
The test was done after calibrating the path lengths with M92 command.

@thisiskeithb thisiskeithb removed the no-locking Prevent Lock-bot from locking the issue. label Apr 9, 2022
@github-actions
Copy link

github-actions bot commented Jun 9, 2022

This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.

@github-actions
Copy link

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 Aug 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants