LinuxCNC Documentation
This page is 10% translated. Untranslated text is shown in English.

1. Introducción

A number of kinematics modules support the switching of kinematics calculations. These modules support a default kinematics method (type0), a second built-in method (type1), and (optionally) a user-provided kinematics method (type2). Identity kinematics are typically used for the type1 method.

The switchkins functionality can be used for machines where post-homing joint control is needed during setup or to avoid movement near singularities from G-code. Such machines use specific kinematics calculations for most operations but can be switched to identity kinematics for control of individual joints after homing.

The kinematics type is selected with G12.1 P- and G13.1, from a G-code program or by interactive MDI commands. Buttons on a virtual panel (PyVCP, GladeVCP, etc.) or on hardware controls select a kinematics type through the halui provisions for activating MDI commands.

Changing the kinematics type requires the interpreter and motion parts of LinuxCNC to be synchronized, which G12.1 and G13.1 do themselves.

A deprecated HAL pin, motion.switchkins-type, selects a kinematics type as well. It is described under Usage below, because existing configurations use it.

2. Switchable Kinematic Modules

The following kinematics modules support switchable kinematics:

  1. xyzac-trt-kins (type0:xyzac-trt-kins type1:identity)

  2. xyzbc-trt-kins (type0:xyzbc-trt-kins type1:identity)

  3. genhexkins (type0:genhexkins type1:identity)

  4. genserkins (type0:genserkins type1:identity) (puma560 example)

  5. pumakins (type0:pumakins type1:identity)

  6. three21kins (type0:three21kins type1:identity)

  7. scarakins (type0:scarakins type1:identity)

  8. 5axiskins (type0:5axiskins type1:identity) (bridgemill)

Every module listed above uses its own kinematics for type0 and identity kinematics for type1. Each accepts the module string parameter sparm to swap the two, so that the machine starts in identity kinematics and the module kinematics are selected on demand:

[KINS]
KINEMATICS = xyzac-trt-kins sparm=identityfirst
# ...

Starting in identity kinematics leaves a way out of poses the module kinematics cannot solve. A module kinematics failure (near a singularity, for instance) reports an error and disables the machine; type0 is then reached without running the failing kinematics again.

Note
The sparm setting exchanges type0 and type1, so any G-code or HAL logic that selects a kinematics type by number must match.

Kinematics that solve the forward direction iteratively, genhexkins among them, need a pose to start from. While another type is running they take the estimate the caller supplies, which motion seeds from the [TRAJ]HOME world home, so they are ready to be switched to.

2.1. Identity letter assignments

When using an identity kinematics type, the module parameter coordinates can be used to assign letters to joints in arbitrary order from the set of allowed coordinate letters. Examples:

[KINS]
JOINTS = 6

# conventional identity ordering: joint0==x, joint1==y, ...
KINEMATICS = genhexkins coordinates=xyzabc

# custom identity ordering: joint0==c, joint1==b, ...
# KINEMATICS = genhexkins coordinates=cbazyx
Note
If the coordinates= parameter is omitted, the default joint-letter identity assignments are joint0==x,joint1=y,…​

The joint assignments provided for identity kinematics when using the coordinates parameter are identical to those provided for the trivkins module. However, duplication of axis letters to assign multiple joints for a coordinate letter is not generally applicable for serial or parallel kinematics (like genserkins, pumakins, genhexkins, etc.) where there is no simple relationship between joints and coordinates.

Duplication of axis coordinate letters is supported in the kinematics modules xyzac-trt-kins, xyzbc-trt-kins, and 5axiskins (bridgemill). Typical applications for duplicate coordinates are gantry machines where two motors (joints) are used for the transverse axis.

2.2. Backwards compatibility

Switchable kinematics initialize with motion.switchkins-type==0 implementing their eponymous kinematics method. If the the motion.switchkins-type pin is not connected — as in legacy configurations — only the default kinematics type is available.

3. Pines HAL

Kinematics switching is controlled by the motion module input HAL pin motion.switchkins-type. The floating point pin value is truncated to integer and used to select one of the provided kinematics types. The zero startup value selects the type0 default kinematics type.

Note
The motion.switchkins-type input pin is floating point in order to facilitate connections to motion module output pins like motion.analog-out-0n that are controllable by standard M-codes (typically M68EnL0).

Output HAL pins are provided to inform GUIs of the current kinematics type. These pins can also be connected to digital inputs that are read by G-code programs to enable or disable program behavior in accordance with the active kinematics type.

