#include "rtapi_math.h"
#include "posemath.h"
#include "pumakins.h"
#include "kinematics.h"
#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
struct haldata {
hal_float_t *a2, *a3, *d3, *d4, *d6;
} *haldata = 0;
#define PUMA_A2 (*(haldata->a2))
#define PUMA_A3 (*(haldata->a3))
#define PUMA_D3 (*(haldata->d3))
#define PUMA_D4 (*(haldata->d4))
#define PUMA_D6 (*(haldata->d6))
int kinematicsForward(const double * joint,
EmcPose * world,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
double s1, s2, s3, s4, s5, s6;
double c1, c2, c3, c4, c5, c6;
double s23;
double c23;
double t1, t2, t3, t4, t5;
double sumSq, k;
PmHomogeneous hom;
PmPose worldPose;
PmRpy rpy;
s1 = sin(joint[0]*PM_PI/180);
s2 = sin(joint[1]*PM_PI/180);
s3 = sin(joint[2]*PM_PI/180);
s4 = sin(joint[3]*PM_PI/180);
s5 = sin(joint[4]*PM_PI/180);
s6 = sin(joint[5]*PM_PI/180);
c1 = cos(joint[0]*PM_PI/180);
c2 = cos(joint[1]*PM_PI/180);
c3 = cos(joint[2]*PM_PI/180);
c4 = cos(joint[3]*PM_PI/180);
c5 = cos(joint[4]*PM_PI/180);
c6 = cos(joint[5]*PM_PI/180);
s23 = c2 * s3 + s2 * c3;
c23 = c2 * c3 - s2 * s3;
t1 = c4 * c5 * c6 - s4 * s6;
t2 = s23 * s5 * c6;
t3 = s4 * c5 * c6 + c4 * s6;
t4 = c23 * t1 - t2;
t5 = c23 * s5 * c6;
hom.rot.x.x = c1 * t4 + s1 * t3;
hom.rot.x.y = s1 * t4 - c1 * t3;
hom.rot.x.z = -s23 * t1 - t5;
t1 = -c4 * c5 * s6 - s4 * c6;
t2 = s23 * s5 * s6;
t3 = c4 * c6 - s4 * c5 * s6;
t4 = c23 * t1 + t2;
t5 = c23 * s5 * s6;
hom.rot.y.x = c1 * t4 + s1 * t3;
hom.rot.y.y = s1 * t4 - c1 * t3;
hom.rot.y.z = -s23 * t1 + t5;
t1 = c23 * c4 * s5 + s23 * c5;
hom.rot.z.x = -c1 * t1 - s1 * s4 * s5;
hom.rot.z.y = -s1 * t1 + c1 * s4 * s5;
hom.rot.z.z = s23 * c4 * s5 - c23 * c5;
t1 = PUMA_A2 * c2 + PUMA_A3 * c23 - PUMA_D4 * s23;
hom.tran.x = c1 * t1 - PUMA_D3 * s1;
hom.tran.y = s1 * t1 + PUMA_D3 * c1;
hom.tran.z = -PUMA_A3 * s23 - PUMA_A2 * s2 - PUMA_D4 * c23;
sumSq = hom.tran.x * hom.tran.x + hom.tran.y * hom.tran.y -
PUMA_D3 * PUMA_D3;
k = (sumSq + hom.tran.z * hom.tran.z - PUMA_A2 * PUMA_A2 -
PUMA_A3 * PUMA_A3 - PUMA_D4 * PUMA_D4) /
(2.0 * PUMA_A2);
*iflags = 0;
if (fabs(joint[0]*PM_PI/180 - atan2(hom.tran.y, hom.tran.x) +
atan2(PUMA_D3, -sqrt(sumSq))) < FLAG_FUZZ)
{
*iflags |= PUMA_SHOULDER_RIGHT;
}
if (fabs(joint[2]*PM_PI/180 - atan2(PUMA_A3, PUMA_D4) +
atan2(k, -sqrt(PUMA_A3 * PUMA_A3 +
PUMA_D4 * PUMA_D4 - k * k))) < FLAG_FUZZ)
{
*iflags |= PUMA_ELBOW_DOWN;
}
t1 = -hom.rot.z.x * s1 + hom.rot.z.y * c1;
t2 = -hom.rot.z.x * c1 * c23 - hom.rot.z.y * s1 * c23 +
hom.rot.z.z * s23;
if (fabs(t1) < SINGULAR_FUZZ && fabs(t2) < SINGULAR_FUZZ)
{
*iflags |= PUMA_SINGULAR;
}
else{
if (! (fabs(joint[3]*PM_PI/180 - atan2(t1, t2)) < FLAG_FUZZ))
{
*iflags |= PUMA_WRIST_FLIP;
}
}
hom.tran.x = hom.tran.x + hom.rot.z.x*PUMA_D6;
hom.tran.y = hom.tran.y + hom.rot.z.y*PUMA_D6;
hom.tran.z = hom.tran.z + hom.rot.z.z*PUMA_D6;
pmHomPoseConvert(&hom, &worldPose);
pmQuatRpyConvert(&worldPose.rot,&rpy);
world->tran = worldPose.tran;
world->a = rpy.r * 180.0/PM_PI;
world->b = rpy.p * 180.0/PM_PI;
world->c = rpy.y * 180.0/PM_PI;
return 0;
}
int kinematicsInverse(const EmcPose * world,
double * joint,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags)
{
PmHomogeneous hom;
PmPose worldPose;
PmRpy rpy;
double t1, t2, t3;
double k;
double sumSq;
double th1;
double th3;
double th23;
double th2;
double th4;
double th5;
double th6;
double s1, c1;
double s3, c3;
double s23, c23;
double s4, c4;
double s5, c5;
double s6, c6;
double px, py, pz;
*fflags = 0;
worldPose.tran = world->tran;
rpy.r = world->a*PM_PI/180.0;
rpy.p = world->b*PM_PI/180.0;
rpy.y = world->c*PM_PI/180.0;
pmRpyQuatConvert(&rpy,&worldPose.rot);
pmPoseHomConvert(&worldPose, &hom);
px = hom.tran.x - PUMA_D6*hom.rot.z.x;
py = hom.tran.y - PUMA_D6*hom.rot.z.y;
pz = hom.tran.z - PUMA_D6*hom.rot.z.z;
sumSq = px * px + py * py -
PUMA_D3 * PUMA_D3;
if (*iflags & PUMA_SHOULDER_RIGHT){
th1 = atan2(py, px) - atan2(PUMA_D3, -sqrt(sumSq));
}
else{
th1 = atan2(py, px) - atan2(PUMA_D3, sqrt(sumSq));
}
s1 = sin(th1);
c1 = cos(th1);
k = (sumSq + pz * pz - PUMA_A2 * PUMA_A2 -
PUMA_A3 * PUMA_A3 - PUMA_D4 * PUMA_D4) / (2.0 * PUMA_A2);
if (*iflags & PUMA_ELBOW_DOWN){
th3 = atan2(PUMA_A3, PUMA_D4) - atan2(k, -sqrt(PUMA_A3 * PUMA_A3 + PUMA_D4 * PUMA_D4 - k * k));
}
else{
th3 = atan2(PUMA_A3, PUMA_D4) -
atan2(k, sqrt(PUMA_A3 * PUMA_A3 + PUMA_D4 * PUMA_D4 - k * k));
}
s3 = sin(th3);
c3 = cos(th3);
t1 = (-PUMA_A3 - PUMA_A2 * c3) * pz +
(c1 * px + s1 * py) * (PUMA_A2 * s3 - PUMA_D4);
t2 = (PUMA_A2 * s3 - PUMA_D4) * pz +
(PUMA_A3 + PUMA_A2 * c3) * (c1 * px + s1 * py);
t3 = pz * pz + (c1 * px + s1 * py) *
(c1 * px + s1 * py);
th23 = atan2(t1, t2);
th2 = th23 - th3;
s23 = t1 / t3;
c23 = t2 / t3;
t1 = -hom.rot.z.x * s1 + hom.rot.z.y * c1;
t2 = -hom.rot.z.x * c1 * c23 - hom.rot.z.y * s1 * c23 + hom.rot.z.z * s23;
if (fabs(t1) < SINGULAR_FUZZ && fabs(t2) < SINGULAR_FUZZ){
*fflags |= PUMA_REACH;
th4 = joint[3]*PM_PI/180;
}
else{
th4 = atan2(t1, t2);
}
s4 = sin(th4);
c4 = cos(th4);
s5 = hom.rot.z.z * (s23 * c4) -
hom.rot.z.x * (c1 * c23 * c4 + s1 * s4) -
hom.rot.z.y * (s1 * c23 * c4 - c1 * s4);
c5 =-hom.rot.z.x * (c1 * s23) - hom.rot.z.y *
(s1 * s23) - hom.rot.z.z * c23;
th5 = atan2(s5, c5);
s6 = hom.rot.x.z * (s23 * s4) - hom.rot.x.x *
(c1 * c23 * s4 - s1 * c4) - hom.rot.x.y *
(s1 * c23 * s4 + c1 * c4);
c6 = hom.rot.x.x * ((c1 * c23 * c4 + s1 * s4) *
c5 - c1 * s23 * s5) + hom.rot.x.y *
((s1 * c23 * c4 - c1 * s4) * c5 - s1 * s23 * s5) -
hom.rot.x.z * (s23 * c4 * c5 + c23 * s5);
th6 = atan2(s6, c6);
if (*iflags & PUMA_WRIST_FLIP){
th4 = th4 + PM_PI;
th5 = -th5;
th6 = th6 + PM_PI;
}
joint[0] = th1*180/PM_PI;
joint[1] = th2*180/PM_PI;
joint[2] = th3*180/PM_PI;
joint[3] = th4*180/PM_PI;
joint[4] = th5*180/PM_PI;
joint[5] = th6*180/PM_PI;
return 0;
}
int kinematicsHome(EmcPose * world,
double * joint,
KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
return kinematicsForward(joint, world, fflags, iflags);
}
KINEMATICS_TYPE kinematicsType()
{
return KINEMATICS_BOTH;
}
EXPORT_SYMBOL(kinematicsType);
EXPORT_SYMBOL(kinematicsForward);
EXPORT_SYMBOL(kinematicsInverse);
int comp_id;
int rtapi_app_main(void) {
int res=0;
comp_id = hal_init("pumakins");
if (comp_id < 0) return comp_id;
haldata = hal_malloc(sizeof(struct haldata));
if (!haldata) goto error;
if((res = hal_pin_float_new("pumakins.A2", HAL_IO, &(haldata->a2), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("pumakins.A3", HAL_IO, &(haldata->a3), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("pumakins.D3", HAL_IO, &(haldata->d3), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("pumakins.D4", HAL_IO, &(haldata->d4), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("pumakins.D6", HAL_IO, &(haldata->d6), comp_id)) < 0) goto error;
PUMA_A2 = DEFAULT_PUMA560_A2;
PUMA_A3 = DEFAULT_PUMA560_A3;
PUMA_D3 = DEFAULT_PUMA560_D3;
PUMA_D4 = DEFAULT_PUMA560_D4;
PUMA_D6 = DEFAULT_PUMA560_D6;
hal_ready(comp_id);
return 0;
error:
hal_exit(comp_id);
return res;
}
void rtapi_app_exit(void) { hal_exit(comp_id); }