按推荐建议,继续执行

结论:已将 LinuxCNC 5axiskins 及 switchkins 相关源码纳入 vendored manifest、native probe 和文档验证链,完整 native 验证通过。
This commit is contained in:
2026-06-07 19:08:40 +08:00
parent 55f6659993
commit 1b2f95b3d1
15 changed files with 1129 additions and 10 deletions

View File

@@ -0,0 +1,272 @@
/********************************************************************
* Description: 5axiskins.c
* kinematics for XYZBC 5 axis bridge mill
*
* Derived from a work by Fred Proctor & Will Shackleford
*
* Author:
* License: GPL Version 2
* System: Linux
*
* Copyright (c) 2007 Chris Radek
*
* Notes:
* 1) pivot_length hal pin must agree with mechanical
* design (including vismach simulation) and augmented
* with current tool z offset
* (typ: mechanical_pivot_length + motion.tooloffset.z)
* 2) C axis: spherical coordinates aziumthal angle (t or theta)
* projection of radius to xy plane
* 3) B axis: spherical coordinates polar angle (p or phi)
* wrt z axis
* 4) W axis: tool motion. Negative values increase tool radial
* motion example: drilling into body at b,c angles
* 5) W axis motion is incorporated into the motion of the
* joints used for X,Y,Z positioning and no motor or
* hal pin connections are required for the joint specified
* as JW. However, a joint must be configured for W to
* support display of the W axis letter value for
* complicated reasons. (motion/control.c computes joint
* positions only for the number of configured kinematic
* joints (NO_OF_KINS_JOINTS) and the joint positions
* are needed to display axis letters via inverse
* kinematics.
* 6) If no coordinates module parameter is supplied, kins
* will use the required coordinates XYZBCW mapped
* to joints 0..5 in sequence.
* 7) Multiple joints may be assigned to an axis letter
* with the module coordinates parameter
* 8) If a coordinates module parameter is supplied,
* the kins will map coordinate letters in sequence
* to joint numbers beginning with joint 0.
* 9) Coordinates XYZBCW are required, AUV may be used
* if specified with the coordinates parameter and will
* be mapped one-to-one with the assigned joint.
* 10) The direction of the tilt axis is the opposite of the
* conventional axis direction. See
* https://linuxcnc.org/docs/html/gcode/machining-center.html
********************************************************************/
// non-required coordinates (A,U,V) can be set by using
// the module coordinates parameter
#define REQUIRED_COORDINATES "XYZBCW"
#define DEFAULT_PIVOT_LENGTH 250
#include <rtapi.h>
#include <rtapi_math.h>
#include <rtapi_string.h>
#include <rtapi_ctype.h>
#include <hal.h>
#include <emcmotcfg.h>
#include <kinematics.h>
#include "switchkins.h"
struct haldata {
hal_float_t *pivot_length;
} *haldata;
static int fiveaxis_max_joints;
static PmCartesian s2r(double r, double t, double p) {
// s2r: spherical coordinates to cartesian coordinates
// r = length of vector
// p=phi = angle of vector wrt z axis
// t=theta = angle of vector projected onto xy plane
// (projection length in xy plane is r*sin(p)
PmCartesian c;
t = TO_RAD*t; p = TO_RAD*p; // degrees to radians
c.x = r * sin(p) * cos(t);
c.y = r * sin(p) * sin(t);
c.z = r * cos(p);
return c;
} //s2r()
// assignments of principal joints to axis letters:
// (-1 means not defined (yet))
static int JX = -1;
static int JY = -1;
static int JZ = -1;
static int JA = -1;
static int JB = -1;
static int JC = -1;
static int JU = -1;
static int JV = -1;
static int JW = -1;
static int fiveaxis_KinematicsForward(const double *joints,
EmcPose * pos,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
(void)fflags;
(void)iflags;
PmCartesian r = s2r(*(haldata->pivot_length) + joints[JW],
joints[JC],
180.0 - joints[JB]);
// Note: 'principal' joints are used
pos->tran.x = joints[JX] + r.x;
pos->tran.y = joints[JY] + r.y;
pos->tran.z = joints[JZ] + *(haldata->pivot_length) + r.z;
pos->b = joints[JB];
pos->c = joints[JC];
pos->w = joints[JW];
// optional letters (specify with coordinates module parameter)
pos->a = (JA != -1)? joints[JA] : 0;
pos->u = (JU != -1)? joints[JU] : 0;
pos->v = (JV != -1)? joints[JV] : 0;
return 0;
} //fiveaxis_KinematicsForward()
static int fiveaxis_KinematicsInverse(const EmcPose * pos,
double *joints,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags)
{
(void)iflags;
(void)fflags;
PmCartesian r = s2r(*(haldata->pivot_length) + pos->w,
pos->c,
180.0 - pos->b);
EmcPose P; // computed position
P.tran.x = pos->tran.x - r.x;
P.tran.y = pos->tran.y - r.y;
P.tran.z = pos->tran.z - *(haldata->pivot_length) - r.z;
P.b = pos->b;
P.c = pos->c;
P.w = pos->w;
// optional letters (specify with coordinates module parameter)
P.a = (JA != -1)? pos->a : 0;
P.u = (JU != -1)? pos->u : 0;
P.v = (JV != -1)? pos->v : 0;
// update joints with support for
// multiple-joints per-coordinate letter:
// based on computed position
position_to_mapped_joints(fiveaxis_max_joints,
&P,
joints);
return 0;
} // fiveaxis_kinematicsInverse()
int fiveaxis_KinematicsSetup(const int comp_id,
const char* coordinates,
kparms* kp)
{
int result=0;
int i,jno;
int axis_idx_for_jno[EMCMOT_MAX_JOINTS];
int minjoints = strlen(kp->required_coordinates);
fiveaxis_max_joints = strlen(coordinates); // allow for dup coords
if (fiveaxis_max_joints > kp->max_joints) {
rtapi_print_msg(RTAPI_MSG_ERR,
"ERROR %s: coordinates=%s requires %d joints, max joints=%d\n",
kp->kinsname,
coordinates,
fiveaxis_max_joints,
kp->max_joints);
goto error;
}
if (map_coordinates_to_jnumbers(coordinates,
kp->max_joints,
kp->allow_duplicates,
axis_idx_for_jno)) {
goto error;
}
// require all chars in reqd_coordinates (order doesn't matter)
for (i=0; i < minjoints; i++) {
char reqd_char;
reqd_char = *(kp->required_coordinates + i);
if ( !strchr(coordinates,toupper(reqd_char))
&& !strchr(coordinates,tolower(reqd_char)) ) {
rtapi_print_msg(RTAPI_MSG_ERR,
"ERROR %s:\nrequired coordinates:%s\n"
"specified coordinates:%s\n",
kp->kinsname, kp->required_coordinates, coordinates);
goto error;
}
}
// assign principal joint numbers (first found in coordinates map)
// duplicates are handled by position_to_mapped_joints()
for (jno=0; jno<EMCMOT_MAX_JOINTS; jno++) {
if (axis_idx_for_jno[jno] == 0) {if (JX == -1) JX=jno;}
if (axis_idx_for_jno[jno] == 1) {if (JY == -1) JY=jno;}
if (axis_idx_for_jno[jno] == 2) {if (JZ == -1) JZ=jno;}
if (axis_idx_for_jno[jno] == 3) {if (JA == -1) JA=jno;}
if (axis_idx_for_jno[jno] == 4) {if (JB == -1) JB=jno;}
if (axis_idx_for_jno[jno] == 5) {if (JC == -1) JC=jno;}
if (axis_idx_for_jno[jno] == 6) {if (JU == -1) JU=jno;}
if (axis_idx_for_jno[jno] == 7) {if (JV == -1) JV=jno;}
if (axis_idx_for_jno[jno] == 8) {if (JW == -1) JW=jno;}
}
haldata = hal_malloc(sizeof(struct haldata));
result = hal_pin_float_newf(HAL_IN,&(haldata->pivot_length),comp_id,
"%s.pivot-length",kp->halprefix);
if(result < 0) goto error;
*haldata->pivot_length = DEFAULT_PIVOT_LENGTH;
rtapi_print("Kinematics Module %s\n",__FILE__);
rtapi_print(" module name = %s\n"
" coordinates = %s Requires: [KINS]JOINTS>=%d\n"
" sparm = %s\n",
kp->kinsname,
coordinates,fiveaxis_max_joints,
kp->sparm?kp->sparm:"NOTSPECIFIED");
rtapi_print(" default pivot-length = %.3f\n",*haldata->pivot_length);
return 0;
error:
return -1;
} // fiveaxis_KinematicsSetup()
int switchkinsSetup(kparms* kp,
KS* kset0, KS* kset1, KS* kset2,
KF* kfwd0, KF* kfwd1, KF* kfwd2,
KI* kinv0, KI* kinv1, KI* kinv2
)
{
kp->kinsname = "5axiskins"; // !!! must agree with filename
kp->halprefix = "5axiskins"; // hal pin names
kp->required_coordinates = REQUIRED_COORDINATES;
kp->allow_duplicates = 1;
kp->max_joints = EMCMOT_MAX_JOINTS;
if (kp->sparm && strstr(kp->sparm,"identityfirst")) {
rtapi_print("\n!!! switchkins-type 0 is IDENTITY\n");
*kset0 = identityKinematicsSetup;
*kfwd0 = identityKinematicsForward;
*kinv0 = identityKinematicsInverse;
*kset1 = fiveaxis_KinematicsSetup;
*kfwd1 = fiveaxis_KinematicsForward;
*kinv1 = fiveaxis_KinematicsInverse;
} else {
rtapi_print("\n!!! switchkins-type 0 is %s\n",kp->kinsname);
*kset0 = fiveaxis_KinematicsSetup;
*kfwd0 = fiveaxis_KinematicsForward;
*kinv0 = fiveaxis_KinematicsInverse;
*kset1 = identityKinematicsSetup;
*kfwd1 = identityKinematicsForward;
*kinv1 = identityKinematicsInverse;
}
*kset2 = userkKinematicsSetup;
*kfwd2 = userkKinematicsForward;
*kinv2 = userkKinematicsInverse;
return 0;
} // switchkinsSetup()

