Skip to content

motion: check circular moves against axis soft limits - #4619

Open
Rimas2200 wants to merge 2 commits into
LinuxCNC:2.9from
Rimas2200:fix/joint-path-limits
Open

Rimas2200 wants to merge 2 commits into
LinuxCNC:2.9from
Rimas2200:fix/joint-path-limits

Conversation

@Rimas2200

@Rimas2200 Rimas2200 commented Oct 3, 2026 •

Copy link
Copy Markdown

Fixes #3839.

Circular moves were checked at their endpoint before entering the motion queue. A G2/G3 move could therefore pass validation while exceeding axis soft limits between its endpoints, including full circles whose endpoints coincide.

Changes

  • Check the complete Cartesian bounds of circular moves before queueing them.
  • Use the end of the queued path as the starting position and the same circle geometry as the trajectory planner.
  • Handle partial and multi-turn arcs, spirals, helices, and tilted planes.
  • Retain the existing endpoint joint checks and runtime limit checks.

This PR is limited to Cartesian arc bounds. The proposed joint bounds interface and CoreXY/SCARA implementations have been removed from this PR to avoid overlapping with #4374.

Testing

  • uspace build passed.
  • RTAI build passed with --enable-werror (make -O -j4 default pycheck V=1).
  • All four test suites passed in uspace/POSIX simulation:
    • tests/arc-soft-limits
    • tests/posemath/arc-bounds
    • tests/abort/g64
    • tests/hard-limits

The tests cover rejection before motion in MDI and AUTO, queued starting positions, valid paths and tangencies, and arc geometry in different planes. Geometry tests also cover large coordinates, large turn counts, and invalid inputs. RTAI was built only; kernel modules were not loaded.

Scope

These checks cover commanded arc geometry before trajectory planning. They do not validate interior joint positions for arbitrary kinematics or subsequent trajectory changes from blending, interpolation, external offsets, or changes to limits after queueing.

@grandixximo

grandixximo commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

CI is complaining...

Haven't had a chance to look at the code yet, GitHub is being weird on my end...
I already have a large rework of the limits in the pipe, see #4374

@grandixximo

Copy link
Copy Markdown
Contributor

Thanks for this. #3839 is a real gap: an arc is only checked at its endpoint.

The joint side overlaps #4374, though. There, canon already takes every line and arc through the kinematics in force, whatever the module, and caps each segment at what its joints can follow; checking the joint position limits inside segments is the next step on the same sampling. #4374 also reworks the files the joint part touches: inRange() in command.c (the [AXIS_L] box moves to the machine frame), kinematics.h, and corexykins, scarakins and switchkins. A second per-module bounds interface would conflict with that.

Could you trim this PR to the Cartesian arc bounds: the full extent of partial, multi-turn, helical and tilted arcs, checked against the axis limits? That part is independent of the kinematics, fixes #3839 on trivkins machines, and would fit either way.

@Rimas2200

Copy link
Copy Markdown
Author

Thanks, that makes sense. I'll trim this PR to the Cartesian arc bounds, including partial, multi-turn, helical and tilted arcs, with the corresponding tests.
I'll keep the joint-limit work on a separate branch so it can be revisited alongside #4374 without introducing a competing kinematics interface.

@Rimas2200
Rimas2200 force-pushed the fix/joint-path-limits branch from b36668d to 6e6a145 Compare October 3, 2026 10:50
@Rimas2200 Rimas2200 changed the title motion: check axis and joint soft limits along commanded paths motion: check circular moves against axis soft limits Oct 3, 2026
@grandixximo

Copy link
Copy Markdown
Contributor

@andypugh @BsAtHome this targets 2.9. It fixes a long-standing bug, but it adds about 200 lines of new numerics to the motion module. I think master is the better place, with a backport to 2.9 later if wanted. What do you think?

if (b->amplitude == 0)
return;

if (b->radial_rate == 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does circle->spiral come out as for an R-word arc, where the interpreter computes the centre so both radii are equal? Is it exactly 0, or a few ulps? If it is 1e-15, which branch does this test send that circle down, and what does R/(2k) mean in the spiral branch with k at that size?

Try G0 X-36.2949 Y44.4302 then G2 X-96.1034 Y10.8100 R-109.857 against dense pmCirclePoint() sampling.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, you're right. I tried your example and got spiral = -1.42e-14, so it takes the spiral branch. The Y bounds come back as [10.81, 44.43], while sampling gives about [-173.21, 46.50]. That's a pretty big miss.
The code doesn't actually calculate R/(2k) - that's only in the comment - but the sign checks near the tan poles break down with k this small. The current tests don't catch it. Thanks for the example, this needs fixing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix it when I'm back at my PC. I'll switch to atan2 for finding the inflection points, so tiny k doesn't break the sign checks near the tan poles. I'll add your example to the tests too, and check both signs of a one-ulp radius difference.

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

Successfully merging this pull request may close these issues.

2 participants