3.1. HAL Pin Summary

  1. motion.switchkins-type Input (float)

  2. motion.kins-type Output (float)

  3. kinstype.is-0 Output (bit)

  4. kinstype.is-1 Output (bit)

  5. kinstype.is-2 Output (bit)

A module providing more than three kinematics types has one kinstype.is-N pin per type.

4. Utilización

4.1. Conexiones HAL

G12.1 and G13.1 ask motion for a kinstype directly and need no HAL connection at all.

A kinstype can also be selected by writing the pin motion.switchkins-type, which is sourced from an analog output pin like motion.analog-out-03 so that it can be set by M68 commands:

net :kinstype-select <= motion.analog-out-03
net :kinstype-select => motion.switchkins-type
Warning
Selecting the kinstype from HAL is deprecated and motion says so, once, the first time the pin is used to change it. The interpreter does not see the pin, so a program is read, its limits checked and its path looked ahead in whatever kinematics the interpreter last knew about, which is not necessarily the one that will run it. Use G12.1 and G13.1. The pin is in a grace period: it keeps working for now, but is meant to be removed in the future.

4.2. G-code commands

G12.1 P- selects a kinstype and G13.1 cancels back to identity kinematics. Which kinstype is identity is declared by the module (see Code Notes), not fixed to a number:

...
G12.1 P1  ;select kinstype 1
...
...       ;user G-code
...
G13.1     ;back to identity kinematics
...

These codes ask motion for the kinstype directly and synchronize task and motion themselves, so no HAL connection and no separate sync command are needed. The G-code words and the motion.switchkins-type pin are both acted on when they change, so whichever asked most recently is the one in force. motion.kins-type reports what is currently selected.

The pin is deprecated, see the warning under HAL Connections.

The kinstype in force is readable in G-code as #<_kins_type>, which lets a subroutine restore whatever its caller had selected:

#<saved> = #<_kins_type>
G12.1 P2
( ... )
G12.1 P#<saved>

Selection is not cancelled by the end of a program or by an abort, so that the kinstype continues to match the position readout. A program that should leave the machine in identity kinematics ends with G13.1.

A module that declares no identity kinstype refuses G13.1 with an error and can still be driven by number with G12.1; see Code Notes for how a module declares its types.

See the G-code documentation for G12.1 and G13.1 for the full description.

4.3. M-code commands

Warning
This is the deprecated route described under HAL Connections above. It is documented because existing configurations use it. New ones should use G12.1 and G13.1.

Writing motion.switchkins-type through an analog output pin needs the HAL connection shown above. Kinstype selection is then managed using G-code sequences like:

...
M68 E3 Q1 ;update analog-out-03 to select kinstype 1
M66 E0 L0 ;sync interp-motion
...
...       ;user G-code
...
M68 E3 Q0 ;update analog-out-03 to select kinstype 0
M66 E0 L0 ;sync interp-motion
...
Note
An M66 wait-on-input command updates the #5399 variable. If the current value of this variable is needed for subsequent purposes, it should be copied to an additional variable before invoking M66.

These G-code command sequences are typically implemented in G-code subroutines as remapped M-codes or with conventional M-code scripts.

Suggested codes (as used in sim configs) are:

Códigos M de usuario convencionales:

  1. M128 Select kinstype 0 (startup default kinematics)

  2. M129 Select kinstype 1 (typically identity kinematics)

  3. M130 Select kinstype 2 (user-provided kinematics)

Códigos M remapeados:

  1. M428 Select kinstype 0 (startup default kinematics)

  2. M429 Select kinstype 1 (typically identity kinematics)

  3. M430 Select kinstype 2 (user-provided kinematics)

Note
Conventional user M-codes (in the range M100-M199) are in modal group 10. Remapped M-codes (in the range M200 to M999) can specify a modalgroup. See the remap documentation for additional information.

4.4. INI file limit settings

LinuxCNC trajectory planning uses limits for position (min,max), velocity, and acceleration for each applicable coordinate letter specified in the configuration INI file. Example for letter L (in the set XYZABCUVW):

[AXIS_L]
MIN_LIMIT =
MAX_LIMIT =
MAX_VELOCITY =
MIN_ACCELERATION =

The INI file limits specified apply to the type 0 default kinematics type that is activated at startup. These limits may not be applicable when switching to alternative kinematics. However, since an interpreter-motion synchronization is required when switching kinematics, INI-HAL pins can be used to setup limits for a pending kinematics type.

Note
INI-HAL pins are typically not recognized during a G-code program unless a synchronization (queue-buster) command is issued. See the milltask manpage for more information ($ man milltask).

The relevant INI-HAL pins for a joint number (N) are:

