Skip to content

Fix/tp circle curvature - #4643

Open
Rimas2200 wants to merge 3 commits into
LinuxCNC:masterfrom
Rimas2200:fix/tp-circle-curvature
Open

Rimas2200 wants to merge 3 commits into
LinuxCNC:masterfrom
Rimas2200:fix/tp-circle-curvature

Conversation

@Rimas2200

Copy link
Copy Markdown

Fixes #4642.

pmCircleEffectiveMinRadius() uses the total axial rise of a command in its curvature estimate. For a constant-radius helix with R=10 mm, rise=20 mm and a full turn, it gives a radius of 50 mm. Splitting the same path into four arcs changes the estimate to 12.5 mm per arc. The geometric curvature radius is about 11.0132 mm in both cases.

Change

  • Calculate curvature using axial rise per radian and find the maximum curvature along a spiral.
  • Apply the corrected normal-acceleration limit to constant-radius helices. Keep the existing jerk limits and the existing motion limits for general spirals.
  • Recalculate limits when blending changes arc geometry, and add geometry, limit and headless motion tests.

Testing and limits

The TP regression tests and headless simulation tests passed. The committed motion test checks completion and endpoints; it does not assert acceleration.

In a separate POSIX simulation capture (1 ms servo period, F6000, acceleration limit 100 mm/s^2), peak commanded acceleration decreased from about 134 to 104 mm/s^2. Some overshoot remains, so this change should not be taken as full acceleration-limit compliance.

@grandixximo

Copy link
Copy Markdown
Contributor

@Rimas2200 shellcheck fails on the test script

@thomam04 could you check this, I know you do spirals a lot :-)

@BsAtHome BsAtHome left a comment

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.

Only looked at form. Content/calculation review must be done by someone more familiar with this code.

Comment on lines +9 to +14
"${CC:-cc}" ${CFLAGS:--O2} -std=gnu11 -Wall -Wextra -fno-fast-math \
-ffunction-sections -fdata-sections -DULAPI \
-I"$HEADERS" -I"$TOPDIR/src" -I"$TOPDIR/src/emc" -I"$TOPDIR/src/emc/tp" \
test.c "$TOPDIR/src/emc/tp/tc.c" "$TOPDIR/src/emc/tp/blendmath.c" \
"$TOPDIR/src/emc/tp/circle_curvature.c" "$TOPDIR/src/emc/tp/cruckig/roots.c" \
-L"$LIBDIR" -Wl,-rpath,"$LIBDIR" ${LDFLAGS:-} -Wl,--gc-sections -lposemath -lm \

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.

This is problematic. You are recreating compiler options which you do not control and will be hard to maintain.

Can't you create a component and do the test in rtapi_app_main(), just like other tests?

