#include "kinematics.h"
#include "rtapi_math.h"
#ifndef __GNUC__
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif
#include "hal.h"
struct haldata {
hal_float_t *bx, *cx, *cy;
} *haldata = 0;
#define Bx (*(haldata->bx))
#define Cx (*(haldata->cx))
#define Cy (*(haldata->cy))
#define sq(x) ((x)*(x))
int kinematicsForward(const double * joints,
EmcPose * pos,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
#define AD (joints[0])
#define BD (joints[1])
#define CD (joints[2])
#define Dx (pos->tran.x)
#define Dy (pos->tran.y)
#define Dz (pos->tran.z)
double P, Q, R;
double s, t, u;
P = sq(AD);
Q = sq(BD) - sq(Bx);
R = sq(CD) - sq(Cx) - sq(Cy);
s = -2.0 * Bx;
t = -2.0 * Cx;
u = -2.0 * Cy;
if (s == 0.0) {
return -1;
}
Dx = (Q - P) / s;
if (u == 0.0) {
return -1;
}
Dy = (R - Q - (t - s) * Dx) / u;
Dz = P - sq(Dx) - sq(Dy);
if (Dz < 0.0) {
return -1;
}
Dz = sqrt(Dz);
if (*fflags) {
Dz = -Dz;
}
pos->a = 0.0;
pos->b = 0.0;
pos->c = 0.0;
return 0;
#undef AD
#undef BD
#undef CD
#undef Dx
#undef Dy
#undef Dz
}
int kinematicsInverse(const EmcPose * pos,
double * joints,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags)
{
#define AD (joints[0])
#define BD (joints[1])
#define CD (joints[2])
#define Dx (pos->tran.x)
#define Dy (pos->tran.y)
#define Dz (pos->tran.z)
AD = sqrt(sq(Dx) + sq(Dy) + sq(Dz));
BD = sqrt(sq(Dx - Bx) + sq(Dy) + sq(Dz));
CD = sqrt(sq(Dx - Cx) + sq(Dy - Cy) + sq(Dz));
*fflags = 0;
if (Dz < 0.0) {
*fflags = 1;
}
return 0;
#undef AD
#undef BD
#undef CD
#undef Dx
#undef Dy
#undef Dz
}
KINEMATICS_TYPE kinematicsType()
{
return KINEMATICS_BOTH;
}
#ifdef MAIN
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
#ifndef BUFFERLEN
#define BUFFERLEN 256
#endif
char buffer[BUFFERLEN];
char cmd[BUFFERLEN];
EmcPose pos, vel;
double joints[3], jointvels[3];
char inverse;
char flags;
KINEMATICS_FORWARD_FLAGS fflags;
inverse = 0;
flags = 0;
fflags = 0;
if (argc != 4 ||
1 != sscanf(argv[1], "%lf", &Bx) ||
1 != sscanf(argv[2], "%lf", &Cx) ||
1 != sscanf(argv[3], "%lf", &Cy)) {
fprintf(stderr, "syntax: %s Bx Cx Cy\n", argv[0]);
return 1;
}
while (! feof(stdin)) {
if (inverse) {
printf("inv> ");
}
else {
printf("fwd> ");
}
fflush(stdout);
if (NULL == fgets(buffer, BUFFERLEN, stdin)) {
break;
}
if (1 != sscanf(buffer, "%s", cmd)) {
continue;
}
if (! strcmp(cmd, "quit")) {
break;
}
if (! strcmp(cmd, "i")) {
inverse = 1;
continue;
}
if (! strcmp(cmd, "f")) {
inverse = 0;
continue;
}
if (! strcmp(cmd, "ff")) {
if (1 != sscanf(buffer, "%*s %d", &fflags)) {
printf("need forward flag\n");
}
continue;
}
if (inverse) {
if (3 != sscanf(buffer, "%lf %lf %lf",
&pos.tran.x,
&pos.tran.y,
&pos.tran.z)) {
printf("need X Y Z\n");
continue;
}
if (0 != kinematicsInverse(&pos, joints, NULL, &fflags)) {
printf("inverse kin error\n");
}
else {
printf("%f\t%f\t%f\n", joints[0], joints[1], joints[2]);
if (0 != kinematicsForward(joints, &pos, &fflags, NULL)) {
printf("forward kin error\n");
}
else {
printf("%f\t%f\t%f\n", pos.tran.x, pos.tran.y, pos.tran.z);
}
}
}
else {
if (flags) {
if (4 != sscanf(buffer, "%lf %lf %lf %d",
&joints[0],
&joints[1],
&joints[2],
&fflags)) {
printf("need 3 strut values and flag\n");
continue;
}
}
else {
if (3 != sscanf(buffer, "%lf %lf %lf",
&joints[0],
&joints[1],
&joints[2])) {
printf("need 3 strut values\n");
continue;
}
}
if (0 != kinematicsForward(joints, &pos, &fflags, NULL)) {
printf("forward kin error\n");
}
else {
printf("%f\t%f\t%f\n", pos.tran.x, pos.tran.y, pos.tran.z);
if (0 != kinematicsInverse(&pos, joints, NULL, &fflags)) {
printf("inverse kin error\n");
}
else {
printf("%f\t%f\t%f\n", joints[0], joints[1], joints[2]);
}
}
}
}
return 0;
}
#endif
#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
EXPORT_SYMBOL(kinematicsType);
EXPORT_SYMBOL(kinematicsForward);
EXPORT_SYMBOL(kinematicsInverse);
MODULE_LICENSE("GPL");
int comp_id;
int rtapi_app_main(void) {
int res = 0;
comp_id = hal_init("tripodkins");
if(comp_id < 0) return comp_id;
haldata = hal_malloc(sizeof(struct haldata));
if(!haldata) goto error;
if((res = hal_pin_float_new("tripodkins.Bx", HAL_IO, &(haldata->bx), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("tripodkins.Cx", HAL_IO, &(haldata->cx), comp_id)) < 0) goto error;
if((res = hal_pin_float_new("tripodkins.Cy", HAL_IO, &(haldata->cy), comp_id)) < 0) goto error;
Bx = Cx = Cy = 1.0;
hal_ready(comp_id);
return 0;
error:
hal_exit(comp_id);
return res;
}
void rtapi_app_exit(void) { hal_exit(comp_id); }