ini.N.min_limit
ini.N.max_limit
ini.N.max_acceleration
ini.N.max_velocity

The relevant INI-HAL pins for an axis coordinate (L) are:

ini.L.min_limit
ini.L.max_limit
ini.L.max_velocity
ini.L.max_acceleration
Note
In general, there are no fixed mappings between joint numbers and axis coordinate letters. There may be specific mappings for some kinematics modules especially those that implement identity kinematics (trivkins). See the kins man page for more information ($ man kins).

A user-provided M-code can alter any or all of the axis coordinate limits prior to changing the motion.switchkins-type pin and synchronizing the interpreter and motionparts of LinuxCNC. As an example, a bash script invoking halcmd can be hardcoded to set any number of HAL pins:

#!/bin/bash
halcmd -f <<EOF
setp ini.x.min_limit -100
setp ini.x.max_limit  100
# ... repeat for other limit parameters
EOF

Scripts like this can be invoked as a user M-code and used prior to the kins switching M-code that updates the motion.switchkins-type HAL pin and forces an interp-motion sync. Typically, separate scripts would be used for each kinstype (0,1,2).

When identity kinematics are provided as a means to control individual joints, it may be convenient to set or restore limits as specified in the system INI file. For example, a robot starts with a complex (non-identity) kinematics (type0) after homing. The system is configured so that it can be switched to identity kinematics (type1) in order to manipulate individual joints using the conventional letters from the set XYZABCUVW. The INI file settings ([AXIS_L]) are not applicable when operating with identity (type1) kinematics. To address this use case, the user M-code scripts can be designed as follows:

M129 (Switch to identity type1)

  1. read and parse INI file

  2. HAL: setp the INI-HAL limit pins for each axis letter ([AXIS_L]) according to the identity-referenced joint number INI file setting ([JOINT_N])

  3. HAL: setp motion.switchkins-type 1

  4. MDI: execute a syncing G-code (M66E0L0)

M128 (restore robot default kinematics type 0)

  1. read and parse INI file

  2. HAL: setp the INI-HAL limit pins for each axis letter ([AXIS_L]) according to the appropriate INI file setting ([AXIS_L])

  3. HAL: setp motion.switchkins-type 0

  4. MDI: execute a syncing G-code (M66E0L0)

Note
The vismach simulation configurations for a puma robot demonstrate M-code scripts (M128,M129,M130) for this example use case.

4.5. Consideraciones de offsets del sistema de coordenadas

Like INI file limit settings, coordinate system offsets (G92, G10L2, G10L20, G43, etc) are generally applicable only for the type 0 default startup kinematics type. When switching kinematics types, it may be important to either reset all offsets prior to switching or update offsets based on system-specific requirements.

4.6. External offset considerations

External offsets (set to an axis (L) via axis.L.eoffset-request) are preserved during kinematics switches. When an offset is active on an axis before the switch (visible in axis.L.eoffset), the trajectory planner maintains that same offset after the switch, similar to how it maintains the commanded position from a G-code. This ensures consistent machine behavior regardless of the active kinematics.

If maintaining the offset will be an issue due to axis limit changes or other concerns, be sure to clear and possibly disable the eoffset before making a kinematics switch.

5. Simulation configs

Simulation configs (requiring no hardware) are provided with illustrative vismach displays in subdirectories of configs/sim/axis/vismach/ .

  1. 5axis/table-rotary-tilting/xyzac-trt.ini (xyzac-trt-kins)

  2. 5axis/table-rotary-tilting/xyzbc-trt.ini (xyzac-trt-kins)

  3. 5axis/bridgemill/5axis.ini (5axiskins)

  4. scara/scara.ini (scarakins)

  5. puma/puma560.ini (genserkins)

  6. puma/puma.ini (pumakins)

  7. hexapod-sim/hexapod.ini (genhexkins)

6. User kinematics provisions

Custom kinematics can be coded and tested on Run-In-Place (RIP) builds. A template file src/emc/kinematics/userkfuncs.c is provided in the distribution. This file can be copied/renamed to a user directory and edited to supply custom kinematics with kinstype==2.

The user custom kinematics file can be compiled from out-of-tree source locations for rt-preempt implementations or by replacing the in-tree template file (src/emc/kinematics/userkfuncs.c) for rtai systems.

Preempt-rt make example:

$ userkfuncs=/home/myname/kins/mykins.c make && sudo make setuid

7. Warnings

Unexpected behavior can result if a G-code program is inadvertently started with an incompatible kinematics type. Unwanted behavior can be circumvented in G-code programs by:

  1. Connecting appropriate kinstype.is.N HAL pins to digital input pins (like motion.digital-in-0m).

  2. Reading the digital input pin (M66 E0 Pm) at the start of the G-code program

  3. Aborting (M2) the G-code program with a message (DEBUG, problem_message) if the kinstype is not suitable.