View File

@@ -0,0 +1,342 @@
/*
Copyright 2019 Dewey Garrett <dgarrett@panix.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* switchkins.c provide functions for switchable kins modules:
* rtapi_app()
* rtapi_exit()
* kinematicsType()
* kinematicsForward()
* kinematicsInverse()
* kinematicsSwitch()
* kinematicsSwitchable()
* Using modules must supply function: switchkinsSetup()
*/
#include <rtapi.h>
#include <rtapi_app.h>
#include <hal.h>
#include <emcmotcfg.h>
#include <kinematics.h>
#include "switchkins.h"
//*********************************************************************
// kinematic functions (default=0 for err detection):
static kparms kp; // kinematics parms (common all types)
static KF kfwd0 = 0; // 0==switchkins_type kinematics forward
static KF kfwd1 = 0; // 1
static KF kfwd2 = 0; // 2
static KI kinv0 = 0; // 0==switchkins_type kinematics inverse
static KI kinv1 = 0; // 1
static KI kinv2 = 0; // 2
static hal_u32_t switchkins_type;
static struct swdata {
hal_bit_t *kinstype_is_0;
hal_bit_t *kinstype_is_1;
hal_bit_t *kinstype_is_2;
hal_float_t *gui_x;
hal_float_t *gui_y;
hal_float_t *gui_z;
hal_float_t *gui_a;
hal_float_t *gui_b;
hal_float_t *gui_c;
} *swdata;
// Note: parallel kinematics (like genhexkins) often
// use iterative method for Forward algorithm
// and require an initial EmcPose.
// If fwd_iterates_mask is set
// then save/use the lastpose
static int fwd_iterates[SWITCHKINS_MAX_TYPES] = {0};
static bool use_lastpose[SWITCHKINS_MAX_TYPES] = {0};
static EmcPose lastpose[SWITCHKINS_MAX_TYPES];
static void save_lastpose(int ktype, EmcPose* pos)
{
lastpose[ktype].tran.x = pos->tran.x;
lastpose[ktype].tran.y = pos->tran.y;
lastpose[ktype].tran.z = pos->tran.z;
lastpose[ktype].a = pos->a;
lastpose[ktype].b = pos->b;
lastpose[ktype].c = pos->c;
lastpose[ktype].u = pos->u;
lastpose[ktype].v = pos->v;
lastpose[ktype].w = pos->w;
} // save_lastpose()
static void get_lastpose(int ktype, EmcPose* pos)
{
pos->tran.x = lastpose[ktype].tran.x;
pos->tran.y = lastpose[ktype].tran.y;
pos->tran.z = lastpose[ktype].tran.z;
pos->a = lastpose[ktype].a;
pos->b = lastpose[ktype].b;
pos->c = lastpose[ktype].c;
pos->u = lastpose[ktype].u;
pos->v = lastpose[ktype].v;
pos->w = lastpose[ktype].w;
} // get_lastpose()
static int gui_forward_kins(const double *joints)
{
// the hexapod vismach gui uses these hal pins to
// display platform position/orientation in both
// genhexkins and identity kinematic types
// (similar needs for many parallel kinemtic machines)
int res;
KINEMATICS_FORWARD_FLAGS fflags = 0;
KINEMATICS_INVERSE_FLAGS iflags;
switch (kp.gui_kinstype) {
case 0: res = kfwd0(joints, &lastpose[0], &fflags, &iflags);break;
case 1: res = kfwd1(joints, &lastpose[1], &fflags, &iflags);break;
case 2: res = kfwd2(joints, &lastpose[2], &fflags, &iflags);break;
default: rtapi_print_msg(RTAPI_MSG_ERR,
"gui_forward_kins BAD gui_kinstype <%d>\n",
kp.gui_kinstype);
return -1;
}
*swdata->gui_x = lastpose[kp.gui_kinstype].tran.x;
*swdata->gui_y = lastpose[kp.gui_kinstype].tran.y;
*swdata->gui_z = lastpose[kp.gui_kinstype].tran.z;
*swdata->gui_a = lastpose[kp.gui_kinstype].a;
*swdata->gui_b = lastpose[kp.gui_kinstype].b;
*swdata->gui_c = lastpose[kp.gui_kinstype].c;
return res;
} // gui_forward_kins
//*********************************************************************
int kinematicsSwitchable() {return 1;}
int kinematicsSwitch(int new_switchkins_type)
{
int k;
for (k=0; k< SWITCHKINS_MAX_TYPES; k++) { use_lastpose[k] = 0;}
switchkins_type = new_switchkins_type;
switch (switchkins_type) {
case 0: rtapi_print_msg(RTAPI_MSG_INFO,
"kinematicsSwitch:TYPE0\n");
*swdata->kinstype_is_0 = 1;
*swdata->kinstype_is_1 = 0;
*swdata->kinstype_is_2 = 0;
break;
case 1: rtapi_print_msg(RTAPI_MSG_INFO,
"kinematicsSwitch:TYPE1\n");
*swdata->kinstype_is_0 = 0;
*swdata->kinstype_is_1 = 1;
*swdata->kinstype_is_2 = 0;
break;
case 2: rtapi_print_msg(RTAPI_MSG_INFO,
"kinematicsSwitch:TYPE2\n");
*swdata->kinstype_is_0 = 0;
*swdata->kinstype_is_1 = 0;
*swdata->kinstype_is_2 = 1;
break;
default: rtapi_print_msg(RTAPI_MSG_ERR,
"kinematicsSwitch:BAD VALUE <%d>\n",
switchkins_type);
*swdata->kinstype_is_1 = 0;
*swdata->kinstype_is_0 = 0;
*swdata->kinstype_is_2 = 0;
return -1; // FAIL
}
if (fwd_iterates[switchkins_type]) {
use_lastpose[switchkins_type] = 1; // restarting a kins types
}
return 0; // 0==> no error
} // kinematicsSwitch()
int kinematicsForward(const double *joint,
EmcPose * pos,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
int r;
if (fwd_iterates[switchkins_type] && use_lastpose[switchkins_type]) {
// initialize iterative forward kins (ok for identity too)
get_lastpose(switchkins_type,pos);
use_lastpose[switchkins_type] = 0;
}
switch (switchkins_type) {
case 0: r = kfwd0(joint, pos, fflags, iflags); break;
case 1: r = kfwd1(joint, pos, fflags, iflags); break;
case 2: r = kfwd2(joint, pos, fflags, iflags); break;
default: rtapi_print_msg(RTAPI_MSG_ERR,
"switchkins: Forward BAD switchkins_type </%d>\n",
switchkins_type);
return -1;
}
if (fwd_iterates[switchkins_type]) {save_lastpose(switchkins_type,pos);}
if (r) return r;
// gui.* pins created only if gui_kinstype>=0
// consider alternate implementations for gui_forward_kins():
// a) always call and use -1 to select default 0 type
if (kp.gui_kinstype >=0) {
// create gui pins for a vismach gui using the
// kins type specified by kp.gui_kinstype;
// currently the skgui pins are only needed for
// the hexagui vismach program (as it needs
// world coords for switchkin-types
r = gui_forward_kins(joint);
}
return r;
} // kinematicsForward()
int kinematicsInverse(const EmcPose * pos,
double *joint,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags)
{
int r;
switch (switchkins_type) {
case 0: r = kinv0(pos, joint, iflags, fflags); break;
case 1: r = kinv1(pos, joint, iflags, fflags); break;
case 2: r = kinv2(pos, joint, iflags, fflags); break;
default: rtapi_print_msg(RTAPI_MSG_ERR,
"switchkins: Inverse BAD switchkins_type </%d>\n",
switchkins_type);
return -1;
}
return r;
} // kinematicsInverse()
KINEMATICS_TYPE kinematicsType()
{
return KINEMATICS_BOTH;
}
//*********************************************************************
static char *coordinates;
RTAPI_MP_STRING(coordinates, "Axes-to-joints-ordering");
static char *sparm;
RTAPI_MP_STRING(sparm, "switchkins module-specific parameter");
EXPORT_SYMBOL(kinematicsSwitchable);
EXPORT_SYMBOL(kinematicsSwitch);
EXPORT_SYMBOL(kinematicsType);
EXPORT_SYMBOL(kinematicsForward);
EXPORT_SYMBOL(kinematicsInverse);
MODULE_LICENSE("GPL");
static int comp_id;
//*********************************************************************
int rtapi_app_main(void)
{
int i,res;
char* emsg="other";
// defaults prior to switchkinsSetup() call
kp.kinsname = NULL;
kp.halprefix = NULL;
kp.required_coordinates = "";
kp.max_joints = 0; // Setup must supply
kp.allow_duplicates = 0;
kp.fwd_iterates_mask = 0;
kp.gui_kinstype = -1; // negative means: not used
kp.sparm = sparm; // module parm passed to kins
KS ksetup0 = 0;
KS ksetup1 = 0;
KS ksetup2 = 0;
res = switchkinsSetup(&kp,
&ksetup0, &ksetup1, &ksetup2,
&kfwd0, &kfwd1, &kfwd2,
&kinv0, &kinv1, &kinv2);
if (res) {emsg="switchkinsSetp FAIL"; goto error;}
for (i=0; i < SWITCHKINS_MAX_TYPES; i++) {
if (kp.fwd_iterates_mask & (1<<i)) {
fwd_iterates[i] = 1;
rtapi_print("switchkins-type %d: fwd_iterates\n",i);
}
}
if (!kp.kinsname) { emsg = "Missing kinsname"; goto error; }
if (!kp.halprefix) {
kp.halprefix = kp.kinsname;
rtapi_print("Missing halprefix, using \"%s\"\n",kp.halprefix);
}
if (kp.max_joints <= 0 || kp.max_joints > EMCMOT_MAX_JOINTS) {
emsg = "bogus max_joints"; goto error;
}
if (kp.gui_kinstype >= SWITCHKINS_MAX_TYPES) {
emsg = "bogus gui_kinstype"; goto error;
}
if (!ksetup0 || !ksetup1 || !ksetup2) {
emsg = "Missing setup function"; goto error;
}
if (!kfwd0 || !kfwd1 || !kfwd2) {
emsg = "Missing fwd functionn"; goto error;
}
if (!kinv0 || !kinv1 || !kinv2) {
emsg = "Missing inv function"; goto error;
}
comp_id = hal_init(kp.kinsname);
if(comp_id < 0) goto error;
swdata = hal_malloc(sizeof(struct swdata));
if (!swdata) goto error;
res += hal_pin_bit_new("kinstype.is-0", HAL_OUT, &(swdata->kinstype_is_0), comp_id);
res += hal_pin_bit_new("kinstype.is-1", HAL_OUT, &(swdata->kinstype_is_1), comp_id);
res += hal_pin_bit_new("kinstype.is-2", HAL_OUT, &(swdata->kinstype_is_2), comp_id);
if (kp.gui_kinstype >=0) {
res += hal_pin_float_newf(HAL_IN, &swdata->gui_x, comp_id, "skgui.x");
res += hal_pin_float_newf(HAL_IN, &swdata->gui_y, comp_id, "skgui.y");
res += hal_pin_float_newf(HAL_IN, &swdata->gui_z, comp_id, "skgui.z");
res += hal_pin_float_newf(HAL_IN, &swdata->gui_a, comp_id, "skgui.a");
res += hal_pin_float_newf(HAL_IN, &swdata->gui_b, comp_id, "skgui.b");
res += hal_pin_float_newf(HAL_IN, &swdata->gui_c, comp_id, "skgui.c");
if (res) {emsg = "hal pin create fail";goto error;}
}
switchkins_type = 0; // startup with default type
kinematicsSwitch(switchkins_type);
if (!coordinates) {coordinates = kp.required_coordinates;}
ksetup0(comp_id,coordinates,&kp);
ksetup1(comp_id,coordinates,&kp);
ksetup2(comp_id,coordinates,&kp);
hal_ready(comp_id);
return 0;
error:
rtapi_print_msg(RTAPI_MSG_ERR,
"\nSwitchkins FAIL %s:<%s>\n",kp.kinsname,emsg);
hal_exit(comp_id);
return -1;
} // rtapi_app_main()
void rtapi_app_exit(void) { hal_exit(comp_id); }

