Skip to content

Commit c30de0c

Browse files
authored
Merge pull request #4546 from grandixximo/kins-fixes
kinematics: six fixes found by round-tripping every module
2 parents c6e0261 + 91dfff8 commit c30de0c

24 files changed

Lines changed: 746 additions & 58 deletions

src/emc/kinematics/maxkins.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,25 @@ int kinematicsForward(const double *joints,
5050
// B correction
5151
const double zb = (pivot_length + joints[8] + tool_length) * cos(d2r(joints[4]));
5252
const double xb = (pivot_length + joints[8] + tool_length) * sin(d2r(joints[4]));
53-
54-
// C correction
55-
const double xyr = hypot(joints[0], joints[1]);
56-
const double xytheta = atan2(joints[1], joints[0]) + d2r(joints[5]);
5753

5854
// U correction
5955
const double zv = joints[6] * sin(d2r(joints[4]));
6056
const double xv = joints[6] * cos(d2r(joints[4]));
6157

6258
// V correction is always in joint 1 only
6359

64-
pos->tran.x = xyr * cos(xytheta) - (con * xb) - xv;
65-
pos->tran.y = xyr * sin(xytheta) - joints[7];
60+
// B, U and V are all machine frame: the head hangs off the Z slide and
61+
// does not turn with the C table, so they apply before the rotation into
62+
// the workpiece frame rather than after it.
63+
const double mx = joints[0] - (con * xb) - xv;
64+
const double my = joints[1] - joints[7];
65+
66+
// C correction
67+
const double xyr = hypot(mx, my);
68+
const double xytheta = atan2(my, mx) + d2r(joints[5]);
69+
70+
pos->tran.x = xyr * cos(xytheta);
71+
pos->tran.y = xyr * sin(xytheta);
6672
pos->tran.z = joints[2] - zb - (con * zv) + pivot_length + tool_length;
6773

6874
pos->a = joints[3];
@@ -103,7 +109,7 @@ int kinematicsInverse(const EmcPose * pos,
103109

104110
joints[0] = xyr * cos(xytheta) + (con * xb) + xv;
105111
joints[1] = xyr * sin(xytheta) + pos->v;
106-
joints[2] = pos->tran.z + zb - (con * zv) - pivot_length - tool_length;
112+
joints[2] = pos->tran.z + zb + (con * zv) - pivot_length - tool_length;
107113

108114
joints[3] = pos->a;
109115
joints[4] = pos->b;

src/emc/kinematics/pumakins.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ struct haldata {
2929
hal_real_t a2, a3, d3, d4, d6;
3030
} *haldata = NULL;
3131

32+
/* the difference of two angles, brought into (-pi, pi] so that a joint a
33+
whole turn from the formula still matches it */
34+
static double angleDiff(double a, double b)
35+
{
36+
double d = a - b;
37+
while (d > PM_PI) { d -= 2*PM_PI; }
38+
while (d <= -PM_PI) { d += 2*PM_PI; }
39+
return d;
40+
}
41+
3242
/* The flange orientation for a joint set: the ISO 9787 mechanical interface
3343
frame, whose z points out of the interface towards the work. Shared by the
3444
forward kinematics and the tool frame so the two cannot drift apart. */
@@ -152,16 +162,16 @@ static int pumaKinematicsForward(const double * joint,
152162
*iflags = 0;
153163

154164
/* Set shoulder-up flag if necessary */
155-
if (fabs(joint[0]*PM_PI/180 - atan2(hom.tran.y, hom.tran.x) +
156-
atan2(PUMA_D3, -sqrt(sumSq))) < FLAG_FUZZ)
165+
if (fabs(angleDiff(joint[0]*PM_PI/180, atan2(hom.tran.y, hom.tran.x) -
166+
atan2(PUMA_D3, -sqrt(sumSq)))) < FLAG_FUZZ)
157167
{
158168
*iflags |= PUMA_SHOULDER_RIGHT;
159169
}
160170

161171
/* Set elbow down flag if necessary */
162-
if (fabs(joint[2]*PM_PI/180 - atan2(PUMA_A3, PUMA_D4) +
172+
if (fabs(angleDiff(joint[2]*PM_PI/180, atan2(PUMA_A3, PUMA_D4) -
163173
atan2(k, -sqrt(PUMA_A3 * PUMA_A3 +
164-
PUMA_D4 * PUMA_D4 - k * k))) < FLAG_FUZZ)
174+
PUMA_D4 * PUMA_D4 - k * k)))) < FLAG_FUZZ)
165175
{
166176
*iflags |= PUMA_ELBOW_DOWN;
167177
}
@@ -177,7 +187,7 @@ static int pumaKinematicsForward(const double * joint,
177187

178188
/* if not singular set wrist flip flag if necessary */
179189
else{
180-
if (! (fabs(joint[3]*PM_PI/180 - atan2(t1, t2)) < FLAG_FUZZ))
190+
if (! (fabs(angleDiff(joint[3]*PM_PI/180, atan2(t1, t2))) < FLAG_FUZZ))
181191
{
182192
*iflags |= PUMA_WRIST_FLIP;
183193
}

src/emc/kinematics/scarakins.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ int scaraKinematicsForward(const double * joint,
9696
z = D1 + D3 - joint[2] - D5;
9797
c = a3;
9898

99+
// the elbow flag: which sign the inverse gives the acos of joint 1
99100
*iflags = 0;
100-
if (joint[1] < 90)
101+
if (joint[1] < 0)
101102
*iflags = 1;
102103

103104
world->tran.x = x;

src/emc/kinematics/three21kins.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ struct haldata {
3232
hal_real_t a1, a2, a3, d1, d2, d3, d4, d6;
3333
} *haldata = NULL;
3434

35+
/* the difference of two angles, brought into (-pi, pi] so that a joint a
36+
whole turn from the formula still matches it */
37+
static double angleDiff(double a, double b)
38+
{
39+
double d = a - b;
40+
while (d > PM_PI) { d -= 2*PM_PI; }
41+
while (d <= -PM_PI) { d += 2*PM_PI; }
42+
return d;
43+
}
44+
3545
static int three21KinematicsForward(const double * joint,
3646
EmcPose * world,
3747
const KINEMATICS_FORWARD_FLAGS * fflags,
@@ -132,8 +142,8 @@ static int three21KinematicsForward(const double * joint,
132142
*iflags = 0;
133143

134144
/* set shoulder flag */
135-
if (fabs(joint[0]*PM_PI/180 - atan2(hom.tran.y, hom.tran.x) +
136-
atan2(d23, -sqrt(sumSq))) < FLAG_FUZZ)
145+
if (fabs(angleDiff(joint[0]*PM_PI/180, atan2(hom.tran.y, hom.tran.x) -
146+
atan2(d23, -sqrt(sumSq)))) < FLAG_FUZZ)
137147
{
138148
*iflags |= THREE21_SHOULDER_RIGHT;
139149
}
@@ -143,8 +153,8 @@ static int three21KinematicsForward(const double * joint,
143153
if (discr < 0.0) {
144154
discr = 0.0;
145155
}
146-
if (fabs(joint[2]*PM_PI/180 - atan2(a3, d4) +
147-
atan2(k, -sqrt(discr))) < FLAG_FUZZ)
156+
if (fabs(angleDiff(joint[2]*PM_PI/180, atan2(a3, d4) -
157+
atan2(k, -sqrt(discr)))) < FLAG_FUZZ)
148158
{
149159
*iflags |= THREE21_ELBOW_DOWN;
150160
}
@@ -158,7 +168,7 @@ static int three21KinematicsForward(const double * joint,
158168
}
159169
else
160170
{
161-
if (! (fabs(joint[3]*PM_PI/180 - atan2(t1, t2)) < FLAG_FUZZ))
171+
if (! (fabs(angleDiff(joint[3]*PM_PI/180, atan2(t1, t2))) < FLAG_FUZZ))
162172
{
163173
*iflags |= THREE21_WRIST_FLIP;
164174
}

src/emc/kinematics/trtfuncs.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,14 @@ int xyzbcKinematicsInverse(const EmcPose * pos,
362362
const double dz = hal_get_real(haldata->z_offset) + dt;
363363
const double b_rad = pos->b*TO_RAD;
364364
const double c_rad = pos->c*TO_RAD;
365-
const double dpx = -cos(b_rad)*dx + sin(b_rad)*dz + dx;
366-
const double dpz = -sin(b_rad)*dx - cos(b_rad)*dz + dz;
367365

368366
rtapi_real con = hal_get_bool(haldata->conventional_directions) ? 1.0 : -1.0;
369367

368+
// the offsets seen from the tilted table: the same rotation the
369+
// forward applies to them, in the same sense
370+
const double dpx = -cos(b_rad)*dx + con * sin(b_rad)*dz + dx;
371+
const double dpz = -con * sin(b_rad)*dx - cos(b_rad)*dz + dz;
372+
370373
EmcPose P; // computed position
371374

372375
P.tran.x = + cos(c_rad) * cos(b_rad) * (pos->tran.x - x_rot_point)

src/emc/motion/control.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,6 @@ static void handle_kinematicsSwitch(void) {
363363
return; // the kinematics in force is unchanged
364364
}
365365

366-
switchkins_type = requested_type;
367-
hal_set_real(emcmot_hal_data->kins_type, (double)switchkins_type);
368-
emcmotStatus->switchkins_type = switchkins_type;
369-
370366
KINEMATICS_FORWARD_FLAGS tmpFFlags = fflags;
371367
KINEMATICS_INVERSE_FLAGS tmpIFlags = iflags;
372368
#ifdef SWITCHKINS_DEBUG
@@ -376,15 +372,25 @@ static void handle_kinematicsSwitch(void) {
376372
beforePose[anum] = *pcmd_p[anum];
377373
}
378374
#endif
375+
/* the joints stay where they are, so a kinematics whose forward cannot
376+
solve them is one the machine cannot run in from here: put the old
377+
one back, or the inverse would run the joints to wherever the pose
378+
we know lands in the new one */
379379
EmcPose poseKinsSwitch = emcmotStatus->carte_pos_cmd;
380380
if (kinematicsForward(joint_posKinsSwitch, &poseKinsSwitch,
381381
&tmpFFlags, &tmpIFlags)) {
382-
reportError(_("kinematicsForward failed for kinematics type %d"),
383-
switchkins_type);
382+
kinematicsSwitch(switchkins_type);
383+
reportError(_("kinematicsForward failed for kinematics type %d,"
384+
" type %d is still in force"),
385+
requested_type, switchkins_type);
384386
SET_MOTION_ERROR_FLAG(1); // abort
385-
return; // keep the position we know rather than an unsolved one
387+
return; // the kinematics in force and the position are unchanged
386388
}
387389
emcmotStatus->carte_pos_cmd = poseKinsSwitch;
390+
391+
switchkins_type = requested_type;
392+
hal_set_real(emcmot_hal_data->kins_type, (double)switchkins_type);
393+
emcmotStatus->switchkins_type = switchkins_type;
388394
#ifdef SWITCHKINS_DEBUG
389395
fprintf(stderr,"kswitch type=%d (%s:%d)\n",switchkins_type,__FUNCTION__,__LINE__);
390396
for (anum = 0; anum < EMCMOT_MAX_AXIS; anum++) {

src/hal/components/matrixkins.comp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ the adjustment values should be added to the old values instead of replacing the
176176
""";
177177
see_also "kins(9)";
178178
pin out bool dummy=1; // halcompile requires at least one pin
179+
option extra_setup;
179180
license "GPL";
180181
;;
181182

@@ -191,15 +192,15 @@ static struct haldata {
191192
hal_real_t C_zz;
192193
} *haldata;
193194

194-
static int matrixkins_setup(void) {
195+
EXTRA_SETUP() {
196+
(void)__comp_inst;
197+
(void)prefix;
198+
(void)extra_arg;
195199
int res=0;
196200

197201
// inherit comp_id from rtapi_main()
198202
if (comp_id < 0) goto error;
199203

200-
res = hal_set_unready(comp_id);
201-
if (res) goto error;
202-
203204
haldata = hal_malloc(sizeof(struct haldata));
204205
if (!haldata) goto error;
205206

@@ -215,9 +216,6 @@ static int matrixkins_setup(void) {
215216

216217
if (res) goto error;
217218

218-
res = hal_ready(comp_id);
219-
if (res) goto error;
220-
221219
rtapi_print("*** %s setup ok\n",__FILE__);
222220
return 0;
223221
error:
@@ -235,8 +233,6 @@ EXPORT_SYMBOL(kinematicsForward);
235233

236234
KINEMATICS_TYPE kinematicsType()
237235
{
238-
static bool is_setup=0;
239-
if (!is_setup) matrixkins_setup();
240236
return KINEMATICS_BOTH;
241237
}
242238

src/hal/components/millturn.comp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ chapter (docs/src/motion/switchkins.txt)
2727

2828
""";
2929
// The fpin pin is not accessible in kinematics functions.
30-
// Use the *_setup() function for pins and params used by kinematics.
30+
// Use EXTRA_SETUP() for pins and params used by kinematics.
3131
pin out si32 fpin=0"pin to demonstrate use of a conventional (non-kinematics) function fdemo";
3232
option period no;
33+
option extra_setup;
3334
function fdemo;
3435
license "GPL";
3536
author "David Mueller";
@@ -59,14 +60,15 @@ FUNCTION(fdemo) {
5960
fpin_set(fpin + 1);
6061
}
6162

62-
static int millturn_setup(void) {
63+
EXTRA_SETUP() {
64+
(void)__comp_inst;
65+
(void)prefix;
66+
(void)extra_arg;
6367
#define HAL_PREFIX "millturn"
6468
int res=0;
6569

6670
// inherit comp_id from rtapi_main()
6771
if (comp_id < 0) goto error;
68-
// set unready to allow creation of pins
69-
if (hal_set_unready(comp_id)) goto error;
7072

7173
haldata = hal_malloc(sizeof(*haldata));
7274
if (!haldata) goto error;
@@ -85,7 +87,6 @@ static int millturn_setup(void) {
8587
res += hal_pin_new_bool(comp_id, HAL_OUT, &haldata->kinstype_is_1, 0, "kinstype.is-1");
8688

8789
if (res) goto error;
88-
hal_ready(comp_id);
8990
rtapi_print("*** %s setup ok\n",__FILE__);
9091
return 0;
9192
error:
@@ -142,8 +143,6 @@ int kinematicsSwitch(int new_switchkins_type)
142143

143144
KINEMATICS_TYPE kinematicsType()
144145
{
145-
static bool is_setup=0;
146-
if (!is_setup) millturn_setup();
147146
return KINEMATICS_BOTH; // set as required
148147
// Note: If kinematics are identity, using KINEMATICS_BOTH
149148
// may be used in order to allow a gui to display

src/hal/components/userkins.comp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,16 @@ change all instances of `userkins` to `mykins`.
5353
* The *fpin* pin is included to satisfy the requirements of the halcompile
5454
utility but it is not accessible to kinematics functions.
5555
* HAL pins and parameters needed in kinematics functions (kinematicsForward(),
56-
kinematicsInverse()) must be setup in a function (*userkins_setup()*) invoked
57-
by the initial motion module call to kinematicsType().
56+
kinematicsInverse()) must be setup in the *EXTRA_SETUP()* function, which
57+
halcompile runs once when the module is loaded, before the component is
58+
made ready.
5859

5960
""";
6061
// The fpin pin is not accessible in kinematics functions.
61-
// Use the *_setup() function for pins and params used by kinematics.
62+
// Use EXTRA_SETUP() for pins and params used by kinematics.
6263
pin out si32 fpin=0"pin to demonstrate use of a conventional (non-kinematics) function fdemo";
6364
option period no;
65+
option extra_setup;
6466
function fdemo;
6567
license "GPL";
6668
author "Dewey Garrett";
@@ -91,14 +93,15 @@ FUNCTION(fdemo) {
9193
fpin_set(fpin + 1);
9294
}
9395

94-
static int userkins_setup(void) {
96+
EXTRA_SETUP() {
97+
(void)__comp_inst;
98+
(void)prefix;
99+
(void)extra_arg;
95100
#define HAL_PREFIX "userkins"
96101
int res=0;
97102

98103
// inherit comp_id from rtapi_main()
99104
if (comp_id < 0) goto error;
100-
// set unready to allow creation of pins
101-
if (hal_set_unready(comp_id)) goto error;
102105

103106
haldata = hal_malloc(sizeof(struct haldata));
104107
if (!haldata) goto error;
@@ -112,7 +115,6 @@ static int userkins_setup(void) {
112115
res += hal_param_new_real(comp_id, HAL_RO, &haldata->param_ro, 0.0, "%s.param-ro", HAL_PREFIX);
113116

114117
if (res) goto error;
115-
hal_ready(comp_id);
116118
rtapi_print("*** %s setup ok\n",__FILE__);
117119
return 0;
118120
error:
@@ -130,8 +132,6 @@ EXPORT_SYMBOL(kinematicsForward);
130132

131133
KINEMATICS_TYPE kinematicsType()
132134
{
133-
static bool is_setup=0;
134-
if (!is_setup) userkins_setup();
135135
return KINEMATICS_IDENTITY; // set as required
136136
// Note: If kinematics are identity, using KINEMATICS_BOTH
137137
// may be used in order to allow a gui to display

src/hal/components/xyzab_tdr_kins.comp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ chapter (docs/src/motion/switchkins.txt)
3131
""";
3232

3333
pin out si32 dummy=0"one pin needed to satisfy halcompile requirement";
34+
option extra_setup;
3435

3536
license "GPL";
3637
author "David Mueller";
@@ -54,13 +55,14 @@ static struct haldata {
5455
hal_bool_t kinstype_is_1;
5556
} *haldata;
5657

57-
static int xyzab_tdr_setup(void) {
58+
EXTRA_SETUP() {
59+
(void)__comp_inst;
60+
(void)prefix;
61+
(void)extra_arg;
5862
#define HAL_PREFIX "xyzab_tdr_kins"
5963
int res=0;
6064
// inherit comp_id from rtapi_main()
6165
if (comp_id < 0) goto error;
62-
// set unready to allow creation of pins
63-
if (hal_set_unready(comp_id)) goto error;
6466

6567
haldata = hal_malloc(sizeof(*haldata));
6668
if (!haldata) goto error;
@@ -80,7 +82,6 @@ static int xyzab_tdr_setup(void) {
8082
res += hal_pin_new_bool(comp_id, HAL_OUT, &haldata->kinstype_is_1, 0, "kinstype.is-1");
8183

8284
if (res) goto error;
83-
hal_ready(comp_id);
8485
rtapi_print("*** %s setup ok\n",__FILE__);
8586
return 0;
8687
error:
@@ -137,8 +138,6 @@ int kinematicsSwitch(int new_switchkins_type)
137138

138139
KINEMATICS_TYPE kinematicsType()
139140
{
140-
static bool is_setup=0;
141-
if (!is_setup) xyzab_tdr_setup();
142141
return KINEMATICS_BOTH; // set as required
143142
// Note: If kinematics are identity, using KINEMATICS_BOTH
144143
// may be used in order to allow a gui to display

0 commit comments

Comments
 (0)