When using jogging facilities or MDI commands interactively, operator caution is required. Guis should include indicators to display the current kinematics type.

Note
Switching kinematics can cause substantial operational changes requiring careful design, testing, and training for deployment. The management of coordinate offsets, tool compensation, and INI file limits may require complicated and non-standard operating protocols.

8. Notas sobre el código

Kinematic modules providing switchkins functionality are linked to the switchkins.o object (switchkins.c) that provides the module main program (rtapi_app_main()) and related functions. This main program reads (optional) module command-line parameters (coordinates, sparm) and passes them to the module-provided function switchkinsSetup().

The switchkinsSetup() function identifies kinstype-specific setup routines and the functions for forward an inverse calculation for each kinstype (0,1,2) and sets a number of configuration settings.

A module can provide further kinstypes by calling switchkinsRegister() from within switchkinsSetup(), once per kinstype:

int switchkinsRegister(int ktype, KS kset, KF kfwd, KI kinv);

ktype runs from 0 to SWITCHKINS_MAX_TYPES-1 (defined in kinematics.h). A kinstype has to come from one route or the other, so registering one that switchkinsSetup() has already filled in is an error, and so is leaving a gap below the highest kinstype provided. Either mistake fails the module load and says which kinstype is at fault.

Each kinstype gets its own kinstype.is-N pin, so a module providing the usual three keeps the pin names it always had.

A module should also declare what each kinstype IS, again from within switchkinsSetup():

int switchkinsDeclare(int ktype, int flags);

with flags from kinematics.h:

  1. KINSTYPE_IDENTITY no transform: the joints are the world

  2. KINSTYPE_PRIMARY the module’s working transform

G-code reads these declarations: G13.1 cancels to the kinstype declared KINSTYPE_IDENTITY, whatever its number, so a module whose identity kinematics is not kinstype 0 still gets a working G13.1. At most one kinstype may be declared identity, and declaring a kinstype the module does not provide fails the module load. A module that declares nothing keeps working exactly as before for G12.1 P-, but G13.1 is an error, since the number of the identity kinematics is then a guess.

After calling switchkinsSetup(), rtapi_app_main() checks the supplied parameters, creates a HAL component, and then invokes the setup routine identified for each kinstype.

Each kinstype setup routine can (optionally) create HAL pins and set them to default values. A setup routine is called once per kinstype it is registered for, so a routine used for two kinstypes must not create the same pin twice. When all setup routines finish, rtapi_app_main() issues hal_ready() for the component to complete creation of the module.

8.1. Outline

The two routes in one switchkinsSetup(), with the kinematics itself left out. Types 0 to 2 are filled in through the pointer arguments as they always were, and a fourth is registered:

int switchkinsSetup(kparms* kp,
                    KS* kset0, KS* kset1, KS* kset2,
                    KF* kfwd0, KF* kfwd1, KF* kfwd2,
                    KI* kinv0, KI* kinv1, KI* kinv2
                   )
{
    kp->kinsname             = "mykins"; // must agree with the filename
    kp->halprefix            = "mykins"; // hal pin names
    kp->required_coordinates = "xyzab";
    kp->max_joints           = strlen(kp->required_coordinates);
    // remaining kparms fields

    *kset0 = identityKinematicsSetup;    // kinstype 0 is the startup default
    *kfwd0 = identityKinematicsForward;
    *kinv0 = identityKinematicsInverse;

    *kset1 = myKinematicsSetup;
    *kfwd1 = myKinematicsForward;
    *kinv1 = myKinematicsInverse;

    *kset2 = userkKinematicsSetup;
    *kfwd2 = userkKinematicsForward;
    *kinv2 = userkKinematicsInverse;

    // any further kinstype comes from switchkinsRegister(), and the
    // numbering carries on from the three above with no gaps
    if (switchkinsRegister(3, myOtherKinematicsSetup,
                              myOtherKinematicsForward,
                              myOtherKinematicsInverse)) { return -1; }

    return 0;
} // switchkinsSetup()

A module wanting fewer than three kinstypes leaves the unused pointer arguments alone and starts registering at the first free number.

For the surrounding shape, the in-tree switchkinsSetup() routines are in src/emc/kinematics: 5axiskins.c, xyzac-trt-kins.c, genserkins.c, scarakins.c and the others listed at the top of this document. None of them registers a fourth kinstype yet, so the call above has no in-tree example to copy.