#include <stdarg.h>
#include "rtapi.h"
#include "rtapi_app.h"
#include "rtapi_string.h"
#include "hal.h"
#include "motion.h"
#include "motion_debug.h"
#include "motion_struct.h"
#include "mot_priv.h"
#include "rtapi_math.h"
#include "homing.h"
#define _(s) (s)
MODULE_AUTHOR("Matt Shaver/John Kasunich");
MODULE_DESCRIPTION("Motion Controller for EMC");
MODULE_LICENSE("GPL");
static int key = DEFAULT_SHMEM_KEY;
RTAPI_MP_INT(key, "shared memory key");
static long base_period_nsec = 0;
RTAPI_MP_LONG(base_period_nsec, "fastest thread period (nsecs)");
int base_thread_fp = 0;
RTAPI_MP_INT(base_thread_fp, "floating point in base thread?");
static long servo_period_nsec = 1000000;
RTAPI_MP_LONG(servo_period_nsec, "servo thread period (nsecs)");
static long traj_period_nsec = 0;
RTAPI_MP_LONG(traj_period_nsec, "trajectory planner period (nsecs)");
static int num_spindles = 1;
RTAPI_MP_INT (num_spindles, "number of spindles");
int motion_num_spindles;
static int num_joints = EMCMOT_MAX_JOINTS;
RTAPI_MP_INT(num_joints, "number of joints used in kinematics");
static int num_extrajoints = 0;
RTAPI_MP_INT(num_extrajoints, "number of extra joints (not used in kinematics)");
static int num_dio = DEFAULT_DIO;
RTAPI_MP_INT(num_dio, "number of digital inputs/outputs");
static int num_aio = DEFAULT_AIO;
RTAPI_MP_INT(num_aio, "number of analog inputs/outputs");
static int unlock_joints_mask = 0;
RTAPI_MP_INT(unlock_joints_mask, "mask to select joints for unlock pins");
emcmot_hal_data_t *emcmot_hal_data = 0;
emcmot_joint_t *joints = 0;
emcmot_axis_t *axes = 0;
#ifndef STRUCTS_IN_SHMEM
emcmot_joint_t joint_array[EMCMOT_MAX_JOINTS];
emcmot_axis_t axis_array[EMCMOT_MAX_AXIS];
#endif
emcmot_struct_t *emcmotStruct = 0;
struct emcmot_command_t *emcmotCommand = 0;
struct emcmot_status_t *emcmotStatus = 0;
struct emcmot_config_t *emcmotConfig = 0;
struct emcmot_debug_t *emcmotDebug = 0;
struct emcmot_error_t *emcmotError = 0;
static int emc_shmem_id;
static int mot_comp_id;
static int init_hal_io(void);
static int export_joint(int num, joint_hal_t * addr);
static int export_extrajoint(int num, extrajoint_hal_t * addr);
static int export_axis(char c, axis_hal_t * addr);
static int export_spindle(int num, spindle_hal_t * addr);
static int init_comm_buffers(void);
static int init_threads(void);
static int setTrajCycleTime(double secs);
static int setServoCycleTime(double secs);
int joint_is_lockable(int joint_num) {
return (unlock_joints_mask & (1 << joint_num) );
}
void switch_to_teleop_mode(void) {
int joint_num;
emcmot_joint_t *joint;
if (emcmotConfig->kinType != KINEMATICS_IDENTITY) {
if (!checkAllHomed()) {
reportError(_("all joints must be homed before going into teleop mode"));
return;
}
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
if (joint != 0) { joint->free_tp.enable = 0; }
}
emcmotDebug->teleoperating = 1;
emcmotDebug->coordinating = 0;
}
void emcmot_config_change(void)
{
if (emcmotConfig->head == emcmotConfig->tail) {
emcmotConfig->config_num++;
emcmotStatus->config_num = emcmotConfig->config_num;
emcmotConfig->head++;
}
}
void reportError(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
emcmotErrorPutfv(emcmotError, fmt, args);
va_end(args);
}
#ifndef va_copy
#define va_copy(dest, src) ((dest)=(src))
#endif
static rtapi_msg_handler_t old_handler = NULL;
static void emc_message_handler(msg_level_t level, const char *fmt, va_list ap)
{
va_list apc;
va_copy(apc, ap);
if(level == RTAPI_MSG_ERR) emcmotErrorPutfv(emcmotError, fmt, apc);
if(old_handler) old_handler(level, fmt, ap);
va_end(apc);
}
int rtapi_app_main(void)
{
int retval;
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_module() starting...\n");
mot_comp_id = hal_init("motmod");
if (mot_comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: hal_init() failed\n"));
return -1;
}
if (( num_joints < 1 ) || ( num_joints > EMCMOT_MAX_JOINTS )) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: num_joints is %d, must be between 1 and %d\n"), num_joints, EMCMOT_MAX_JOINTS);
hal_exit(mot_comp_id);
return -1;
}
if (( num_extrajoints < 0 ) || ( num_extrajoints > num_joints )) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("\nMOTION: num_extrajoints is %d, must be between 0 and %d\n\n"), num_extrajoints, num_joints);
hal_exit(mot_comp_id);
return -1;
}
if ( (num_extrajoints > 0) && (kinematicsType() != KINEMATICS_BOTH) ) {
rtapi_print_msg(RTAPI_MSG_ERR, _("\nMOTION: nonzero num_extrajoints requires KINEMATICS_BOTH\n\n"));
return -1;
}
if (num_extrajoints > 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("\nMOTION: kinematicjoints=%2d\n extrajoints=%2d\n Total joints=%2d\n\n"),
num_joints-num_extrajoints, num_extrajoints, num_joints
);
}
if (( num_spindles < 0 ) || ( num_spindles > EMCMOT_MAX_SPINDLES )) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: num_spindles is %d, must be between 0 and %d\n"), num_spindles, EMCMOT_MAX_SPINDLES);
hal_exit(mot_comp_id);
return -1;
}
motion_num_spindles = num_spindles;
if (( num_dio < 1 ) || ( num_dio > EMCMOT_MAX_DIO )) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: num_dio is %d, must be between 1 and %d\n"), num_dio, EMCMOT_MAX_DIO);
hal_exit(mot_comp_id);
return -1;
}
if (( num_aio < 1 ) || ( num_aio > EMCMOT_MAX_AIO )) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: num_aio is %d, must be between 1 and %d\n"), num_aio, EMCMOT_MAX_AIO);
hal_exit(mot_comp_id);
return -1;
}
retval = init_hal_io();
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: init_hal_io() failed\n"));
hal_exit(mot_comp_id);
return -1;
}
retval = init_comm_buffers();
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: init_comm_buffers() failed\n"));
hal_exit(mot_comp_id);
return -1;
}
retval = init_threads();
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: init_threads() failed\n"));
hal_exit(mot_comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_module() complete\n");
hal_ready(mot_comp_id);
old_handler = rtapi_get_msg_handler();
rtapi_set_msg_handler(emc_message_handler);
return 0;
}
void rtapi_app_exit(void)
{
int retval;
rtapi_set_msg_handler(old_handler);
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: cleanup_module() started.\n");
retval = hal_stop_threads();
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: hal_stop_threads() failed, returned %d\n"), retval);
}
retval = rtapi_shmem_delete(emc_shmem_id, mot_comp_id);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: rtapi_shmem_delete() failed, returned %d\n"), retval);
}
retval = hal_exit(mot_comp_id);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
_("MOTION: hal_exit() failed, returned %d\n"), retval);
}
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: cleanup_module() finished.\n");
}
static int init_hal_io(void)
{
int n, retval;
joint_hal_t *joint_data;
extrajoint_hal_t *ejoint_data;
axis_hal_t *axis_data;
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_hal_io() starting...\n");
emcmot_hal_data = hal_malloc(sizeof(emcmot_hal_data_t));
if (emcmot_hal_data == 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: emcmot_hal_data malloc failed\n"));
return -1;
}
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->probe_input), mot_comp_id, "motion.probe-input")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_IN, &(emcmot_hal_data->adaptive_feed), mot_comp_id, "motion.adaptive-feed")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->feed_hold), mot_comp_id, "motion.feed-hold")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->feed_inhibit), mot_comp_id, "motion.feed-inhibit")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->homing_inhibit), mot_comp_id, "motion.homing-inhibit")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->tp_reverse), mot_comp_id, "motion.tp-reverse")) < 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->enable), mot_comp_id, "motion.enable")) != 0) goto error;
for (n = 0; n < num_dio; n++) {
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->synch_do[n]), mot_comp_id, "motion.digital-out-%02d", n)) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->synch_di[n]), mot_comp_id, "motion.digital-in-%02d", n)) != 0) goto error;
}
for (n = 0; n < num_aio; n++) {
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->analog_output[n]), mot_comp_id, "motion.analog-out-%02d", n)) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_IN, &(emcmot_hal_data->analog_input[n]), mot_comp_id, "motion.analog-in-%02d", n)) != 0) goto error;
}
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->motion_enabled), mot_comp_id, "motion.motion-enabled")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->in_position), mot_comp_id, "motion.in-position")) != 0) goto error;
if ((retval = hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->motion_type), mot_comp_id, "motion.motion-type")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->coord_mode), mot_comp_id, "motion.coord-mode")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->teleop_mode), mot_comp_id, "motion.teleop-mode")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->coord_error), mot_comp_id, "motion.coord-error")) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->on_soft_limit), mot_comp_id, "motion.on-soft-limit")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->current_vel), mot_comp_id, "motion.current-vel")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->requested_vel), mot_comp_id, "motion.requested-vel")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->distance_to_go), mot_comp_id, "motion.distance-to-go")) != 0) goto error;
if ((retval = hal_pin_s32_newf(HAL_OUT, &(emcmot_hal_data->program_line), mot_comp_id, "motion.program-line")) != 0) goto error;
if ((retval = hal_param_bit_newf(HAL_RO, &(emcmot_hal_data->debug_bit_0), mot_comp_id, "motion.debug-bit-0")) != 0) goto error;
if ((retval = hal_param_bit_newf(HAL_RO, &(emcmot_hal_data->debug_bit_1), mot_comp_id, "motion.debug-bit-1")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->debug_float_0), mot_comp_id, "motion.debug-float-0")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->debug_float_1), mot_comp_id, "motion.debug-float-1")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->debug_float_2), mot_comp_id, "motion.debug-float-2")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->debug_float_3), mot_comp_id, "motion.debug-float-3")) != 0) goto error;
if ((retval = hal_param_s32_newf(HAL_RO, &(emcmot_hal_data->debug_s32_0), mot_comp_id, "motion.debug-s32-0")) != 0) goto error;
if ((retval = hal_param_s32_newf(HAL_RO, &(emcmot_hal_data->debug_s32_1), mot_comp_id, "motion.debug-s32-1")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->traj_pos_out), mot_comp_id, "traj.pos_out")) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->traj_vel_out), mot_comp_id, "traj.vel_out")) != 0) goto error;
if ((retval = hal_param_u32_newf(HAL_RO, &(emcmot_hal_data->traj_active_tc), mot_comp_id, "traj.active_tc")) != 0) goto error;
for ( n = 0 ; n < 4 ; n++ ) {
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->tc_pos[n]), mot_comp_id, "tc.%d.pos", n)) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->tc_vel[n]), mot_comp_id, "tc.%d.vel", n)) != 0) goto error;
if ((retval = hal_param_float_newf(HAL_RO, &(emcmot_hal_data->tc_acc[n]), mot_comp_id, "tc.%d.acc", n)) != 0) goto error;
}
if ((retval = hal_pin_u32_newf(HAL_OUT, &(emcmot_hal_data->last_period), mot_comp_id, "motion.servo.last-period")) != 0) goto error;
#ifdef HAVE_CPU_KHZ
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->last_period_ns), mot_comp_id, "motion.servo.last-period-ns")) != 0) goto error;
#endif
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_x), mot_comp_id, "motion.tooloffset.x")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_y), mot_comp_id, "motion.tooloffset.y")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_z), mot_comp_id, "motion.tooloffset.z")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_a), mot_comp_id, "motion.tooloffset.a")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_b), mot_comp_id, "motion.tooloffset.b")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_c), mot_comp_id, "motion.tooloffset.c")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_u), mot_comp_id, "motion.tooloffset.u")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_v), mot_comp_id, "motion.tooloffset.v")) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->tooloffset_w), mot_comp_id, "motion.tooloffset.w")) != 0) goto error;
*(emcmot_hal_data->adaptive_feed) = 1.0;
*(emcmot_hal_data->feed_hold) = 0;
*(emcmot_hal_data->feed_inhibit) = 0;
*(emcmot_hal_data->homing_inhibit) = 0;
*(emcmot_hal_data->probe_input) = 0;
*(emcmot_hal_data->enable) = 1;
for (n = 0; n < num_dio; n++) {
*(emcmot_hal_data->synch_do[n]) = 0;
*(emcmot_hal_data->synch_di[n]) = 0;
}
for (n = 0; n < num_aio; n++) {
*(emcmot_hal_data->analog_output[n]) = 0.0;
*(emcmot_hal_data->analog_input[n]) = 0.0;
}
*(emcmot_hal_data->motion_enabled) = 0;
*(emcmot_hal_data->in_position) = 0;
*(emcmot_hal_data->motion_type) = 0;
*(emcmot_hal_data->coord_mode) = 0;
*(emcmot_hal_data->teleop_mode) = 0;
*(emcmot_hal_data->coord_error) = 0;
*(emcmot_hal_data->on_soft_limit) = 0;
emcmot_hal_data->debug_bit_0 = 0;
emcmot_hal_data->debug_bit_1 = 0;
emcmot_hal_data->debug_float_0 = 0.0;
emcmot_hal_data->debug_float_1 = 0.0;
emcmot_hal_data->debug_float_2 = 0.0;
emcmot_hal_data->debug_float_3 = 0.0;
*(emcmot_hal_data->last_period) = 0;
for (n=0; n < num_spindles; n++) {
retval = export_spindle(n, &(emcmot_hal_data->spindle[n]));
if (retval != 0){
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: spindle %d pin export failed"), n);
return -1;
}
}
for (n = 0; n < num_joints; n++) {
joint_data = &(emcmot_hal_data->joint[n]);
retval = export_joint(n, joint_data);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: joint %d pin/param export failed\n"), n);
return -1;
}
*(joint_data->amp_enable) = 0;
}
retval = export_joint_home_pins(num_joints,mot_comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: export_joint_home_pins failed\n"));
return -1;
}
for (n = 0; n < num_extrajoints; n++) {
ejoint_data = &(emcmot_hal_data->ejoint[n]);
retval = export_extrajoint(n + num_joints - num_extrajoints,ejoint_data);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: ejoint %d pin/param export failed\n"), n);
return -1;
}
}
for (n = 0; n < EMCMOT_MAX_AXIS; n++) {
char c = "xyzabcuvw"[n];
axis_data = &(emcmot_hal_data->axis[n]);
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].pos_cmd),
mot_comp_id, "axis.%c.pos-cmd", c)) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].teleop_vel_cmd),
mot_comp_id, "axis.%c.teleop-vel-cmd", c)) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].teleop_pos_cmd),
mot_comp_id, "axis.%c.teleop-pos-cmd", c)) != 0) goto error;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].teleop_vel_lim),
mot_comp_id, "axis.%c.teleop-vel-lim", c)) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->axis[n].teleop_tp_enable),
mot_comp_id, "axis.%c.teleop-tp-enable",c)) != 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->axis[n].eoffset_enable),
mot_comp_id, "axis.%c.eoffset-enable", c)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(emcmot_hal_data->axis[n].eoffset_clear),
mot_comp_id, "axis.%c.eoffset-clear", c)) != 0) return retval;
if ((retval = hal_pin_s32_newf(HAL_IN, &(emcmot_hal_data->axis[n].eoffset_counts),
mot_comp_id, "axis.%c.eoffset-counts", c)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN, &(emcmot_hal_data->axis[n].eoffset_scale),
mot_comp_id, "axis.%c.eoffset-scale", c)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].external_offset),
mot_comp_id, "axis.%c.eoffset", c)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(emcmot_hal_data->axis[n].external_offset_requested),
mot_comp_id, "axis.%c.eoffset-request", c)) != 0) return retval;
retval = export_axis(c, axis_data);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("MOTION: axis %c pin/param export failed\n"), c);
return -1;
}
}
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->eoffset_limited), mot_comp_id,
"motion.eoffset-limited")) < 0) goto error;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(emcmot_hal_data->eoffset_active), mot_comp_id,
"motion.eoffset-active")) < 0) goto error;
rtapi_print_msg(RTAPI_MSG_INFO,
"MOTION: init_hal_io() complete, %d axes.\n", n);
return 0;
error:
return retval;
}
static int export_spindle(int num, spindle_hal_t * addr){
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level(RTAPI_MSG_WARN);
if ((retval = hal_pin_bit_newf(HAL_IO, &(addr->spindle_index_enable), mot_comp_id, "spindle.%d.index-enable", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_on), mot_comp_id, "spindle.%d.on", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_forward), mot_comp_id, "spindle.%d.forward", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_reverse), mot_comp_id, "spindle.%d.reverse", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_brake), mot_comp_id, "spindle.%d.brake", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_speed_out), mot_comp_id, "spindle.%d.speed-out", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_speed_out_abs), mot_comp_id, "spindle.%d.speed-out-abs", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_speed_out_rps), mot_comp_id, "spindle.%d.speed-out-rps", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_speed_out_rps_abs), mot_comp_id, "spindle.%d.speed-out-rps-abs", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_speed_cmd_rps), mot_comp_id, "spindle.%d.speed-cmd-rps", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->spindle_inhibit), mot_comp_id, "spindle.%d.inhibit", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->spindle_amp_fault), mot_comp_id, "spindle.%d.amp-fault-in", num)) != 0) return retval;
*(addr->spindle_inhibit) = 0;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->spindle_orient_angle), mot_comp_id, "spindle.%d.orient-angle", num)) < 0) return retval;
if ((retval = hal_pin_s32_newf(HAL_OUT, &(addr->spindle_orient_mode), mot_comp_id, "spindle.%d.orient-mode", num)) < 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_orient), mot_comp_id, "spindle.%d.orient", num)) < 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->spindle_locked), mot_comp_id, "spindle.%d.locked", num)) < 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->spindle_is_oriented), mot_comp_id, "spindle.%d.is-oriented", num)) < 0) return retval;
if ((retval = hal_pin_s32_newf(HAL_IN, &(addr->spindle_orient_fault), mot_comp_id, "spindle.%d.orient-fault", num)) < 0) return retval;
*(addr->spindle_orient_angle) = 0.0;
*(addr->spindle_orient_mode) = 0;
*(addr->spindle_orient) = 0;
if ((retval = hal_pin_float_newf(HAL_IN, &(addr->spindle_revs), mot_comp_id, "spindle.%d.revs", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN, &(addr->spindle_speed_in), mot_comp_id, "spindle.%d.speed-in", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->spindle_is_atspeed), mot_comp_id, "spindle.%d.at-speed", num)) != 0) return retval;
*(addr->spindle_is_atspeed) = 1;
rtapi_set_msg_level(msg);
return 0;
}
static int export_joint(int num, joint_hal_t * addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level(RTAPI_MSG_WARN);
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->coarse_pos_cmd), mot_comp_id, "joint.%d.coarse-pos-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->joint_pos_cmd), mot_comp_id, "joint.%d.pos-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->joint_pos_fb), mot_comp_id, "joint.%d.pos-fb", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->motor_pos_cmd), mot_comp_id, "joint.%d.motor-pos-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN, &(addr->motor_pos_fb), mot_comp_id, "joint.%d.motor-pos-fb", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->motor_offset), mot_comp_id, "joint.%d.motor-offset", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->pos_lim_sw), mot_comp_id, "joint.%d.pos-lim-sw-in", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->neg_lim_sw), mot_comp_id, "joint.%d.neg-lim-sw-in", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->amp_enable), mot_comp_id, "joint.%d.amp-enable-out", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->amp_fault), mot_comp_id, "joint.%d.amp-fault-in", num)) != 0) return retval;
if ((retval = hal_pin_s32_newf(HAL_IN, &(addr->jjog_counts), mot_comp_id, "joint.%d.jog-counts", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->jjog_enable), mot_comp_id, "joint.%d.jog-enable", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN, &(addr->jjog_scale), mot_comp_id, "joint.%d.jog-scale", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->jjog_vel_mode), mot_comp_id, "joint.%d.jog-vel-mode", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->joint_vel_cmd), mot_comp_id, "joint.%d.vel-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->joint_acc_cmd), mot_comp_id, "joint.%d.acc-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->backlash_corr), mot_comp_id, "joint.%d.backlash-corr", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->backlash_filt), mot_comp_id, "joint.%d.backlash-filt", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->backlash_vel), mot_comp_id, "joint.%d.backlash-vel", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->f_error), mot_comp_id, "joint.%d.f-error", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->f_error_lim), mot_comp_id, "joint.%d.f-error-lim", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->free_pos_cmd), mot_comp_id, "joint.%d.free-pos-cmd", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_OUT, &(addr->free_vel_lim), mot_comp_id, "joint.%d.free-vel-lim", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->free_tp_enable), mot_comp_id, "joint.%d.free-tp-enable", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->kb_jjog_active), mot_comp_id, "joint.%d.kb-jog-active", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->wheel_jjog_active), mot_comp_id, "joint.%d.wheel-jog-active", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->in_position), mot_comp_id, "joint.%d.in-position", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->phl), mot_comp_id, "joint.%d.pos-hard-limit", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->nhl), mot_comp_id, "joint.%d.neg-hard-limit", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->active), mot_comp_id, "joint.%d.active", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->error), mot_comp_id, "joint.%d.error", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->f_errored), mot_comp_id, "joint.%d.f-errored", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->faulted), mot_comp_id, "joint.%d.faulted", num)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN,&(addr->jjog_accel_fraction),mot_comp_id,"joint.%d.jog-accel-fraction", num)) != 0) return retval;
*addr->jjog_accel_fraction = 1.0;
if ( joint_is_lockable(num) ) {
rtapi_print_msg(RTAPI_MSG_WARN,"motion.c: Creating unlock hal pins for joint %d\n",num);
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->unlock), mot_comp_id, "joint.%d.unlock", num)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->is_unlocked), mot_comp_id, "joint.%d.is-unlocked", num)) != 0) return retval;
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_extrajoint(int num, extrajoint_hal_t * addr)
{
int retval;
if ((retval = hal_pin_float_newf(HAL_IN, &(addr->posthome_cmd), mot_comp_id,
"joint.%d.posthome-cmd", num)) != 0) return retval;
return 0;
}
static int export_axis(char c, axis_hal_t * addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level(RTAPI_MSG_WARN);
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->ajog_enable), mot_comp_id,"axis.%c.jog-enable", c)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN,&(addr->ajog_scale), mot_comp_id,"axis.%c.jog-scale", c)) != 0) return retval;
if ((retval = hal_pin_s32_newf(HAL_IN, &(addr->ajog_counts), mot_comp_id,"axis.%c.jog-counts", c)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->ajog_vel_mode), mot_comp_id,"axis.%c.jog-vel-mode", c)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->kb_ajog_active), mot_comp_id,"axis.%c.kb-jog-active", c)) != 0) return retval;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->wheel_ajog_active),mot_comp_id,"axis.%c.wheel-jog-active", c)) != 0) return retval;
if ((retval = hal_pin_float_newf(HAL_IN,&(addr->ajog_accel_fraction), mot_comp_id,"axis.%c.jog-accel-fraction", c)) != 0) return retval;
*addr->ajog_accel_fraction = 1.0;
rtapi_set_msg_level(msg);
return 0;
}
static int init_comm_buffers(void)
{
int joint_num, axis_num, spindle_num, n;
emcmot_joint_t *joint;
int retval;
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_comm_buffers() starting...\n");
emcmotStruct = 0;
emcmotDebug = 0;
emcmotStatus = 0;
emcmotCommand = 0;
emcmotConfig = 0;
emc_shmem_id = rtapi_shmem_new(key, mot_comp_id, sizeof(emcmot_struct_t));
if (emc_shmem_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: rtapi_shmem_new failed, returned %d\n", emc_shmem_id);
return -1;
}
retval = rtapi_shmem_getptr(emc_shmem_id, (void **) &emcmotStruct);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: rtapi_shmem_getptr failed, returned %d\n", retval);
return -1;
}
memset(emcmotStruct, 0, sizeof(emcmot_struct_t));
emcmotCommand = &emcmotStruct->command;
emcmotStatus = &emcmotStruct->status;
emcmotConfig = &emcmotStruct->config;
emcmotDebug = &emcmotStruct->debug;
emcmotError = &emcmotStruct->error;
emcmotErrorInit(emcmotError);
emcmotCommand->head = 0;
emcmotCommand->command = 0;
emcmotCommand->commandNum = 0;
emcmotCommand->tail = 0;
emcmotStatus->head = 0;
emcmotStatus->commandEcho = 0;
emcmotStatus->commandNumEcho = 0;
emcmotStatus->commandStatus = 0;
emcmotDebug->head = 0;
emcmotConfig->head = 0;
emcmotStatus->motionFlag = 0;
SET_MOTION_ERROR_FLAG(0);
SET_MOTION_COORD_FLAG(0);
SET_MOTION_TELEOP_FLAG(0);
emcmotDebug->split = 0;
emcmotStatus->heartbeat = 0;
ALL_JOINTS = num_joints; emcmotConfig->numExtraJoints = num_extrajoints; emcmotStatus->numExtraJoints = num_extrajoints;
emcmotConfig->numSpindles = num_spindles;
emcmotConfig->numDIO = num_dio;
emcmotConfig->numAIO = num_aio;
ZERO_EMC_POSE(emcmotStatus->carte_pos_cmd);
ZERO_EMC_POSE(emcmotStatus->carte_pos_fb);
emcmotStatus->vel = 0.0;
emcmotConfig->limitVel = 0.0;
emcmotStatus->acc = 0.0;
emcmotStatus->feed_scale = 1.0;
emcmotStatus->rapid_scale = 1.0;
emcmotStatus->net_feed_scale = 1.0;
emcmotStatus->enables_new = FS_ENABLED | SS_ENABLED | FH_ENABLED;
emcmotStatus->enables_queued = emcmotStatus->enables_new;
emcmotStatus->id = 0;
emcmotStatus->depth = 0;
emcmotStatus->activeDepth = 0;
emcmotStatus->paused = 0;
emcmotStatus->overrideLimitMask = 0;
SET_MOTION_INPOS_FLAG(1);
SET_MOTION_ENABLE_FLAG(0);
emcmotConfig->kinType = kinematicsType();
emcmot_config_change();
#ifdef STRUCTS_IN_SHMEM
joints = &(emcmotDebug->joints[0]);
axes = &(emcmotDebug->axes[0]);
#else
joints = &(joint_array[0]);
axes = &(axis_array[0]);
#endif
for (spindle_num = 0; spindle_num < EMCMOT_MAX_SPINDLES; spindle_num++){
emcmotStatus->spindle_status[spindle_num].scale = 1.0;
emcmotStatus->spindle_status[spindle_num].speed = 0.0;
}
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
emcmot_axis_t *axis;
axis = &axes[axis_num];
axis->locking_joint = -1;
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->type = 0;
joint->max_pos_limit = 1.0;
joint->min_pos_limit = -1.0;
joint->vel_limit = 1.0;
joint->acc_limit = 1.0;
joint->min_ferror = 0.01;
joint->max_ferror = 1.0;
joint->backlash = 0.0;
joint->comp.entries = 0;
joint->comp.entry = &(joint->comp.array[0]);
joint->comp.array[0].nominal = -DBL_MAX;
joint->comp.array[0].fwd_trim = 0.0;
joint->comp.array[0].rev_trim = 0.0;
joint->comp.array[0].fwd_slope = 0.0;
joint->comp.array[0].rev_slope = 0.0;
for ( n = 1 ; n < EMCMOT_COMP_SIZE+2 ; n++ ) {
joint->comp.array[n].nominal = DBL_MAX;
joint->comp.array[n].fwd_trim = 0.0;
joint->comp.array[n].rev_trim = 0.0;
joint->comp.array[n].fwd_slope = 0.0;
joint->comp.array[n].rev_slope = 0.0;
}
joint->flag = 0;
SET_JOINT_INPOS_FLAG(joint, 1);
joint->coarse_pos = 0.0;
joint->pos_cmd = 0.0;
joint->vel_cmd = 0.0;
joint->acc_cmd = 0.0;
joint->backlash_corr = 0.0;
joint->backlash_filt = 0.0;
joint->backlash_vel = 0.0;
joint->motor_pos_cmd = 0.0;
joint->motor_pos_fb = 0.0;
joint->pos_fb = 0.0;
joint->ferror = 0.0;
joint->ferror_limit = joint->min_ferror;
joint->ferror_high_mark = 0.0;
cubicInit(&(joint->cubic));
}
homing_init();
emcmotDebug->cur_time = emcmotDebug->last_time = 0.0;
emcmotDebug->start_time = etime();
emcmotDebug->running_time = 0.0;
if (-1 == tpCreate(&emcmotDebug->coord_tp, DEFAULT_TC_QUEUE_SIZE,
emcmotDebug->queueTcSpace)) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: failed to create motion emcmotDebug->coord_tp\n");
return -1;
}
tpSetCycleTime(&emcmotDebug->coord_tp, emcmotConfig->trajCycleTime);
tpSetPos(&emcmotDebug->coord_tp, &emcmotStatus->carte_pos_cmd);
tpSetVmax(&emcmotDebug->coord_tp, emcmotStatus->vel, emcmotStatus->vel);
tpSetAmax(&emcmotDebug->coord_tp, emcmotStatus->acc);
emcmotStatus->tail = 0;
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_comm_buffers() complete\n");
return 0;
}
static int init_threads(void)
{
double base_period_sec, servo_period_sec;
int servo_base_ratio;
int retval;
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_threads() starting...\n");
if (base_period_nsec == 0) {
base_period_nsec = servo_period_nsec;
}
if (traj_period_nsec == 0) {
traj_period_nsec = servo_period_nsec;
}
if (servo_period_nsec < base_period_nsec) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: bad servo period %ld nsec\n", servo_period_nsec);
return -1;
}
base_period_sec = base_period_nsec * 0.000000001;
servo_period_sec = servo_period_nsec * 0.000000001;
servo_base_ratio = (servo_period_sec / base_period_sec) + 0.5;
servo_period_nsec = base_period_nsec * servo_base_ratio;
if (servo_base_ratio > 1) {
retval = hal_create_thread("base-thread", base_period_nsec, base_thread_fp);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: failed to create %ld nsec base thread\n",
base_period_nsec);
return -1;
}
}
retval = hal_create_thread("servo-thread", servo_period_nsec, 1);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: failed to create %ld nsec servo thread\n",
servo_period_nsec);
return -1;
}
retval = hal_export_funct("motion-controller", emcmotController, 0 , 1 , 0 , mot_comp_id);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: failed to export controller function\n");
return -1;
}
retval = hal_export_funct("motion-command-handler", emcmotCommandHandler, 0 , 1 , 0 , mot_comp_id);
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"MOTION: failed to export command handler function\n");
return -1;
}
#if 0#endif
setServoCycleTime(servo_period_nsec * 1e-9);
setTrajCycleTime(traj_period_nsec * 1e-9);
rtapi_print_msg(RTAPI_MSG_INFO, "MOTION: init_threads() complete\n");
return 0;
}
void emcmotSetCycleTime(unsigned long nsec )
{
int servo_mult;
servo_mult = traj_period_nsec / nsec;
if(servo_mult < 0) servo_mult = 1;
setTrajCycleTime(nsec * 1e-9);
setServoCycleTime(nsec * servo_mult * 1e-9);
}
static int setTrajCycleTime(double secs)
{
static int t;
rtapi_print_msg(RTAPI_MSG_INFO,
"MOTION: setting Traj cycle time to %ld nsecs\n", (long) (secs * 1e9));
if (secs <= 0.0) {
return -1;
}
emcmot_config_change();
if(emcmotConfig->servoCycleTime)
emcmotConfig->interpolationRate =
(int) (secs / emcmotConfig->servoCycleTime + 0.5);
else
emcmotConfig->interpolationRate = 1;
tpSetCycleTime(&emcmotDebug->coord_tp, secs);
for (t = 0; t < ALL_JOINTS; t++) {
cubicSetInterpolationRate(&(joints[t].cubic),
emcmotConfig->interpolationRate);
}
emcmotConfig->trajCycleTime = secs;
return 0;
}
static int setServoCycleTime(double secs)
{
static int t;
rtapi_print_msg(RTAPI_MSG_INFO,
"MOTION: setting Servo cycle time to %ld nsecs\n", (long) (secs * 1e9));
if (secs <= 0.0) {
return -1;
}
emcmot_config_change();
emcmotConfig->interpolationRate =
(int) (emcmotConfig->trajCycleTime / secs + 0.5);
for (t = 0; t < ALL_JOINTS; t++) {
cubicSetInterpolationRate(&(joints[t].cubic),
emcmotConfig->interpolationRate);
cubicSetSegmentTime(&(joints[t].cubic), secs);
}
emcmotConfig->servoCycleTime = secs;
return 0;
}