This paper describes how to derive the kinematic model for a 6-axis machine tool in an XYZABC configuration with Tool side A,B rotation of the spindle and work side C (table) rotation . In this example the B axis is a primary (rotating around the Y) and the A axis is the secondary (45° nutating) rotary axis. The primary being independent of the secondary axis. The model presented here will be named 'XYZABC-TRSRN'.
The method used here will be a step by step approach. Starting with a working kinematic model for a single rotary axis all the required elements will be added to build a complete kinematic model for the machine.
The final model includes tool-length compensation, compensation for mechanical offsets between the two rotational axis A and B and compensation for setups where the machine reference point is not located in the rotation-point of the C rotary table.
In this document only basic mathematical functions are used so the kinematic models derived can be used directly in the 'userkins.comp' template file provided with the LinuxCNC installation. All calculations can be done whithout the use of any computer algebra systems, however the use of computer assistance like 'sage' will make the process of matrix multiplication much less error prone.
Note that there are other and potentially more computationally efficient ways to build custom kinematics using built in libraries like 'posemath'. Posemath provides many functions for efficient matrix manipulation and also offers functions for the use of quaternions. However the use of such a library would require a more indepth understanding of the mathematical theory that is beyond the scope of this presentation. Furthermore importing a library like 'posemath' into the 'userkins.comp' template would require substantially more programming skills than using the method applied in this paper.
A custom kinematic model in LinuxCNC is used to calculate cartesian coordinates from given machine joint positions (forward kinematics) and also to calculate the required machine joint positions to reach a given coordinate position (inverse kinematics). In the following description we will use vectors as mathematical representations of the two positions:
Note that the fourth row is added to be able to multiply the vectors with a 4x4 transformation matrix.
For
the tool to follow a point on the work piece we need a model that
calculates where a given position on the work piece moves to when the
rotary joints are rotated. In our example configuration the work piece
will be mounted on the C rotary table and it is therefore here where we
start to build our forward kinematic model.
Note that in matrix multiplication the order is important that is is generally not equal to .
with and being the angle of rotation of joint C
To derive the coordinate position we now need to multiply the joint position vector with our forward transformation matrix .
Note that the input values to our model need to be on the right hand side of the matrix multiplication.
This shows the section of the TCP forward kinematics calculation in the file 'xyzab_tdr_kins.comp'. Note that P(px,py,pz) is equal to the joint position (j[0],j[1],j[2],) while is output to the coordinate position (pos->tran.x, pos->tran.y, pos->tran.z). The values 'cc', 'sc' are calculated and stored in the respective variables earlier in the component file.
case 1: // ========================= TCP kinematics FORWARD
px = j[0];
py = j[1];
pz = j[2];
pos->tran.x = cc*px - sc*py;
pos->tran.y = cc*py + sc*px;
pos->tran.z = pz;
pos->a = j[3];
pos->b = j[4];
pos->c = j[5];
break;
To calculate the joint position from given coordinate positions we need to 'unrotate' joint C. Mathematically this means we need to transpose the rotation part in our transformation matrix.
To derive the joint position we then multiply the coordinate position vector from the right:
This shows the section of the TCP inverse kinematics calculation in the file 'xyzab_tdr_kins.comp'. Note that is equal to the coordinate position (pos->tran.x, pos->tran.y, pos->tran.z) while is output to the joint position (j[0],j[1],j[2]). The values 'cc', 'sc' are calculated and stored in the respective variables earlier in the component file.
case 1: // ========================= TCP kinematics INVERSE
qx = pos->tran.x;
qy = pos->tran.y;
qz = pos->tran.z;
j[0] = cc*qx + sc*qy;
j[1] = cc*qy - sc*qx;
j[2] = qz;
j[3] = pos->a;
j[4] = pos->b;
j[5] = pos->c;
break;
Testing in LinuxCNC shows a working TCP kinematic for rotations around C
To add the B rotation we expand by multiplying first the tool-translation from the right and then the rotation matrix also from the right:
Note how the transformation matrix is constructed from left to right. The first operation is on the left and the last operation is on the right as we work our way from the work side to the spindle side of the kinematic chain.
with and being the angle of rotation of joint B
Note that the tool-position (ie the vector in the 4th column of our transformation matrix ) does not contain the B-rotation in any form. Only the tool-orientation (ie columns 1,2 and 3) is influenced by the addition of the rotation B. This may seem wrong but we have to remember that after the B-rotation () we have not yet built any offset (tool-length or pivot-length) into our model (ie there is no translation matrix on the right side of ). Hence for now a rotation around B simply means that a tool of lenght zero (ie a point) rotates with joint B and does not change it's position. So in the current form it is really not very interesting to test the effect of the added rotation around B so we will move on along the kinematic chain and add the geometric offsets () , the rotation A () and the pivot-lengths () to arrive at the spindle nose.
To get a better understanding of these offsets in the spindle rotary assembly of our example machine we need to have a look at how the rotary axes A and B are arranged in the spindle body. This shows our spindle assembly in its home position (, ). To get a clearer idea of the situation a tool (purple cylinder) is shown protruding from the spindle nose.
Because
the rotation axes A,B and offsets in question are all hidden inside the
spindle body we simplify the model to the relevant kinematic
components. The while cross with the arrow pointing up shows the
intersection of the rotary axes A and B (yellow sphere).
This point will be refered to as the 'pivot-point' of the spindle rotary
assembly.
The rotary axis B (yellow) extends horizontally from the pivot-point in
the machine-y direction.
The slanted rotary axis A (yellow) extends from the pivot-point to the
spindle nose where the tool (purple) attaches.
The 'y-pivot-length' is the distance in the y-direction between the
pivot-point and the spindle nose and shown in green.
The 'z-pivot-length' is the distance in the z-direction between the
pivot-point and the spindle nose and shown in blue.
Note that in this image there is no geometric offset between the two
rotary axes and they intersect at the pivot-point.
We define the values for the offsets in the example image as y-pivot = 200 and z-pivot = 200.
In our kinematic model this represents the situation where, starting
from the spindle nose, we need to travel 200 in the positive z-direction
and 200 in the positive y-direction to reach the pivot-point.
Note that the direction of travel when defining these offsets is
arbitrary so in our case the offset situation in the image could also be
defined as -200 in y and -200 in z. However once the definition is made
we must keep it throughout the entire process of building the kinematic
model.
To be able to add these (y,z)-pivot values to our kinematic model we need to create a transformation matrix that has the effect of a translation. Note that the direction chosen for these offsets is important here as our translation is basically a vector and we have chosen that this 'pivot-length' vector points from the spindle nose to the pivot-point. Since we are building the forward kinematic model we are travelling against this vector and thus its components () need to be entered in the negative.
The
rotational axes of a rotary assembly like the A/B spindle type
discussed here will always have an intended or unintented offset from
one rotational axis to the other. In our case this is an offset in the x
direction (red indicator) and in the z direction (light blue
indicator).
We define the values for the offsets in the example image as x-offset = -20 and z-offset = 40.
In our kinematic model this represents the situation where, starting
from the rotary A axis, we need to travel 40 in the positive z-direction
and 20 in the negative x-direction to reach the pivot-point.
Note that the direction of travel when defining these offsets is arbitrary so in our case the offset situation in the image could also be defined as +20 in x and -40 in z. However once the definition is made we must keep it throughout the entire process of building the kinematic model.
Also note that it might be tempting to simplify things by just adding the z-offset (light blue) to the z-pivot (dark blue). However if we consider the situation with a rotation in A then it's clear that the two values need to be handled sparately in our kinematic model.
To be able to add these (x,z)-offset values to our kinematic model we need to create a transformation matrix that has the effect of a translation. Note that the direction chosen for these offsets is important here as our translation is basically a vector and we have chosen that this 'offset' vector points from the A rotation axis to the pivot-point. Since we are building the forward kinematic model we are travelling against this vector and thus its components () need to be entered in the negative.
The machine in our example has a 'nutating' rotary joint A. Nutating meaning here that the rotational axis of A is not parallel to one of the axes (x, y or z) of our machine coordinate system and hence we cannot use any of the basic rotation matrices to model it in our kinematic. The basic rotation matrices are, as we will see, only three particular solutions of a general formula to describe rotations around any given vector ) in space. So to construct the rotation matrix for the slanted joint A of our machine we can use the ‘Rodrigues' rotation formula. (Note that there is also an 'Euler-Rodrigues' formula that can be used for the same purpose but uses different parameters.)
With:
For the matrix we need a unit vector that represents the rotational axis of the 45° joint:
with the components:
Using and , can thus be written as:
using and the substitution
becomes
and by expanding it to a 4x4 matrix we have now the required transformation matrix
To make the matrix multiplications more manageable we substitute
and get the transformation matrix in it's final form
As we could see above in our inspection of the spindle rotary assembly the tool length offset () has the same direction as the z-component of the pivot-offset () that is, a positive value points in the negative machine-z direction. So as a building block in our forward kinematic transformation the value of needs to be in the negative:
Now that we have all the building blocks we can put everything together:
So with this as our core forward transformation matrix we can now check the output of this model for the home position and
and taking our substitution in into account:
which for reduces to:
we get the coordinates:
To get the expected coordinate position we need to compensate for these offsets by subtracting them from the result of our core transformation matrix. Note subtracting a vector is the same as adding its inverse vector We define the transformation:
Note that this is a translation of the result of our forward transformation matrix it needs to be multiplied from the left:
Note that in the kinematic component is added to the z-pivot value Lz in the line
Lz = Lz + Dt;
case 1: // ========================= TCP kinematics FORWARD
Lz = Lz + Dt;
// onLy used to be consistent with math documentation
Px = j[0];
Py = j[1];
Pz = j[2];
pos->tran.x = - Cb*Cc*Dx - Cc*Dz*Sb
+ (Cb*Cc*t - Cc*Sb*v + Sc*u)*Ly
- (Cb*Cc*t + Cc*Sb*u - Sc*v)*Lz
+ Cc*Px - Py*Sc
+ Dx;
pos->tran.y = - Cb*Dx*Sc - Dz*Sb*Sc
+ (Cb*Sc*t - Sb*Sc*v - Cc*u)*Ly
- (Cb*Sc*t + Sb*Sc*u + Cc*v)*Lz
+ Cc*Py + Px*Sc
+ Ly;
pos->tran.z = - Cb*Dz
- (Sb*t + Cb*v)*Ly
+ (Sb*t - Cb*u)*Lz
+ Dx*Sb
+ Pz
+ Lz
+ Dz
;
pos->a = j[3];
pos->b = j[4];
pos->c = j[5];
break;
Up
to this point we have assumed that the machine reference point
coincides with the rotational axis of our rotary C table.
However, it is somewhat unlikely that a machines home position is
exactly in the rotational axis of the rotary table and this will need to
be taken into account in the kinematic model.
If we assume that we have a setup with no TLO (), no geometric offset (), no pivot-length () and no offset of the rotation-axis of the rotary C to the machine reference point.
A tool positioned in rotational axis of C would have a joint-position of and that would give the expected resulting coordinate position of .
If we now assume that the rotation-axis of our rotary C table is offset from the machine reference point by then our joint-position would be equal to which would give us a result of .
So we need to subtract the offset from the joint-position
before we input it into our transformation matrix. In other words we
need to translate the joint-position vector in the opposite direction
along the offset vector with the components .
Note that this is a translation of the input of our forward transformation matrix so it needs to be multiplied to from the right :
Thus we get:
However some more consideration is needed for now a joint position of will result in a coordinate position of
which is of course not the value we can hand back to LinuxCNC because
if the rotation axis is offset from machine home position then the
coordinate position would need to be .
So to be consistent we need to add the offset values back to the results
of our calculations which we do again by multiplying a vector
translation to the left of our forward kinematic:
Thus we get our final forward transformation matrix:
TCP kinematics FORWARD Qx = -Cb*Cc*Dx - Cc*Dz*Sb - Cc*(Drax - Px) - (Cb*Cc*t + Cc*Sb*u - Sc*v)*(Dt + Lz) + (Cb*Cc*t - Cc*Sb*v + Sc*u)*Ly + (Dray - Py)*Sc + Drax + Dx Qy = -Cb*Dx*Sc - Dz*Sb*Sc - Cc*(Dray - Py) - (Cb*Sc*t + Sb*Sc*u + Cc*v)*(Dt + Lz) + (Cb*Sc*t - Sb*Sc*v - Cc*u)*Ly - (Drax - Px)*Sc + Dray + Ly Qz = (Sb*t - Cb*u)*(Dt + Lz) - Cb*Dz - (Sb*t + Cb*v)*Ly + Dx*Sb + Dt + Dz + Lz + Pz
case 1: // ========================= TCP kinematics FORWARD
// onLy used to be consistent with math in documentation
Px = j[0];
Py = j[1];
Pz = j[2];
pos->tran.x = - Cb*Cc*Dx
- Cc*Dz*Sb
- Cc*(Drax - Px)
- (Cb*Cc*t + Cc*Sb*u - Sc*v)*(Dt + Lz)
+ (Cb*Cc*t - Cc*Sb*v + Sc*u)*Ly
+ (Dray - Py)*Sc
+ Drax
+ Dx;
pos->tran.y = - Cb*Dx*Sc
- Dz*Sb*Sc
- Cc*(Dray - Py)
- (Cb*Sc*t + Sb*Sc*u + Cc*v)*(Dt + Lz)
+ (Cb*Sc*t - Sb*Sc*v - Cc*u)*Ly
- (Drax - Px)*Sc
+ Dray
+ Ly
;
pos->tran.z = (Sb*t - Cb*u)*(Dt + Lz)
- Cb*Dz
- (Sb*t + Cb*v)*Ly
+ Dx*Sb
+ Dt
+ Dz
+ Lz
+ Pz;
pos->a = j[3];
pos->b = j[4];
pos->c = j[5];
break;
To calculate the joint position from a given coordinate position
we need to follow the kinematic chain in the opposite direction from
the spindle to work piece. We can invert our forward kinematic
transformation and build it backwards, using the inverted rotations and
the inverted translations.
Note that the input matrix with its translation {} for the offset of the rotation axis and the output translation need to be handled with some consideration:
In the inverse transformation the input is and it's 'offset' is the inverse of the 'output offset' of the forward transformation. Basically what we added to the result of the forward transformation needs to be removed from the input to the inverse transformation and vice versa. On the right side we additionally need to rotate the inverted spindle offsets by the rotation of the rotary C:
Note that the brackets in the above expressions are only used to highlight the different parts of the kinematic model and are not mathematically required.
This being the inverse transformation our input matrix has changed to :
TCP kinematics INVERSE Px = (Cc^2 + Sc^2)*Cb*Dx + (Cc^2 + Sc^2)*Dz*Sb - Cc*(Drax + Dx - Qx) + ((Cc^2 + Sc^2)*Cb*t + (Cc^2 + Sc^2)*Sb*u)*(Dt + Lz) - ((Cc^2 + Sc^2)*Cb*t - (Cc^2 + Sc^2)*Sb*v)*Ly - (Dray + Ly - Qy)*Sc + Drax Py = (Cc^2 + Sc^2)*Ly*u + (Cc^2 + Sc^2)*(Dt + Lz)*v - Cc*(Dray + Ly - Qy) + (Drax + Dx - Qx)*Sc + Dray Pz = -(Sb*t - Cb*u)*(Dt + Lz) + Cb*Dz + (Sb*t + Cb*v)*Ly - Dx*Sb - Dt - Dz - Lz + Qz
Note that
case 1: // ========================= TCP kinematics INVERSE
Qx = pos->tran.x;
Qy = pos->tran.y;
Qz = pos->tran.z;
j[0] = Cb*Dx
+ Dz*Sb
- Cc*(Drax + Dx - Qx)
+ (Cb*t + Sb*u)*(Dt + Lz)
- (Cb*t - Sb*v)*Ly
- (Dray + Ly - Qy)*Sc
+ Drax;
j[1] = Ly*u
+ (Dt + Lz)*v
- Cc*(Dray + Ly - Qy)
+ (Drax + Dx - Qx)*Sc
+ Dray;
j[2] = - (Sb*t - Cb*u)*(Dt + Lz)
+ Cb*Dz + (Sb*t + Cb*v)*Ly
- Dx*Sb
- Dt
- Dz
- Lz
+ Qz;
j[3] = pos->a;
j[4] = pos->b;
j[5] = pos->c;
break;
Also note that with this kinematic model the offset of the rotational axis of the rotary C is the vector going from the pivot-point of the spindle assembly to the rotatio-axis of C with the machine in the home position. In other words if the C-rotary-axis has the absolute machine coordinates then
In the kinematic comp this is handled in the variable declaration:
// geometric offsets of the universal spindle head as defined in
double Ly = *haldata->y_pivot;
double Lz = *haldata->z_pivot;
double Dx = *haldata->x_offset;
double Dz = *haldata->z_offset;
double Drax = *haldata->x_rot_axis - Dx;
double Dray = *haldata->y_rot_axis - Ly;
This concludes the TCP kinematic
Many,
if not most, applications for 5-axis milling do not require TCP
kinematics where all five axes are moving simultaneously but only need
the work piece to be oriented at certain angles to the tool in between
'conventional' three axis (x,y,z) milling operations. In these
operations the tool is not reoriented while cutting the material. This
is what is called '3+2' mode.
In 3+2 mode the machine operator can use the familiar built in cycles
the machine controller offers for 3d (x,y,z) use and does not
necessarily require CAM/CAD software to machine a part. The ability to
move the tool in a plane perpendicular to its rotational axis also
allows the use of probes for job setup.
Machines with work side rotation (eg the C rotary in our example, or the
'table-rotary-tilting' examples included in LinuxCNC simulation
configs) can orient the work piece to the tool by simply rotating the
work to the required orientation as the tool always remains oriented
along the machine z-axis. A drilling operation on such a machine will
thus still only require the machine z-axis to be moved no matter how the
part is oriented. In this case no special kinematic is required.
Machines with tool side rotation like the one presented here with A and B
spindle rotations however retain the directions of the unrotated
machine coordinate system when moving in IDENTITY and TCP kinematics
while the tool orientation changes in respect to the machine coordinate
system. A drilling operation on such a machine will require the machine
to move in a complex manner that may include all three (x,y,z) axes
depending on how tool is oriented.
Commercial 5-axis machine controllers offer built in functionality that
allow the operator to define work plane orientation using Gcode commands
like G68.2 or similar; automatically adjusting the kinematic model to
the type of kinematic of the machine. To implement such a feature for
our example machine using LinuxCNC we need to create another kind of
kinematic model which we will call the TOOL kinematic.
For the TOOL kinematic start at the tool tip and work towards the work piece omitting the C axis rotation. So in our example case our forward transformation matrix is :
Where is a virtual rotation around the rotational axis of the tool. This is required because we need a way to define the orientation of the tool-x (and -y). Without this the tool-coordinate system will be 'fixed' to the spindle head orientation which we do certainly want for the tool-z orientation but not for the x,y-directions. This will be important when developing the 'Tilted Work Plane' features later.
Tool-length offset is applied automatically in LinuxCNC by subtracting the tool length value stored in the tool table from the z-axis coordinate position while the joint position remains unchanged. This built in compensation also work in our custom tool kinematic because the tool coordinate system is always aligned with the rotational axis of the tool.
Note that the brackets in the above expressions are only used to highlight the different parts of the kinematic model and are not mathematically required.
TOOL kinematics FORWARD Qx = ((Ca*Ctc - Stc*t)*Cb - (Ctc*t - Stc*v)*Sb)*(Dx + Px) - (Ca*Ctc - Stc*t)*Dx - ((Ctc*t - Stc*v)*Cb + (Ca*Ctc - Stc*t)*Sb)*(Dz + Lz + Pz) + (Ctc*t - Stc*v)*Dz + (Ctc*t + Stc*u)*(Ly + Py) - Ly*Stc Qy = -((Ca*Stc + Ctc*t)*Cb - (Stc*t + Ctc*v)*Sb)*(Dx + Px) + (Ca*Stc + Ctc*t)*Dx + ((Stc*t + Ctc*v)*Cb + (Ca*Stc + Ctc*t)*Sb)*(Dz + Lz + Pz) - (Stc*t + Ctc*v)*Dz - (Stc*t - Ctc*u)*(Ly + Py) - Ctc*Ly Qz = (Cb*t + Sb*u)*(Dx + Px) - (Sb*t - Cb*u)*(Dz + Lz + Pz) - Dx*t - Dz*u + (Ly + Py)*v - Lz
In preparation for the 'Tilted work plane' (TWP) feature we introduce a custom offset Twp-(x,y,z).
This will be the offset from the current work offset (eg G54) to the
origin of the TWP as defined by the (X,Y,Z) words in the Gcode (eg
G68.2).
Example:
G68.2 X10 Y20 Z30 ... (the other words are not relevant here)
will define a TWP with an offset of (10,20,30) to the active work origin (0,0,0).
This custom offset can be built into our forward kinematic as a translation of the result of the forward transformation:
Which means simply adding a subtraction to the respective formula in our kinematic component:
case 3: // ========================= TOOL kinematics FORWARD
// onLy used to be consistent with math in documentation
Px = j[0];
Py = j[1];
Pz = j[2];
pos->tran.x = ((Ca*Ctc - Stc*t)*Cb
- (Ctc*t - Stc*v)*Sb)*(Dx + Px)
- (Ca*Ctc - Stc*t)*Dx
- ((Ctc*t - Stc*v)*Cb
+ (Ca*Ctc - Stc*t)*Sb)*(Dz + Lz + Pz)
+ (Ctc*t - Stc*v)*Dz
+ (Ctc*t + Stc*u)*(Ly + Py)
- Ly*Stc
- Twp_x;
pos->tran.y = - ((Ca*Stc + Ctc*t)*Cb - (Stc*t
+ Ctc*v)*Sb)*(Dx + Px)
+ (Ca*Stc + Ctc*t)*Dx
+ ((Stc*t + Ctc*v)*Cb + (Ca*Stc
+ Ctc*t)*Sb)*(Dz + Lz + Pz)
- (Stc*t + Ctc*v)*Dz
- (Stc*t - Ctc*u)*(Ly + Py)
- Ctc*Ly
- Twp_y;
pos->tran.z = (Cb*t + Sb*u)*(Dx + Px)
- (Sb*t - Cb*u)*(Dz + Lz + Pz)
- Dx*t
- Dz*u
+ (Ly + Py)*v
- Lz
- Twp_z;
pos->a = j[3];
pos->b = j[4];
pos->c = j[5];
break;
For the inverse kinematic we need to move from the machine coordinates to the tool coordinates starting with the inverted offset translations for the offsets we used on the input of the forward kinematic :
Note that the brackets in the above expressions are only used to highlight the different parts of the kinematic model and are not mathematically required.
TCP kinematics INVERSE Px = Cb*Dx - (Cb*t - Sb*v)*Ly + (Cb*t + Sb*u)*Lz + ((Ca*Cb - Sb*t)*Ctc - (Cb*t - Sb*v)*Stc)*Qx - ((Cb*t - Sb*v)*Ctc + (Ca*Cb - Sb*t)*Stc)*Qy + (Cb*t + Sb*u)*Qz + Dz*Sb - Dx Py = (Ctc*t + Stc*u)*Qx - (Stc*t - Ctc*u)*Qy + Ly*u + Lz*v + Qz*v - Ly Pz = Cb*Dz + (Sb*t + Cb*v)*Ly - (Sb*t - Cb*u)*Lz - ((Ca*Sb + Cb*t)*Ctc - (Sb*t + Cb*v)*Stc)*Qx + ((Sb*t + Cb*v)*Ctc + (Ca*Sb + Cb*t)*Stc)*Qy - (Sb*t - Cb*u)*Qz - Dx*Sb - Dz - Lz
The custom TWP-offset we built into our forward kinematic as a
translation of the result needs to be reflected in our inverse kinematic
by an inverse translation of the input:
In the kinematic component this is done in lines:
Qx = pos->tran.x + Twp_x;
Qy = pos->tran.y + Twp_y;
Qz = pos->tran.z + Twp_z;
case 3: // ========================= TOOL kinematics INVERSE
Qx = pos->tran.x + Twp_x;
Qy = pos->tran.y + Twp_y;
Qz = pos->tran.z + Twp_z;
j[0] = Cb*Dx
- (Cb*t - Sb*v)*Ly
+ (Cb*t + Sb*u)*Lz
+ ((Ca*Cb - Sb*t)*Ctc - (Cb*t - Sb*v)*Stc)*Qx
- ((Cb*t - Sb*v)*Ctc + (Ca*Cb - Sb*t)*Stc)*Qy
+ (Cb*t + Sb*u)*Qz + Dz*Sb - Dx
;
j[1] = (Ctc*t + Stc*u)*Qx
- (Stc*t - Ctc*u)*Qy
+ Ly*u
+ Lz*v
+ Qz*v
- Ly
;
j[2] = Cb*Dz
+ (Sb*t + Cb*v)*Ly
- (Sb*t - Cb*u)*Lz
- ((Ca*Sb + Cb*t)*Ctc - (Sb*t + Cb*v)*Stc)*Qx
+ ((Sb*t + Cb*v)*Ctc + (Ca*Sb + Cb*t)*Stc)*Qy
- (Sb*t - Cb*u)*Qz
- Dx*Sb
- Dz
- Lz
;
j[3] = pos->a;
j[4] = pos->b;
j[5] = pos->c;
break;
This completes the TOOL kinematic
Any machine operator using TOOL kinematics should be well aware of its behavior before issuing motion commands!
It must be stressed that, while TOOL kinematics are active, any movement
of a rotary joint will cause the machine to rotate the TCS around the
machine reference point. Because the magnitude of the resulting movement
increases with the distance between the tool position and the machine
reference point the effect may seem unpredictable to the inexperienced
operator.
Note here that it is possible to set the rotation point in TOOL
kinematics in much the same way as we offset the rotation-point from
machine zero in TCP kinematics. This however would further complicate
work offset transformation and there seems to be no immediate benefit to
it.
Commercial
5-axis machine controllers offer built in functionality that allow the
operator to define work plane orientation using Gcode commands like
G68.2 or similar. With the new custom TOOL kinematic we can now explore a
possible implementation of TWP in LinuxCNC.
For the purpose of this example we choose the already mentioned 'G68.2' and the associated Gcodes as used by Fanuc:
G68.4 - Same as 68.2 but as an incremental reorientation of an existing TWP
G53.1 - Orient the tool to the TWP using non-TCP joint rotation
G53.6 - Orient the tool to the TWP using TCP joint rotation
G69 - Cancel the TWP setting
The TWP feature always requires a TWP-definition (G68.x) before an orientation command (G53.x) can be issued.
G68.x commands do not cause any machine movement while G53 command will cause immediate machine movement.
At the end of a TWP operation a G69 command is used to return to machine coordinates.
In this presentation we use a 'Pure Python Remap' to make the above Gcode commands available to the machine operator. As a consequence our depth of integration is quite limited in the sense that the LinuxCNC Gcode interpreter will be totally ignorant of our 'TWP'-mode.
This should give a rough overview of how TWP functionality is to be achieved with a python remap:
The idea of TWP is to give the machine operator a mechanism to define
a virtual work plane that is rotated (and optionally offset) in respect
to the machine coordinate system. As mentioned above this is fairly
trivial in a machine with work side rotation as its tool spindle is
fixed to be aligned with the machine z-axis. In such a machine the tool
coordinate system (TCS) remains in the orientation of the machine
coordinate system (MCS)
In a machine with tool side rotation however the TCS rotates in respect
to the MCS as the rotary joints move. The orientation of the TCS for a
given joint rotation can be calculated using the rotational part of the
transformation matrix as derived above. Furthermore we can also solve
for the inverse case of finding the joint positions that will orient the
tool to a given orientation.
Note here that this is very much dependent on the specific kinematic of
the machine at hand and will require careful analysis of the kinematic
model to find any ambiguities in the solution as some specific tool
orientations might be achieved in multiple joint positions.
So to define the TWP means to define a target TCS in respect to the MCS and for this the use of a transformation matrix is well suited as it contains the rotation as well as the (optional) translation.
The TWP is defined by a rotation (I,J,K) and optional offset (X,Y,Z) of the TCS in respect to the MCS. The optional offset is calulated from the current work offset position at the time when the G68.2 or G68.3 command is issued.
The operator can choose from different methods to define the rotation of the custom work plane:
G68.2 ... P0 ... - 'True Euler'-angles (this is the default if the P word is omitted)
G68.2 ... P1 ... - 'Pitch-Roll-Yaw'-angles
G68.2 ... P2 ... - 3 points in the plane (3 points define two vectors)
G68.2 ... P3 ... - 2 vectors (tool-x and tool-z)
G68.2 ... P4 ... - projected angles (A around machine-x, B around machine-y)
For the above methods we create the transformation matrix either by using euler-rotations of the 4x4 identity matrix or by the vector information passed by the command using the cross product to calculate the y-vector. For the projected angles we use basich trigonometry to calculate the vector components. These calculations are independent from the specific machine kinematics.
Here we need to use the specific machine kinematic model to calculate the transformation matrix of the current TCS.
Here we need to multiply the current TWP transformation matrix with the one built from the command words.
Here we reset the TWP transformation matrix to the 4x4 identity matrix (ie no rotation, no translation).
Note that, contrary to some other controllers, moves commanded between G68.x and G53.x will be in the MCS.
Once the TWP has been defined the machine spindle can be oriented by moving the rotary joints to the appropriate positions.
The operator can choose whether the rotation is done in IDENTITY kinematics (only the rotary joints move) or in TCP kinematics where all joint may move to keep the tool center point in position:
G53.1 - orient the tool to the TWP without using TCP
G53.6 - orient the tool to the TWP with using TCP
The
TWP is defined relative to the work offset (eg G54) active when issuing
a G62.x command. With the execution of the following G53.x command and
the reorientation of the spindle the kinematic is switched to the TOOL
kinematics and the coordinate position in the DRO will then reflect the
coordinate position in the rotated TCS. If the work offset values were
to be used without adjusting for the kinematic switch then the physical
position of the work offset would be rotated out of place and the
reference to the work coordinate system (WCS) would be lost. So in order
to find the reference on the work piece in the TCS we need to use the
TWP transformation matrix to transform the work offset values set in WCS
to the new TCS.
Note that the original work offset will have to be restored when the TWP is canceled with a G69 command.