Skip to content

kinematics: let a module report where the tool points - #4455

Open
grandixximo wants to merge 7 commits into
LinuxCNC:masterfrom
grandixximo:kins-tool-frame
Open

kinematics: let a module report where the tool points#4455
grandixximo wants to merge 7 commits into
LinuxCNC:masterfrom
grandixximo:kins-tool-frame

Conversation

@grandixximo

Copy link
Copy Markdown
Contributor

A kinematics module reports the controlled point and nothing about which way the tool faces, so everything that needs the tool frame rebuilds the machine geometry for itself. For xyzacb-trsrn the same chain is written three times: closed-form in xyzacb_trsrn.comp, as homogeneous matrices in the config's remap_funcs_twp.py, and as signed HalRotate calls in the vismach model. The only thing keeping them in step is a comment in the Python saying its matrices "must be the same as the ones used to derive the kinematic model".

This adds an optional entry point a module can answer with instead, and a chapter saying what it answers in.

int kinematicsToolFrame(const double *joint,
                        PmRotationMatrix *rot,
                        const KINEMATICS_FORWARD_FLAGS *fflags);

The columns are the tool frame axes in world coordinates. Its origin is the controlled point kinematicsForward() already gives, so the pair is the whole tool pose.

Nothing is obliged to change. switchkinsSetup() and switchkinsRegister() keep their signatures; a type opts in through a separate call. Nothing in motion calls the entry point, so no module has to define it, and an out-of-tree module need not know it exists. Modules built on switchkins.c export it and return -1 for a type that has not supplied one.

The two conventions. The tree already contains both senses, and they come from two standards rather than from carelessness. ISO 9787 clause 5.3 puts a robot's flange z pointing perpendicularly away from the mechanical interface, and pumakins follows it, reaching the tool tip by adding PUMA_D6 along its third column. Machine tool practice puts z along the spindle, positive away from the work, which is what G68.2 commands. The chapter settles on the machine tool sense for what a module reports, and a module whose own maths is in the other one declares the rotation relating them rather than fixing it up by hand.

That matters because it is not a change of sign. Negating the third column gives determinant -1, a reflection, and loses tool x as well. The declared rotation is checked once at registration for orthonormality and determinant +1, so a bad declaration fails at load rather than producing a quietly wrong frame.

Supplied for trivkins, the identity switchkins types, xyzac-trt-kins, xyzbc-trt-kins, both trsrn nutating modules, and pumakins.

Verification. The trt and trsrn frames were derived and then checked two independent ways against each module's own forward transform: the coefficients the forward applies to a linear-joint displacement must be the table rotation alone, and the tool axis recovered separately as the direction the tip retreats along when the tool gets longer must equal the third column. Agreement is 3e-9 across 27 poses per trsrn machine and 32 per trt machine, orthonormal, determinant one. The new test covers the shared helpers and was verified by mutation, not by passing: making the flange constant a reflection fails nine checks, and reversing the multiplication order fails four.

The pumakins refactor lifts its rotation out of the forward kinematics into one function rather than writing it twice. The moved block is byte-identical.

What is not covered: pumakins is not exercised end to end. The claim that it reports the identity at every joint zero is verified by computing its closed form, not by running the module, because there is no caller for the entry point yet. A non-realtime caller is the next piece of this work and is what would close it.

Part of the multiaxis kinematics work in #4374, item 3. Replaces #4454, which was the chapter on its own; that could not merge alone without documenting an API the tree did not have.

A kinematics module reports the controlled point and nothing else, so
everything needing the rest of the machine geometry rebuilds it.  For
xyzacb-trsrn the same chain is written three times: closed-form in
xyzacb_trsrn.comp, as homogeneous matrices in the config's
remap_funcs_twp.py, and as signed HalRotate calls in the vismach model.  The
Python copy is kept in step by a comment saying its matrices "must be the
same as the ones used to derive the kinematic model".

Write down the vocabulary they would need to share: the four frames and which
one kinematicsForward() reports in, the rotation sense already stated under
Rotational Axes and its ISO 841 equivalent, what conventional-directions
costs at its default, and the definition of the tool frame.

Tool x is the part worth stating as a rule rather than a formula.  The
virtual rotation about tool z supplies what a five-axis machine cannot, and
the convention is that it leaves tool x parallel to the machine xy-plane; the
formula follows from the machine's own secondary rotation matrix, which is
why the two nutating configs in tree have different ones.

Also anchor the Rotational Axes section so it can be referenced.
kinematicsForward() reports where the controlled point is and nothing about
which way the tool faces, so a consumer that needs the tool frame rebuilds the
machine geometry for itself.  Add an entry point the module can answer with
instead:

  int kinematicsToolFrame(const double *joint,
                          PmRotationMatrix *rot,
                          const KINEMATICS_FORWARD_FLAGS *fflags);

