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

G2 that triggers an ARC_ANGULAR_TRAVEL_EPSILON related calculation error #547

Open
bjerrep opened this issue Jul 10, 2024 · 4 comments
Open

Comments

@bjerrep
Copy link

bjerrep commented Jul 10, 2024

FreeCAD cam generated a gcode with a G2 that makes grblhal fall over. This snippet contains the G2:

G17 G90
G21
G54
M3 S17000
G0 Z1.000
G0 X54.000 Y5.431
G1 X54.000 Y3.600 Z-1.800 F300.000
G1 X54.000 Y4.231 Z-1.800 F300.000
G2 X54.000 Y3.600 Z-1.800 I-1379288.060 J-0.621 K0.000 F300.000
G0 Z1.000
M5
G17 G90
M2

This is an arc with a radius of some 1.38 kilometres. It might be the result of me setting an unreasonable precision in FreeCAD somewhere but as far as I can tell it remains a valid G2 statement nevertheless. Since it is so close to horizontal the following line in motion_control.c produces an angle just below ARC_ANGULAR_TRAVEL_EPSILON:

float angular_travel = (float)atan2(rv.x * rt.y - rv.y * rt.x, rv.x * rt.x + rv.y * rt.y);

which triggers an unfortunate "angular_travel -= 2pi" in the following:

if (turns > 0) { // Correct atan2 output per direction
if (angular_travel <= ARC_ANGULAR_TRAVEL_EPSILON)
angular_travel += 2.0f * M_PI;
} else if (angular_travel >= -ARC_ANGULAR_TRAVEL_EPSILON)
angular_travel -= 2.0f * M_PI;

I guess this issue can now go in a number of directions, the first probably beeing 'dont make rediculous G2 with insane radii' or something like that. But if grblhal shouldn't produce potential tool crashes on otherwise 'valid' gcode then there perhaps is something to look into?

For now I just tried to comment the if-else away and now everything is working as expected with the FreeCAD G2. I suspect the ARC_ANGULAR_TRAVEL_EPSILON checks have been around since the dawn of time with softfloat on 8 bit or what not. I get a little lost trying to figure out why an slightly unreasonable small angle is not just left as beeing excactly that, but need to get translated into a full circle. And there are probably one or more very valid and concrete usecases for the fix somewhere, but i haven't found them, or been able to figure it out.

Just some final notes: changing the precision from float to double might move problematic arc centres to mars or thereabout but it won't really fundamentally fix the 2pi thing. If the atan2 is suspected of some small nasty calculation roundoff errors then it might make more sense to compare the sign to the first (y) argument to atan2 and the sign of the resulting angle. They should be the same or something has gone wrong in atan2. Not sure if that would be useful for what the fixup code above tries to accomplish?

@terjeio
Copy link
Contributor

terjeio commented Jul 15, 2024

Some info here.

@bjerrep
Copy link
Author

bjerrep commented Jul 19, 2024

Thanks, but I did read that. Its a nicely written comment but it didn't really help me appriciate the effect of turning a very small arc to a full circle. I still can't help think that this fixed an error found in a very dated math softfloat thingy way before 32 bit. I failed to mention that the few gcode visualizers I tried with the gcode above all worked fine.
I appreciate that it is part of working code and has been for a long time and that I should somehow be able to prove that it isn't valid anymore. And that I am afraid requires someone with floating point skills that I don't have.

I guess this issue should be closed again but I will let that be up to you.

@terjeio
Copy link
Contributor

terjeio commented Jul 21, 2024

I still can't help think that this fixed an error found in a very dated math softfloat thingy way before 32 bit.

Softfloat on most 8-bit controllers is likely to be IEEE-754 compatible and should not behave differently from hardware FPU or soft 32-bit implementations. So IMO the only way to get around this issue is to change the codebase to use double precision.

@bjerrep
Copy link
Author

bjerrep commented Jul 29, 2024

Regarding precision:

I guess my primary crime was not to fully comprehend that this natively is a float codebase and actually realise how relatively few decimal places a float is able to handle. So the Freecad 'I-1379288.060' actually becomes -1379288.000 after the input parsing. I don't know if it would be a job for grblhal to reject gcode with floating point that it is unable to parse 100% correctly? (it's not really related to the issue here though)

I don't think I can say anything useful regarding your comment about a general change to double precision. I am working on a STM32H743 which for one disqualifies me for appreciating implications which might exist for more constrained processors.

Regarding the circle correction:

Just to get a feel for how the 'float angular_travel = (float)atan2(y, x);' line works I tried among others the following 3 sets:

G0 X0.00000 Y0.00000
G2 X0.00000 Y0.00002 I1 J0.00001 F100
gives angular_travel=-2.000000e-05

G0 X0.00000 Y0.00000
G2 X0.00000 Y0.00002 I10000 J0.00001 F100
gives angular_travel=-2.000000e-09

G0 X0.00000 Y0.00000
G2 X0.00000 Y0.00002 I1000000000 J0.00001 F100
gives angular_travel=-2.000000e-14

which suggests that the double world of atan2 and its arguments, and its subsequent float conversion, doesn't seem to have any intrinsic problems around ARC_ANGULAR_TRAVEL_EPSILON (again on a STM32H743). Hardly an impressive proof but for now at least I am living happily without the circle correction code.

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

No branches or pull requests

2 participants