View File

@@ -0,0 +1,36 @@
/*
** License GPL Version 2
*/
#ifndef SWITCHKINS_H // {
#define SWITCHKINS_H
#include <kinematics.h>
//hardcoded number of switchkins types (KS,KF,KI):
#define SWITCHKINS_MAX_TYPES 3
// KinematicsFORWARD functions
typedef int (*KF)(const double *joint,
EmcPose * pos,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags);
// KinematicsINVERSE functions
typedef int (*KI)(const struct EmcPose * world,
double *joint,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags);
// KinematicsSETUP functions
typedef int (*KS)(const int comp_id, // halpins
const char* coordinates, // module parameter
kparms* ksetup_parms //
);
//*********************************************************************
extern int switchkinsSetup(kparms* ksetup_parms,
KS* kset0, KS* kset1, KS* kset2,
KF* kfwd0, KF* kfwd1, KF* kfwd2,
KI* kinv0, KI* kinv1, KI* kinv2
);
#endif // }

View File

@@ -0,0 +1,83 @@
/* userkfuncs.c: template file for a user set of
** switchable kinematics functions.
** License GPL Version 2
**
** Example Usage (for customizing the genser-switchkins module):
** (works with rtpreempt only rtai --> Makefile needs work)
**
** LDIR is LinuxCNC git root directory
** UDIR is user directory (not in LinuxCNC git tree)
** 1) $ cp LDIR/src/emc/kinematics/userkfuncs.c UDIR/my_userk.c
** 2) $ edit UDIR/my_userk.c as required
** 3) $ source LDIR/scripts/rip-environment
** 4) For genser-switchkins module use make command line option:
** $ cd LDIR/src
** $ userkfuncs=UDIR/my_userk.c make && sudo make setuid
*/
// typical includes:
//#include <rtapi_math.h> // if reqd
#include <hal.h>
#include <kinematics.h>
// Add for kins based on genserkins:
// #include "genserkins.h" //includes gomath,hal
//**********************************************************************
// static local variables and functions go here
static int userk_inited = 0;
static struct udata {
hal_s32_t *fct;
hal_s32_t *ict;
} *udata;
//**********************************************************************
int userkKinematicsSetup(const int comp_id,
const char* coordinates,
kparms* kp)
{
int res=0;
rtapi_print("\nuserkKinematicsSetup:\n"
" %s <%s> max_joints=%d allow_duplicates=%d\n\n",
__FILE__,coordinates,
kp->max_joints,kp->allow_duplicates);
udata = hal_malloc(sizeof(struct udata));
if (!udata) goto error;
// HAL_IO used to allow resetting demo pins:
res += hal_pin_s32_new("userk.fct", HAL_IO, &(udata->fct), comp_id);
res += hal_pin_s32_new("userk.ict", HAL_IO, &(udata->ict), comp_id);
if (res) goto error;
userk_inited = 1;
return 0; // 0 ==> OK
error:
return -1;
}
int userkKinematicsForward(const double *joint,
struct EmcPose * world,
const KINEMATICS_FORWARD_FLAGS * fflags,
KINEMATICS_INVERSE_FLAGS * iflags)
{
if (!userk_inited) {
rtapi_print_msg(RTAPI_MSG_ERR,
"userkKinematics: not initialized\n");
return -1;
}
(*udata->fct)++;
return identityKinematicsForward(joint,world,fflags,iflags);
}
int userkKinematicsInverse(const EmcPose * pos,
double *joint,
const KINEMATICS_INVERSE_FLAGS * iflags,
KINEMATICS_FORWARD_FLAGS * fflags)
{
(*udata->ict)++;
return identityKinematicsInverse(pos,joint,iflags,fflags);
}

View File

@@ -0,0 +1,24 @@
#ifndef __LINUXCNC_RTAPI_CTYPE_H
#define __LINUXCNC_RTAPI_CTYPE_H
// Copyright 2006 Jeff Epler
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#ifdef MODULE
#include <linux/ctype.h>
#else
#include <ctype.h>
#endif
#endif