The columns of the rotation are the tool x, y and z direction vectors in world
coordinates; its origin is the controlled point kinematicsForward() gives for
the same joints, so the pair is the whole tool pose.  Conventions are in the
Kinematics Conventions chapter.

Modules built on switchkins.c export it always and dispatch on the current
type, returning -1 for a type that has not supplied one, which is a report
rather than an error.  A type registers with switchkinsRegisterToolFrame()
from its switchkinsSetup(); leaving it out costs nothing.  Adding it that way
rather than as arguments to switchkinsSetup() and switchkinsRegister() keeps
both signatures as they are, so no module has to change to build.

Identity types answer the same way whichever module asked for them, so
switchkins.c attaches identityKinematicsToolFrame() to any type whose forward
is the identity one, and every switchkins module gains a correct tool frame
for its identity type without being touched.

Nothing in motion calls it, so no module is obliged to define it and a module
outside the tree need not know it exists.  A caller resolving it dynamically
has to cope with its absence.
The forward transform already contains the rotation: the coefficients it
applies to a displacement of the X, Y and Z joints are the columns of the
rotation the table contributes, which is the orientation of the tool in the
work.  Write those coefficients out as the tool frame and register it for
whichever switchkins type holds the trt kinematics.

Checked against the forward transform by central difference over the linear
joints at four primary and four secondary angles with both settings of
conventional-directions: columns agree to 3e-9, the result is orthonormal
with determinant one, and tool z is world z with the rotaries at zero.

The check also shows the sign question plainly.  With conventional-directions
true, A at 90 degrees on an xyzac machine puts tool z along -Y, which is +Z
turned counterclockwise about +X as the documentation says it should be.  With
the pin at its default of false the same move puts tool z along +Y.
trivkins does not build on switchkins.c, so it does not pick up the identity
tool frame the way a switchkins identity type does.  Hand it through, since it
is the kinematics most machines run and a caller that has to special-case the
commonest module has not gained much.
These modules carry their own switchkins dispatch, so they answer for all
three of their types directly.

For TCP kinematics the frame is the table rotation times the primary rotation
about z times the nutating secondary rotation, written out as three matrices
and multiplied rather than expanded, so it can be read against the matrices in
the config's remap_funcs_twp.py.

Identity kinematics leaves the frame unrotated, and so does tool kinematics:
there the world axes are the tool axes by construction, which is what makes a
G1 Z move run along the tool.

Checked against the forward transform of each module at 27 poses.  The
coefficients the forward applies to a displacement of the linear joints are
the table rotation alone, as they should be, since turning the head does not
move the tool tip when a linear joint moves.  Tool z, recovered separately as
the direction the tip retreats along when the tool gets longer, matches the
third column of the product.  For tool kinematics the same linear-joint
coefficients come out as the transpose of the whole chain including the
virtual rotation, which is the statement that the world frame is the tool
frame.  Agreement is to 3e-9 throughout.
The first module whose own maths is not in the convention, and so the first
real exercise of the declared rotation.

pumakins builds the ISO 9787 mechanical interface frame, whose z points
perpendicularly away from the flange, and it relies on that: it reaches the
tool tip by adding PUMA_D6 along the third column.  So it answers in its own
frame and declares TOOL_FRAME_FLANGE, and switchkins turns it into the
convention.  Nothing in the module itself flips a sign.

Lift the rotation out of the forward kinematics into pumaFlangeRotation()
rather than writing it twice, which is the whole point: a second copy of a
machine's geometry that has to be kept in step by hand is the thing this
work exists to remove.  The block moves verbatim and the forward kinematics
loses the locals that went with it.

At every joint zero the module's own frame is diag(1, -1, -1), a half turn
about x, so after the declared half turn it reports the identity: tool axis
[0, 0, 1], tool x [1, 0, 0].  A puma at zero and a vertical mill at zero give
the same answer, which is right, because both have the tool pointing down at
the work.
Pins down the property the chapter is about: relating one tool axis
convention to the other is a rotation, not a change of sign.  Checks that a
negated third column is refused because it is a reflection, that the declared
rotation post-multiplies so it is read in the module's own frame, that the
half turn keeps tool x and reverses the other two, and that applying it twice
is the identity.  Also checks the pumakins zero pose, whose own frame is a
half turn about x, ends up as the identity after the declaration it makes.

Verified by mutation rather than by passing: making TOOL_FRAME_FLANGE negate
only the tool axis fails nine checks, and reversing the multiplication order
fails four including the one written for it.

Built the way tests/blendmath builds, compiling the source under test
directly with the rest garbage-collected by the linker.
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.

1 participant