Comment thread src/emc/tp/tp.c
if (!line || tc->motion_type != TC_LINEAR) {
STATIC __attribute__((__noinline__))
int tpPrepareGeometryChange(TC_STRUCT const *tc, PmCircle const *circle,
PmCartLine const *line, int previous, tp_prepared_geometry_t *prepared)

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.

Why is this marked noinline? (and tpValidateFinalization below too)
The compiler is a better judge that most humans.

Comment on lines +12 to +19
"${CC:-cc}" ${CFLAGS:--O2 -g} -std=gnu11 -Wall -Wextra -fno-fast-math \
-ffunction-sections -fdata-sections -DULAPI \
-I"$root/src/emc/tp" -I"$root/src/libposemath" -I"$root/src/rtapi" \
-I"$root/src/emc/nml_intf" -I"$root/src/emc/motion" \
-I"$root/src/emc/kinematics" -I"$root/src/hal" -I"$root/include" \
"$here/test.c" "$root/src/emc/tp/circle_curvature.c" \
"$root/src/emc/tp/blendmath.c" "$root/src/libposemath/_posemath.c" \
${LDFLAGS:-} -Wl,--gc-sections -lm -o "$build/test"

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.

This command line is even more convoluted and uses include statements that are incompatible and unmaintainable. Additionally, we've been removing all these extra -I options in the Makefile and now you are adding them here in the test.

Comment thread src/emc/tp/tc.c
Comment on lines +1076 to +1078
if (!tc || !isfinite(tc->target) || tc->target < 0.0 ||
!isfinite(tc->cycle_time) || tc->cycle_time <= 0.0 ||
!isfinite(tc->maxvel) || tc->maxvel < 0.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.

Can a value become -1e-15 or so due to rounding?

Comment on lines +1 to +4
/* SPDX-License-Identifier: GPL-2.0-only */
#include <rtapi_math.h>
#include "circle_curvature.h"

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.

Is this new file used anywhere other than once? The header only seems to be included once.

Comment thread src/emc/tp/tc.c
Comment on lines +886 to +891
if (!isfinite(radius) || radius <= 0.0 ||
!isfinite(jerk_radius) || jerk_radius <= 0.0 ||
!isfinite(angle) || angle <= 0.0 ||
!isfinite(a_max) || a_max <= 0.0 ||
!isfinite(input_maxvel) || input_maxvel < 0.0 ||
!isfinite(tc->cycle_time) || tc->cycle_time <= 0.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.

When do infinities/singularities occur?
Can they be prevented from occurring? Having to deal with them here seems too late if they could have been prevented.

Comment thread src/emc/tp/tc.c
/**
* Given a PmCircle and a circular segment, copy the circle in as the XYZ portion of the segment, then update the motion parameters.
* NOTE: does not yet support ABC or UVW motion!
*/

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.

Why all the extra pointer arguments. Can' t they be passed as one structure reference or are these not related to belong together?

@grandixximo grandixximo left a comment

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.

The helix curvature formula checks out, and keeping the old estimate as a floor for sweeps under one radian makes sense. Bertho covered the form; my comments are on the content.

The fix itself is about twenty lines (rise per radian, minimum against the old radius, same radius for jerk). Could the isfinite hardening and the prepare/commit rework go in a separate PR? Bertho's questions about infinities and rounding are really about that part.

For the tests, tests/kins-jacobian (#4586) is an example of the component pattern Bertho describes.

Please squash the two fixup commits and give the PR a descriptive title.

Comment thread src/emc/tp/tc.c
}
legacy_radius = pmCircleLegacyMinRadius(circle);
/* For a spiral, progress is not spatial arc length. */
radius = circle->spiral == 0.0 ? 1.0 / curvature : legacy_radius;

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.

Spirals still take legacy_radius here. So what uses the spiral branch of tpCircleMaxCurvature, apart from the validity checks? If nothing does, could this PR stay helix-only, as you suggested in #4642?

Comment thread src/emc/tp/blendmath.c
rise, kappa_max);
}

double pmCircleEffectiveMinRadius(const PmCircle *circle)

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.

Who calls this now? Same question for tcSetCircleXYZ.

Comment thread src/emc/tp/tp.c
tpHandleBlendArc(tp, &tc);
}
tcFinalizeLength(prev_tc);
if (prev_tc && tcFinalizeLength(prev_tc) < 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.

By this point tpHandleBlendArc() may already have changed prev_tc and queued a blend arc. What state is the queue in if this fails? tpValidateFinalization() checks prev_tc before the blend changed it. The same applies at line 2358.

Comment thread src/emc/tp/tp.c
if (!tc) {
return TP_ERR_OK;
}
TC_STRUCT candidate = *tc;

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.

This is a 1744-byte copy on the motion thread stack, next to the TC_STRUCT that tpAddLine already holds. Is this what the noinline attributes work around?

if result == linuxcnc.RCS_ERROR or time.monotonic() > deadline:
raise RuntimeError(f"move failed or timed out: {gcode}")
if max(abs(a - b) for a, b in zip(xyz, endpoint)) > 1e-4:
raise RuntimeError(f"wrong endpoint for {gcode}: {xyz}, expected {endpoint}")

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.

Would this test fail on master? It checks endpoints only, so the change is not covered. Could it assert peak acceleration on the one-turn helix instead?

Comment thread src/emc/tp/tc.c
}
/* Keep the tighter of the old and geometric limits. */
maxvel = fmin(maxvel, geometric_maxvel);
tangent_ratio = fmin(tangent_ratio, geometric_tangent_ratio);

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.

The ratio and the velocity can come from different radii here. That is conservative, but worth a one-line comment.

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.

TP helix curvature estimate depends on arc subdivision

3 participants