#include "posemath.h"
#include "rtapi.h"
#include "hal.h"
#include "motion.h"
#include "mot_priv.h"
#include "rtapi_math.h"
#include "tp.h"
#include "tc.h"
#include "simple_tp.h"
#include "motion_debug.h"
#include "config.h"
#include "motion_types.h"
#include "homing.h"
#define _(s) (s)
static int ext_offset_teleop_limit = 0;
static int ext_offset_coord_limit = 0;
static double ext_offset_epsilon;
KINEMATICS_FORWARD_FLAGS fflags = 0;
KINEMATICS_INVERSE_FLAGS iflags = 0;
double servo_freq;
static unsigned long last_period = 0;
static double servo_period;
extern struct emcmot_status_t *emcmotStatus;
static double *pcmd_p[EMCMOT_MAX_AXIS];
static void process_inputs(void);
static void do_forward_kins(void);
static void process_probe_inputs(void);
static void check_for_faults(void);
static void set_operating_mode(void);
static void handle_jjogwheels(void);
static void handle_ajogwheels(void);
static void get_pos_cmds(long period);
static void compute_screw_comp(void);
static void output_to_hal(void);
static void update_status(void);
static void initialize_external_offsets(void);
static void plan_external_offsets(void);
static void sync_teleop_tp_to_carte_pos(int);
static void sync_carte_pos_to_teleop_tp(int);
static void apply_ext_offsets_to_carte_pos(int);
static int update_coord_with_bound(void);
static int update_teleop_with_check(int,simple_tp_t*);
void emcmotController(void *arg, long period)
{
static int do_once = 1;
if (do_once) {
pcmd_p[0] = &(emcmotStatus->carte_pos_cmd.tran.x);
pcmd_p[1] = &(emcmotStatus->carte_pos_cmd.tran.y);
pcmd_p[2] = &(emcmotStatus->carte_pos_cmd.tran.z);
pcmd_p[3] = &(emcmotStatus->carte_pos_cmd.a);
pcmd_p[4] = &(emcmotStatus->carte_pos_cmd.b);
pcmd_p[5] = &(emcmotStatus->carte_pos_cmd.c);
pcmd_p[6] = &(emcmotStatus->carte_pos_cmd.u);
pcmd_p[7] = &(emcmotStatus->carte_pos_cmd.v);
pcmd_p[8] = &(emcmotStatus->carte_pos_cmd.w);
do_once = 0;
}
static long long int last = 0;
long long int now = rtapi_get_clocks();
long int this_run = (long int)(now - last);
*(emcmot_hal_data->last_period) = this_run;
#ifdef HAVE_CPU_KHZ
*(emcmot_hal_data->last_period_ns) = this_run * 1e6 / cpu_khz;
#endif
last = now;
servo_period = period * 0.000000001;
if(period != last_period) {
emcmotSetCycleTime(period);
last_period = period;
}
servo_freq = 1.0 / servo_period;
emcmotStatus->head++;
read_homing_in_pins(ALL_JOINTS);
process_inputs();
do_forward_kins();
process_probe_inputs();
check_for_faults();
set_operating_mode();
handle_jjogwheels();
handle_ajogwheels();
do_homing_sequence();
do_homing();
get_pos_cmds(period);
compute_screw_comp();
plan_external_offsets();
output_to_hal();
write_homing_out_pins(ALL_JOINTS);
update_status();
emcmotStatus->heartbeat++;
emcmotStatus->tail = emcmotStatus->head;
}
static void process_inputs(void)
{
int joint_num, spindle_num;
double abs_ferror, scale;
joint_hal_t *joint_data;
emcmot_joint_t *joint;
unsigned char enables;
for (spindle_num = 0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
emcmotStatus->spindle_status[spindle_num].spindleRevs =
*emcmot_hal_data->spindle[spindle_num].spindle_revs;
emcmotStatus->spindle_status[spindle_num].spindleSpeedIn =
*emcmot_hal_data->spindle[spindle_num].spindle_speed_in;
emcmotStatus->spindle_status[spindle_num].at_speed =
*emcmot_hal_data->spindle[spindle_num].spindle_is_atspeed;
}
if ( emcmotStatus->motion_state == EMCMOT_MOTION_COORD ) {
enables = emcmotStatus->enables_queued;
} else {
enables = emcmotStatus->enables_new;
}
scale = 1.0;
if ( (emcmotStatus->motion_state != EMCMOT_MOTION_FREE)
&& (enables & FS_ENABLED) ) {
if (emcmotStatus->motionType == EMC_MOTION_TYPE_TRAVERSE) {
scale *= emcmotStatus->rapid_scale;
} else {
scale *= emcmotStatus->feed_scale;
}
}
if ( enables & AF_ENABLED ) {
double adaptive_feed_in = *emcmot_hal_data->adaptive_feed;
if ( adaptive_feed_in > 1.0 ) {
adaptive_feed_in = 1.0;
} else if (adaptive_feed_in < -1.0) {
adaptive_feed_in = -1.0;
}
double adaptive_feed_out = fabs(adaptive_feed_in);
if ( adaptive_feed_in < 0.0 && emcmotDebug->coord_tp.reverse_run == TC_DIR_FORWARD) {
if (tpSetRunDir(&emcmotDebug->coord_tp, TC_DIR_REVERSE) != TP_ERR_OK) {
adaptive_feed_out = 0.0;
}
} else if (adaptive_feed_in > 0.0 && emcmotDebug->coord_tp.reverse_run == TC_DIR_REVERSE ) {
if (tpSetRunDir(&emcmotDebug->coord_tp, TC_DIR_FORWARD) != TP_ERR_OK) {
adaptive_feed_out = 0.0;
}
}
scale *= adaptive_feed_out;
}
if ( enables & FH_ENABLED ) {
if ( *emcmot_hal_data->feed_hold ) {
scale = 0;
}
}
if ( enables & *emcmot_hal_data->feed_inhibit ) {
scale = 0;
}
emcmotStatus->net_feed_scale = scale;
for (spindle_num=0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
scale = 1.0;
if ( enables & SS_ENABLED ) {
scale *= emcmotStatus->spindle_status[spindle_num].scale;
}
if ( enables & *emcmot_hal_data->spindle[spindle_num].spindle_inhibit ) {
scale = 0;
}
emcmotStatus->spindle_status[spindle_num].net_scale = scale;
}
for (joint_num = 0; joint_num < ALL_JOINTS ; joint_num++) {
joint_data = &(emcmot_hal_data->joint[joint_num]);
joint = &joints[joint_num];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
joint->motor_pos_fb = *(joint_data->motor_pos_fb);
if (( get_homing_at_index_search_wait(joint_num) ) &&
( get_index_enable(joint_num) == 0 )) {
joint->pos_fb = joint->pos_cmd;
} else {
joint->pos_fb = joint->motor_pos_fb -
(joint->backlash_filt + joint->motor_offset);
}
if ( IS_EXTRA_JOINT(joint_num) && get_homed(joint_num) ) {
joint->ferror = 0; } else {
joint->ferror = joint->pos_cmd - joint->pos_fb;
}
abs_ferror = fabs(joint->ferror);
if (abs_ferror > joint->ferror_high_mark) {
joint->ferror_high_mark = abs_ferror;
}
if (joint->vel_limit > 0.0) {
joint->ferror_limit =
joint->max_ferror * fabs(joint->vel_cmd) / joint->vel_limit;
} else {
joint->ferror_limit = 0;
}
if (joint->ferror_limit < joint->min_ferror) {
joint->ferror_limit = joint->min_ferror;
}
if (abs_ferror > joint->ferror_limit) {
SET_JOINT_FERROR_FLAG(joint, 1);
} else {
SET_JOINT_FERROR_FLAG(joint, 0);
}
if (*(joint_data->pos_lim_sw)) {
SET_JOINT_PHL_FLAG(joint, 1);
} else {
SET_JOINT_PHL_FLAG(joint, 0);
}
if (*(joint_data->neg_lim_sw)) {
SET_JOINT_NHL_FLAG(joint, 1);
} else {
SET_JOINT_NHL_FLAG(joint, 0);
}
joint->on_pos_limit = GET_JOINT_PHL_FLAG(joint);
joint->on_neg_limit = GET_JOINT_NHL_FLAG(joint);
if (*(joint_data->amp_fault)) {
SET_JOINT_FAULT_FLAG(joint, 1);
} else {
SET_JOINT_FAULT_FLAG(joint, 0);
}
}
for (spindle_num = 0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
if(*(emcmot_hal_data->spindle[spindle_num].spindle_amp_fault)){
emcmotStatus->spindle_status[spindle_num].fault = 1;
}else{
emcmotStatus->spindle_status[spindle_num].fault = 0;
}
if (*(emcmot_hal_data->spindle[spindle_num].spindle_orient)) {
if (*(emcmot_hal_data->spindle[spindle_num].spindle_orient_fault)) {
emcmotStatus->spindle_status[spindle_num].orient_state = EMCMOT_ORIENT_FAULTED;
*(emcmot_hal_data->spindle[spindle_num].spindle_orient) = 0;
emcmotStatus->spindle_status[spindle_num].orient_fault =
*(emcmot_hal_data->spindle[spindle_num].spindle_orient_fault);
reportError(_("fault %d during orient in progress"),
emcmotStatus->spindle_status[spindle_num].orient_fault);
emcmotStatus->commandStatus = EMCMOT_COMMAND_INVALID_COMMAND;
tpAbort(&emcmotDebug->coord_tp);
SET_MOTION_ERROR_FLAG(1);
} else if (*(emcmot_hal_data->spindle[spindle_num].spindle_is_oriented)) {
*(emcmot_hal_data->spindle[spindle_num].spindle_orient) = 0;
*(emcmot_hal_data->spindle[spindle_num].spindle_locked) = 1;
emcmotStatus->spindle_status[spindle_num].locked = 1;
emcmotStatus->spindle_status[spindle_num].brake = 1;
emcmotStatus->spindle_status[spindle_num].orient_state = EMCMOT_ORIENT_COMPLETE;
rtapi_print_msg(RTAPI_MSG_DBG, "SPINDLE_ORIENT complete, spindle locked");
}
}
}
}
static void do_forward_kins(void)
{
double joint_pos[EMCMOT_MAX_JOINTS] = {0,};
int joint_num, result;
emcmot_joint_t *joint;
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint_pos[joint_num] = joint->pos_fb;
}
switch (emcmotConfig->kinType) {
case KINEMATICS_IDENTITY:
kinematicsForward(joint_pos, &emcmotStatus->carte_pos_fb, &fflags,
&iflags);
if (checkAllHomed()) {
emcmotStatus->carte_pos_fb_ok = 1;
} else {
emcmotStatus->carte_pos_fb_ok = 0;
}
break;
case KINEMATICS_BOTH:
if (checkAllHomed()) {
if (!emcmotStatus->carte_pos_fb_ok) {
emcmotStatus->carte_pos_fb = emcmotStatus->world_home;
}
result =
kinematicsForward(joint_pos, &emcmotStatus->carte_pos_fb,
&fflags, &iflags);
if (result < 0) {
emcmotStatus->carte_pos_fb_ok = 0;
} else {
emcmotStatus->carte_pos_fb_ok = 1;
}
} else {
emcmotStatus->carte_pos_fb_ok = 0;
}
break;
case KINEMATICS_INVERSE_ONLY:
if ((GET_MOTION_COORD_FLAG()) || (GET_MOTION_TELEOP_FLAG())) {
emcmotStatus->carte_pos_fb = emcmotStatus->carte_pos_cmd;
emcmotStatus->carte_pos_fb_ok = 1;
} else {
emcmotStatus->carte_pos_fb_ok = 0;
}
break;
default:
emcmotStatus->carte_pos_fb_ok = 0;
break;
}
}
static void process_probe_inputs(void)
{
static int old_probeVal = 0;
unsigned char probe_type = emcmotStatus->probe_type;
char probe_suppress = probe_type & 1;
int axis_num;
char probe_whenclears = !!(probe_type & 2);
emcmotStatus->probeVal = !!*(emcmot_hal_data->probe_input);
if (emcmotStatus->probing) {
if (emcmotStatus->probeVal ^ probe_whenclears) {
emcmotStatus->probedPos = emcmotStatus->carte_pos_fb;
emcmotStatus->probing = 0;
emcmotStatus->probeTripped = 1;
tpAbort(&emcmotDebug->coord_tp);
} else if (GET_MOTION_INPOS_FLAG() && tpQueueDepth(&emcmotDebug->coord_tp) == 0) {
emcmotStatus->probedPos = emcmotStatus->carte_pos_fb;
emcmotStatus->probing = 0;
if (probe_suppress) {
emcmotStatus->probeTripped = 0;
} else if(probe_whenclears) {
reportError(_("G38.4 move finished without breaking contact."));
SET_MOTION_ERROR_FLAG(1);
} else {
reportError(_("G38.2 move finished without making contact."));
SET_MOTION_ERROR_FLAG(1);
}
}
} else if (!old_probeVal && emcmotStatus->probeVal) {
int i;
int aborted = 0;
if(!GET_MOTION_INPOS_FLAG() && tpQueueDepth(&emcmotDebug->coord_tp) &&
tpGetExecId(&emcmotDebug->coord_tp) <= 0) {
tpAbort(&emcmotDebug->coord_tp);
reportError(_("Probe tripped during non-probe MDI command."));
SET_MOTION_ERROR_FLAG(1);
}
for(i=0; i<NO_OF_KINS_JOINTS; i++) {
emcmot_joint_t *joint = &joints[i];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
if(get_homing(i)) {
set_home_abort(i);
aborted=1;
}
if(joint->free_tp.enable == 1) {
joint->free_tp.enable = 0;
if(!aborted) aborted=2;
}
}
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
emcmot_axis_t *axis;
axis = &axes[axis_num];
if (axis->teleop_tp.enable) {
axis->teleop_tp.enable = 0;
axis->teleop_tp.curr_vel = 0.0;
aborted = 3;
}
}
if(aborted == 1) {
reportError(_("Probe tripped during homing motion."));
}
if(aborted == 2) {
reportError(_("Probe tripped during a joint jog."));
}
if(aborted == 3) {
reportError(_("Probe tripped during a coordinate jog."));
}
}
old_probeVal = emcmotStatus->probeVal;
}
static void check_for_faults(void)
{
int joint_num, spindle_num;
emcmot_joint_t *joint;
int neg_limit_override, pos_limit_override;
if ( GET_MOTION_ENABLE_FLAG() != 0 ) {
if ( *(emcmot_hal_data->enable) == 0 ) {
reportError(_("motion stopped by enable input"));
emcmotDebug->enabling = 0;
}
}
for (spindle_num = 0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
if(emcmotStatus->spindle_status[spindle_num].fault && GET_MOTION_ENABLE_FLAG()){
reportError(_("spindle %d amplifier fault"), spindle_num);
emcmotDebug->enabling = 0;
}
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
if ( GET_JOINT_ACTIVE_FLAG(joint) && GET_JOINT_ENABLE_FLAG(joint) ) {
neg_limit_override = emcmotStatus->overrideLimitMask & ( 1 << (joint_num*2));
pos_limit_override = emcmotStatus->overrideLimitMask & ( 2 << (joint_num*2));
if ((GET_JOINT_PHL_FLAG(joint) && ! pos_limit_override ) ||
(GET_JOINT_NHL_FLAG(joint) && ! neg_limit_override )) {
if (get_homing(joint_num)) {
} else {
if (!GET_JOINT_ERROR_FLAG(joint)) {
reportError(_("joint %d on limit switch error"),
joint_num);
}
SET_JOINT_ERROR_FLAG(joint, 1);
emcmotDebug->enabling = 0;
}
}
if (GET_JOINT_FAULT_FLAG(joint)) {
if (!GET_JOINT_ERROR_FLAG(joint)) {
reportError(_("joint %d amplifier fault"), joint_num);
}
SET_JOINT_ERROR_FLAG(joint, 1);
emcmotDebug->enabling = 0;
}
if (GET_JOINT_FERROR_FLAG(joint)) {
if (!GET_JOINT_ERROR_FLAG(joint)) {
reportError(_("joint %d following error"), joint_num);
}
SET_JOINT_ERROR_FLAG(joint, 1);
emcmotDebug->enabling = 0;
}
}
}
}
static void set_operating_mode(void)
{
int joint_num, axis_num;
emcmot_joint_t *joint;
emcmot_axis_t *axis;
double positions[EMCMOT_MAX_JOINTS];
if (!emcmotDebug->enabling && GET_MOTION_ENABLE_FLAG()) {
tpClear(&emcmotDebug->coord_tp);
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->free_tp.enable = 0;
joint->free_tp.curr_vel = 0.0;
cubicDrain(&(joint->cubic));
if (GET_JOINT_ACTIVE_FLAG(joint)) {
SET_JOINT_INPOS_FLAG(joint, 1);
SET_JOINT_ENABLE_FLAG(joint, 0);
set_joint_homing(joint_num,0);
set_home_idle(joint_num);
}
}
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis->teleop_tp.enable = 0;
axis->teleop_tp.curr_vel = 0.0;
}
SET_MOTION_ENABLE_FLAG(0);
}
if (emcmotDebug->enabling && !GET_MOTION_ENABLE_FLAG()) {
if (*(emcmot_hal_data->eoffset_limited)) {
reportError("Starting beyond Soft Limits");
*(emcmot_hal_data->eoffset_limited) = 0;
}
initialize_external_offsets();
tpSetPos(&emcmotDebug->coord_tp, &emcmotStatus->carte_pos_cmd);
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->free_tp.curr_pos = joint->pos_cmd;
if (GET_JOINT_ACTIVE_FLAG(joint)) {
SET_JOINT_ENABLE_FLAG(joint, 1);
set_joint_homing(joint_num,0);
set_home_idle(joint_num);
}
SET_JOINT_ERROR_FLAG(joint, 0);
}
if ( !GET_MOTION_ENABLE_FLAG() ) {
if (GET_MOTION_TELEOP_FLAG()) {
sync_teleop_tp_to_carte_pos(0);
}
}
SET_MOTION_ENABLE_FLAG(1);
SET_MOTION_ERROR_FLAG(0);
}
if (emcmotDebug->teleoperating && !GET_MOTION_TELEOP_FLAG()) {
if (GET_MOTION_INPOS_FLAG()) {
tpSetPos(&emcmotDebug->coord_tp, &emcmotStatus->carte_pos_cmd);
for (joint_num = 0; joint_num < EMCMOT_MAX_JOINTS; joint_num++) {
if (joint_num < NO_OF_KINS_JOINTS) {
joint = &joints[joint_num];
cubicDrain(&(joint->cubic));
positions[joint_num] = joint->coarse_pos;
} else {
positions[joint_num] = 0;
}
}
SET_MOTION_TELEOP_FLAG(1);
SET_MOTION_ERROR_FLAG(0);
kinematicsForward(positions, &emcmotStatus->carte_pos_cmd, &fflags, &iflags);
sync_teleop_tp_to_carte_pos(-1);
} else {
emcmotDebug->teleoperating = 0;
}
} else {
if (GET_MOTION_INPOS_FLAG()) {
if (!emcmotDebug->teleoperating && GET_MOTION_TELEOP_FLAG()) {
SET_MOTION_TELEOP_FLAG(0);
if (!emcmotDebug->coordinating) {
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->free_tp.curr_pos = joint->pos_cmd;
}
}
}
}
if (emcmotDebug->coordinating && !GET_MOTION_COORD_FLAG()) {
if (GET_MOTION_INPOS_FLAG()) {
apply_ext_offsets_to_carte_pos(-1);
tpSetPos(&emcmotDebug->coord_tp, &emcmotStatus->carte_pos_cmd);
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
joint = &joints[joint_num];
cubicDrain(&(joint->cubic));
}
emcmotDebug->overriding = 0;
emcmotStatus->overrideLimitMask = 0;
SET_MOTION_COORD_FLAG(1);
SET_MOTION_TELEOP_FLAG(0);
SET_MOTION_ERROR_FLAG(0);
} else {
emcmotDebug->coordinating = 0;
}
}
if (!emcmotDebug->coordinating && GET_MOTION_COORD_FLAG()) {
if (GET_MOTION_INPOS_FLAG()) {
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->free_tp.curr_pos = joint->pos_cmd;
joint->free_tp.enable = 0;
}
SET_MOTION_COORD_FLAG(0);
SET_MOTION_TELEOP_FLAG(0);
SET_MOTION_ERROR_FLAG(0);
} else {
emcmotDebug->coordinating = 1;
}
}
}
if (!GET_MOTION_ENABLE_FLAG()) {
emcmotStatus->motion_state = EMCMOT_MOTION_DISABLED;
} else if (GET_MOTION_TELEOP_FLAG()) {
emcmotStatus->motion_state = EMCMOT_MOTION_TELEOP;
} else if (GET_MOTION_COORD_FLAG()) {
emcmotStatus->motion_state = EMCMOT_MOTION_COORD;
} else {
emcmotStatus->motion_state = EMCMOT_MOTION_FREE;
}
}
static void handle_jjogwheels(void)
{
int joint_num;
emcmot_joint_t *joint;
joint_hal_t *joint_data;
int new_jjog_counts, delta;
double distance, pos, stop_dist;
static int first_pass = 1;
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
double jaccel_limit;
joint_data = &(emcmot_hal_data->joint[joint_num]);
joint = &joints[joint_num];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
if ( (*(joint_data->jjog_accel_fraction) > 1)
|| (*(joint_data->jjog_accel_fraction) < 0) ) {
jaccel_limit = joint->acc_limit;
} else {
jaccel_limit = (*(joint_data->jjog_accel_fraction)) * joint->acc_limit;
}
new_jjog_counts = *(joint_data->jjog_counts);
delta = new_jjog_counts - joint->old_jjog_counts;
joint->old_jjog_counts = new_jjog_counts;
if ( first_pass ) {
continue;
}
if ( delta == 0 ) {
continue;
}
if (GET_MOTION_TELEOP_FLAG()) {
joint->free_tp.enable = 0;
return;
}
if (GET_MOTION_COORD_FLAG()) {
continue;
}
if (!GET_MOTION_ENABLE_FLAG()) {
continue;
}
if ( *(joint_data->jjog_enable) == 0 ) {
continue;
}
if (get_homing_is_active() ) {
continue;
}
if (joint->kb_jjog_active) {
continue;
}
if (emcmotStatus->net_feed_scale < 0.0001 ) {
break;
}
if (get_home_needs_unlock_first(joint_num) ) {
reportError("Can't wheel jog locking joint_num=%d",joint_num);
continue;
}
if (get_home_is_synchronized(joint_num)) {
if (emcmotConfig->kinType == KINEMATICS_IDENTITY) {
rtapi_print_msg(RTAPI_MSG_ERR,
"Homing is REQUIRED to wheel jog requested coordinate\n"
"because joint (%d) home_sequence is synchronized (%d)\n"
,joint_num,get_home_sequence(joint_num) );
} else {
rtapi_print_msg(RTAPI_MSG_ERR,
"Cannot wheel jog joint %d because home_sequence synchronized (%d)\n"
,joint_num,get_home_sequence(joint_num) );
}
continue;
}
distance = delta * *(joint_data->jjog_scale);
if (distance > 0.0 && GET_JOINT_PHL_FLAG(joint)) {
continue;
}
if (distance < 0.0 && GET_JOINT_NHL_FLAG(joint)) {
continue;
}
pos = joint->free_tp.pos_cmd + distance;
refresh_jog_limits(joint,joint_num);
if (pos > joint->max_jog_limit) {
continue;
}
if (pos < joint->min_jog_limit) {
continue;
}
if ( *(joint_data->jjog_vel_mode) ) {
double v = joint->vel_limit * emcmotStatus->net_feed_scale;
stop_dist = v * v / ( 2 * jaccel_limit);
if ( pos > joint->pos_cmd + stop_dist ) {
pos = joint->pos_cmd + stop_dist;
} else if ( pos < joint->pos_cmd - stop_dist ) {
pos = joint->pos_cmd - stop_dist;
}
}
joint->free_tp.pos_cmd = pos;
joint->free_tp.max_vel = joint->vel_limit;
joint->free_tp.max_acc = jaccel_limit;
joint->wheel_jjog_active = 1;
joint->free_tp.enable = 1;
SET_JOINT_ERROR_FLAG(joint, 0);
clearHomes(joint_num);
}
first_pass = 0;
}
static void handle_ajogwheels(void)
{
int axis_num;
emcmot_axis_t *axis;
axis_hal_t *axis_data;
int new_ajog_counts, delta;
double distance, pos, stop_dist;
static int first_pass = 1;
if ( emcmotStatus->on_soft_limit ) { return; }
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
double aaccel_limit;
axis = &axes[axis_num];
axis_data = &(emcmot_hal_data->axis[axis_num]);
if ( (*(axis_data->ajog_accel_fraction) > 1)
|| (*(axis_data->ajog_accel_fraction) < 0) ) {
aaccel_limit = axis->acc_limit;
} else {
aaccel_limit = *(axis_data->ajog_accel_fraction) * axis->acc_limit;
}
new_ajog_counts = *(axis_data->ajog_counts);
delta = new_ajog_counts - axis->old_ajog_counts;
axis->old_ajog_counts = new_ajog_counts;
if ( first_pass ) { continue; }
if ( delta == 0 ) {
continue;
}
if (!GET_MOTION_TELEOP_FLAG()) {
axis->teleop_tp.enable = 0;
return;
}
if (!GET_MOTION_TELEOP_FLAG()) { continue; }
if (!GET_MOTION_ENABLE_FLAG()) { continue; }
if ( *(axis_data->ajog_enable) == 0 ) { continue; }
if (get_homing_is_active() ) { continue; }
if (axis->kb_ajog_active) { continue; }
if (axis->locking_joint >= 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"Cannot wheel jog a locking indexer AXIS_%c\n",
"XYZABCUVW"[axis_num]);
continue;
}
distance = delta * *(axis_data->ajog_scale);
pos = axis->teleop_tp.pos_cmd + distance;
if ( *(axis_data->ajog_vel_mode) ) {
double v = axis->vel_limit;
stop_dist = v * v / ( 2 * aaccel_limit);
if ( pos > axis->pos_cmd + stop_dist ) {
pos = axis->pos_cmd + stop_dist;
} else if ( pos < axis->pos_cmd - stop_dist ) {
pos = axis->pos_cmd - stop_dist;
}
}
if (pos > axis->max_pos_limit) { break; }
if (pos < axis->min_pos_limit) { break; }
axis->teleop_tp.pos_cmd = pos;
axis->teleop_tp.max_vel = axis->vel_limit;
axis->teleop_tp.max_acc = aaccel_limit;
axis->wheel_ajog_active = 1;
axis->teleop_tp.enable = 1;
}
first_pass = 0;
}
static void get_pos_cmds(long period)
{
int joint_num, axis_num, result;
emcmot_joint_t *joint;
emcmot_axis_t *axis;
double positions[EMCMOT_MAX_JOINTS];
double vel_lim;
int onlimit = 0;
int joint_limit[EMCMOT_MAX_JOINTS][2];
int violated_teleop_limit = 0;
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
positions[joint_num] = joint->coarse_pos;
}
while ( joint_num < EMCMOT_MAX_JOINTS ) {
positions[joint_num++] = 0.0;
}
switch ( emcmotStatus->motion_state) {
case EMCMOT_MOTION_FREE:
SET_MOTION_INPOS_FLAG(1);
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
if (IS_EXTRA_JOINT(joint_num) && get_homed(joint_num)) continue;
if(joint->acc_limit > emcmotStatus->acc)
joint->acc_limit = emcmotStatus->acc;
if ( get_home_is_idle(joint_num) ) {
vel_lim = joint->vel_limit * emcmotStatus->net_feed_scale;
if (vel_lim > joint->vel_limit) {
vel_lim = joint->vel_limit;
}
if (vel_lim < joint->free_tp.max_vel)
joint->free_tp.max_vel = vel_lim;
} else {
}
if (joint->wheel_jjog_active) {
double jaccel_limit;
joint_hal_t *joint_data;
joint_data = &(emcmot_hal_data->joint[joint_num]);
if ( (*(joint_data->jjog_accel_fraction) > 1)
|| (*(joint_data->jjog_accel_fraction) < 0) ) {
jaccel_limit = joint->acc_limit;
} else {
jaccel_limit = (*(joint_data->jjog_accel_fraction)) * joint->acc_limit;
}
joint->free_tp.max_acc = jaccel_limit;
} else {
joint->free_tp.max_acc = joint->acc_limit;
}
simple_tp_update(&(joint->free_tp), servo_period );
joint->pos_cmd = joint->free_tp.curr_pos;
joint->vel_cmd = joint->free_tp.curr_vel;
joint->acc_cmd = 0.0;
joint->coarse_pos = joint->free_tp.curr_pos;
if ( joint->free_tp.active ) {
SET_JOINT_INPOS_FLAG(joint, 0);
SET_MOTION_INPOS_FLAG(0);
set_joint_at_home(joint_num,0);
if ( emcmotStatus->overrideLimitMask ) {
emcmotDebug->overriding = 1;
}
} else {
SET_JOINT_INPOS_FLAG(joint, 1);
joint->kb_jjog_active = 0;
joint->wheel_jjog_active = 0;
}
}
if ( (emcmotDebug->overriding ) && ( GET_MOTION_INPOS_FLAG() ) ) {
emcmotStatus->overrideLimitMask = 0;
emcmotDebug->overriding = 0;
}
switch (emcmotConfig->kinType) {
case KINEMATICS_IDENTITY:
kinematicsForward(positions, &emcmotStatus->carte_pos_cmd, &fflags, &iflags);
if (checkAllHomed()) {
emcmotStatus->carte_pos_cmd_ok = 1;
} else {
emcmotStatus->carte_pos_cmd_ok = 0;
}
break;
case KINEMATICS_BOTH:
if (checkAllHomed()) {
if (!emcmotStatus->carte_pos_cmd_ok) {
emcmotStatus->carte_pos_cmd = emcmotStatus->world_home;
}
result =
kinematicsForward(positions, &emcmotStatus->carte_pos_cmd, &fflags, &iflags);
if (result < 0) {
emcmotStatus->carte_pos_cmd_ok = 0;
} else {
emcmotStatus->carte_pos_cmd_ok = 1;
}
} else {
emcmotStatus->carte_pos_cmd_ok = 0;
}
break;
case KINEMATICS_INVERSE_ONLY:
emcmotStatus->carte_pos_cmd_ok = 0;
break;
default:
emcmotStatus->carte_pos_cmd_ok = 0;
break;
}
break;
case EMCMOT_MOTION_COORD:
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis->teleop_tp.enable = 0;
axis->teleop_tp.curr_vel = 0.0;
}
while (cubicNeedNextPoint(&(joints[0].cubic))) {
tpRunCycle(&emcmotDebug->coord_tp, period);
tpGetPos(&emcmotDebug->coord_tp, &emcmotStatus->carte_pos_cmd);
if ( update_coord_with_bound() ) {
ext_offset_coord_limit = 1;
} else {
ext_offset_coord_limit = 0;
}
result = kinematicsInverse(&emcmotStatus->carte_pos_cmd, positions,
&iflags, &fflags);
if(result == 0)
{
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
if(!isfinite(positions[joint_num]))
{
reportError(_("kinematicsInverse gave non-finite joint location on joint %d"),
joint_num);
SET_MOTION_ERROR_FLAG(1);
SET_MOTION_ENABLE_FLAG(0);
emcmotDebug->enabling = 0;
break;
}
joint = &joints[joint_num];
joint->coarse_pos = positions[joint_num];
cubicAddPoint(&(joint->cubic), joint->coarse_pos);
}
}
else
{
reportError(_("kinematicsInverse failed"));
SET_MOTION_ERROR_FLAG(1);
SET_MOTION_ENABLE_FLAG(0);
emcmotDebug->enabling = 0;
break;
}
}
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->pos_cmd = cubicInterpolate(&(joint->cubic), 0, &(joint->vel_cmd), &(joint->acc_cmd), 0);
}
SET_MOTION_INPOS_FLAG(0);
if (tpIsDone(&emcmotDebug->coord_tp)) {
SET_MOTION_INPOS_FLAG(1);
}
break;
case EMCMOT_MOTION_TELEOP:
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
if(axis->teleop_tp.max_vel > axis->vel_limit) {
axis->teleop_tp.max_vel = axis->vel_limit;
}
if (update_teleop_with_check(axis_num,&(axis->teleop_tp) )) {
violated_teleop_limit = 1;
ext_offset_teleop_limit = 1;
} else {
axis->teleop_vel_cmd = axis->teleop_tp.curr_vel;
axis->pos_cmd = axis->teleop_tp.curr_pos;
}
if(!axis->teleop_tp.active) {
axis->kb_ajog_active = 0;
axis->wheel_ajog_active = 0;
}
if (axis->ext_offset_tp.enable) {
if (update_teleop_with_check(axis_num,&(axis->ext_offset_tp)) ) {
violated_teleop_limit = 1;
ext_offset_teleop_limit = 1;
}
}
}
if (!violated_teleop_limit) {
ext_offset_teleop_limit = 0;
ext_offset_coord_limit = 0; }
sync_carte_pos_to_teleop_tp(+1);
result = kinematicsInverse(&emcmotStatus->carte_pos_cmd, positions, &iflags, &fflags);
if(result == 0)
{
for (joint_num = 0; joint_num < NO_OF_KINS_JOINTS; joint_num++) {
if(!isfinite(positions[joint_num]))
{
reportError(_("kinematicsInverse gave non-finite joint location on joint %d"),
joint_num);
SET_MOTION_ERROR_FLAG(1);
SET_MOTION_ENABLE_FLAG(0);
emcmotDebug->enabling = 0;
break;
}
joint = &joints[joint_num];
joint->coarse_pos = positions[joint_num];
cubicAddPoint(&(joint->cubic), joint->coarse_pos);
joint->pos_cmd = cubicInterpolate(&(joint->cubic), 0, &(joint->vel_cmd), &(joint->acc_cmd), 0);
}
}
else
{
reportError(_("kinematicsInverse failed"));
SET_MOTION_ERROR_FLAG(1);
SET_MOTION_ENABLE_FLAG(0);
emcmotDebug->enabling = 0;
break;
}
break;
case EMCMOT_MOTION_DISABLED:
emcmotStatus->carte_pos_cmd = emcmotStatus->carte_pos_fb;
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint->pos_cmd = joint->pos_fb;
joint->vel_cmd = 0.0;
joint->acc_cmd = 0.0;
}
break;
default:
break;
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
if ((!GET_JOINT_ACTIVE_FLAG(joint)) || (!get_homed(joint_num))) {
continue;
}
if (joint->pos_cmd > joint->max_pos_limit) {
joint_limit[joint_num][1] = 1;
onlimit = 1;
}
else if (joint->pos_cmd < joint->min_pos_limit) {
joint_limit[joint_num][0] = 1;
onlimit = 1;
}
}
if ( onlimit ) {
if ( ! emcmotStatus->on_soft_limit ) {
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
if (joint_limit[joint_num][0] == 1) {
joint = &joints[joint_num];
reportError(_("Exceeded NEGATIVE soft limit (%.5f) on joint %d\n"),
joint->min_pos_limit, joint_num);
if (emcmotConfig->kinType == KINEMATICS_IDENTITY) {
reportError(_("Stop, fix joints axis LIMITS, then Restart"));
} else {
reportError(_("Hint: switch to joint mode to jog off soft limit"));
}
} else if (joint_limit[joint_num][1] == 1) {
joint = &joints[joint_num];
reportError(_("Exceeded POSITIVE soft limit (%.5f) on joint %d\n"),
joint->max_pos_limit,joint_num);
if (emcmotConfig->kinType == KINEMATICS_IDENTITY) {
reportError(_("Stop, fix joints and axis LIMITS, then Restart"));
} else {
reportError(_("Hint: switch to joint mode to jog off soft limit"));
}
}
}
SET_MOTION_ERROR_FLAG(1);
emcmotStatus->on_soft_limit = 1;
}
} else {
emcmotStatus->on_soft_limit = 0;
}
if ( emcmotDebug->teleoperating
&& GET_MOTION_TELEOP_FLAG()
&& emcmotStatus->on_soft_limit ) {
SET_MOTION_ERROR_FLAG(1);
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis->teleop_tp.enable = 0;
axis->teleop_tp.curr_vel = 0.0;
}
}
if (ext_offset_teleop_limit || ext_offset_coord_limit) {
*(emcmot_hal_data->eoffset_limited) = 1;
} else {
*(emcmot_hal_data->eoffset_limited) = 0;
}
}
static void compute_screw_comp(void)
{
int joint_num;
emcmot_joint_t *joint;
emcmot_comp_t *comp;
double dpos;
double a_max, v_max, v, s_to_go, ds_stop, ds_vel, ds_acc, dv_acc;
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
comp = &(joint->comp);
if ( comp->entries > 0 ) {
while ( joint->pos_cmd < comp->entry->nominal ) {
comp->entry--;
}
while ( joint->pos_cmd >= (comp->entry+1)->nominal ) {
comp->entry++;
}
dpos = joint->pos_cmd - comp->entry->nominal;
if (joint->vel_cmd > 0.0) {
joint->backlash_corr = comp->entry->fwd_trim +
comp->entry->fwd_slope * dpos;
} else if (joint->vel_cmd < 0.0) {
joint->backlash_corr = comp->entry->rev_trim +
comp->entry->rev_slope * dpos;
} else {
}
} else {
if (joint->vel_cmd > 0.0) {
joint->backlash_corr = 0.5 * joint->backlash;
} else if (joint->vel_cmd < 0.0) {
joint->backlash_corr = -0.5 * joint->backlash;
} else {
}
}
v_max = 0.5 * joint->vel_limit * emcmotStatus->net_feed_scale;
a_max = 0.5 * joint->acc_limit;
v = joint->backlash_vel;
if (joint->backlash_corr >= joint->backlash_filt) {
s_to_go = joint->backlash_corr - joint->backlash_filt;
if (s_to_go > 0) {
ds_vel = v * servo_period;
dv_acc = a_max * servo_period;
ds_stop = 0.5 * (v + dv_acc) *
(v + dv_acc) / a_max;
if (s_to_go <= ds_stop + ds_vel) {
if (v > dv_acc) {
ds_acc = 0.5 * dv_acc * servo_period;
joint->backlash_vel -= dv_acc;
joint->backlash_filt += ds_vel - ds_acc;
} else {
joint->backlash_vel = 0.0;
joint->backlash_filt = joint->backlash_corr;
}
} else {
if (v + dv_acc > v_max) {
dv_acc = v_max - v;
}
ds_acc = 0.5 * dv_acc * servo_period;
ds_stop = 0.5 * (v + dv_acc) *
(v + dv_acc) / a_max;
if (s_to_go > ds_stop + ds_vel + ds_acc) {
joint->backlash_vel += dv_acc;
joint->backlash_filt += ds_vel + ds_acc;
} else {
joint->backlash_filt += ds_vel;
}
}
} else if (s_to_go < 0) {
joint->backlash_vel = 0.0;
joint->backlash_filt = joint->backlash_corr;
}
} else {
s_to_go = joint->backlash_filt - joint->backlash_corr;
if (s_to_go > 0) {
ds_vel = -v * servo_period;
dv_acc = a_max * servo_period;
ds_stop = 0.5 * (v - dv_acc) *
(v - dv_acc) / a_max;
if (s_to_go <= ds_stop + ds_vel) {
if (-v > dv_acc) {
ds_acc = 0.5 * dv_acc * servo_period;
joint->backlash_vel += dv_acc;
joint->backlash_filt -= ds_vel - ds_acc;
} else {
joint->backlash_vel = 0.0;
joint->backlash_filt = joint->backlash_corr;
}
} else {
if (-v + dv_acc > v_max) {
dv_acc = v_max + v;
}
ds_acc = 0.5 * dv_acc * servo_period;
ds_stop = 0.5 * (v - dv_acc) *
(v - dv_acc) / a_max;
if (s_to_go > ds_stop + ds_vel + ds_acc) {
joint->backlash_vel -= dv_acc;
joint->backlash_filt -= ds_vel + ds_acc;
} else {
joint->backlash_filt -= ds_vel;
}
}
} else if (s_to_go < 0) {
joint->backlash_vel = 0.0;
joint->backlash_filt = joint->backlash_corr;
}
}
}
}
static void output_to_hal(void)
{
int joint_num, axis_num, spindle_num;
emcmot_joint_t *joint;
emcmot_axis_t *axis;
joint_hal_t *joint_data;
axis_hal_t *axis_data;
static int old_motion_index[EMCMOT_MAX_SPINDLES] = {0};
static int old_hal_index[EMCMOT_MAX_SPINDLES] = {0};
*(emcmot_hal_data->motion_enabled) = GET_MOTION_ENABLE_FLAG();
*(emcmot_hal_data->in_position) = GET_MOTION_INPOS_FLAG();
*(emcmot_hal_data->coord_mode) = GET_MOTION_COORD_FLAG();
*(emcmot_hal_data->teleop_mode) = GET_MOTION_TELEOP_FLAG();
*(emcmot_hal_data->coord_error) = GET_MOTION_ERROR_FLAG();
*(emcmot_hal_data->on_soft_limit) = emcmotStatus->on_soft_limit;
for (spindle_num = 0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
if(emcmotStatus->spindle_status[spindle_num].css_factor) {
double denom = fabs(emcmotStatus->spindle_status[spindle_num].xoffset
- emcmotStatus->carte_pos_cmd.tran.x);
double speed;
double maxpositive;
if(denom > 0) speed = emcmotStatus->spindle_status[spindle_num].css_factor / denom;
else speed = emcmotStatus->spindle_status[spindle_num].speed;
speed = speed * emcmotStatus->spindle_status[spindle_num].net_scale;
maxpositive = fabs(emcmotStatus->spindle_status[spindle_num].speed);
if(speed < -maxpositive)
speed = -maxpositive;
if(speed > maxpositive)
speed = maxpositive;
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out) = speed;
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out_rps) = speed/60.;
} else {
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out) =
emcmotStatus->spindle_status[spindle_num].speed *
emcmotStatus->spindle_status[spindle_num].net_scale;
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out_rps) =
emcmotStatus->spindle_status[spindle_num].speed *
emcmotStatus->spindle_status[spindle_num].net_scale / 60.;
}
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out_abs) =
fabs(*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out));
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out_rps_abs) =
fabs(*(emcmot_hal_data->spindle[spindle_num].spindle_speed_out_rps));
*(emcmot_hal_data->spindle[spindle_num].spindle_speed_cmd_rps) =
emcmotStatus->spindle_status[spindle_num].speed / 60.;
*(emcmot_hal_data->spindle[spindle_num].spindle_on) =
((emcmotStatus->spindle_status[spindle_num].speed *
emcmotStatus->spindle_status[spindle_num].net_scale) != 0) ? 1 : 0;
*(emcmot_hal_data->spindle[spindle_num].spindle_forward) =
(*emcmot_hal_data->spindle[spindle_num].spindle_speed_out > 0) ? 1 : 0;
*(emcmot_hal_data->spindle[spindle_num].spindle_reverse) =
(*emcmot_hal_data->spindle[spindle_num].spindle_speed_out < 0) ? 1 : 0;
*(emcmot_hal_data->spindle[spindle_num].spindle_brake) =
(emcmotStatus->spindle_status[spindle_num].brake != 0) ? 1 : 0;
}
*(emcmot_hal_data->program_line) = emcmotStatus->id;
*(emcmot_hal_data->tp_reverse) = emcmotStatus->reverse_run;
*(emcmot_hal_data->motion_type) = emcmotStatus->motionType;
*(emcmot_hal_data->distance_to_go) = emcmotStatus->distance_to_go;
if(GET_MOTION_COORD_FLAG()) {
*(emcmot_hal_data->current_vel) = emcmotStatus->current_vel;
*(emcmot_hal_data->requested_vel) = emcmotStatus->requested_vel;
} else if (GET_MOTION_TELEOP_FLAG()) {
int i;
double v2 = 0.0;
for(i=0; i < EMCMOT_MAX_AXIS; i++)
if(axes[i].teleop_tp.active)
v2 += axes[i].teleop_vel_cmd * axes[i].teleop_vel_cmd;
if(v2 > 0.0)
emcmotStatus->current_vel = (*emcmot_hal_data->current_vel) = sqrt(v2);
else
emcmotStatus->current_vel = (*emcmot_hal_data->current_vel) = 0.0;
*(emcmot_hal_data->requested_vel) = 0.0;
} else {
int i;
double v2 = 0.0;
for(i=0; i < ALL_JOINTS; i++)
if(GET_JOINT_ACTIVE_FLAG(&(joints[i])) && joints[i].free_tp.active)
v2 += joints[i].vel_cmd * joints[i].vel_cmd;
if(v2 > 0.0)
emcmotStatus->current_vel = (*emcmot_hal_data->current_vel) = sqrt(v2);
else
emcmotStatus->current_vel = (*emcmot_hal_data->current_vel) = 0.0;
*(emcmot_hal_data->requested_vel) = 0.0;
}
emcmot_hal_data->debug_bit_0 = joints[1].free_tp.active;
emcmot_hal_data->debug_bit_1 = emcmotStatus->enables_new & AF_ENABLED;
emcmot_hal_data->debug_float_0 = emcmotStatus->spindle_status[0].speed;
emcmot_hal_data->debug_float_1 = emcmotStatus->spindleSync;
emcmot_hal_data->debug_float_2 = emcmotStatus->vel;
emcmot_hal_data->debug_float_3 = emcmotStatus->spindle_status[0].net_scale;
emcmot_hal_data->debug_s32_0 = emcmotStatus->overrideLimitMask;
emcmot_hal_data->debug_s32_1 = emcmotStatus->tcqlen;
for (spindle_num = 0; spindle_num < emcmotConfig->numSpindles; spindle_num++){
if(emcmotStatus->spindle_status[spindle_num].spindle_index_enable
&& !old_motion_index[spindle_num]) {
*emcmot_hal_data->spindle[spindle_num].spindle_index_enable = 1;
rtapi_print_msg(RTAPI_MSG_DBG, "setting index-enable on spindle %d\n", spindle_num);
}
if(!*emcmot_hal_data->spindle[spindle_num].spindle_index_enable
&& old_hal_index[spindle_num]) {
emcmotStatus->spindle_status[spindle_num].spindle_index_enable = 0;
}
old_motion_index[spindle_num] =
emcmotStatus->spindle_status[spindle_num].spindle_index_enable;
old_hal_index[spindle_num] =
*emcmot_hal_data->spindle[spindle_num].spindle_index_enable;
}
*(emcmot_hal_data->tooloffset_x) = emcmotStatus->tool_offset.tran.x;
*(emcmot_hal_data->tooloffset_y) = emcmotStatus->tool_offset.tran.y;
*(emcmot_hal_data->tooloffset_z) = emcmotStatus->tool_offset.tran.z;
*(emcmot_hal_data->tooloffset_a) = emcmotStatus->tool_offset.a;
*(emcmot_hal_data->tooloffset_b) = emcmotStatus->tool_offset.b;
*(emcmot_hal_data->tooloffset_c) = emcmotStatus->tool_offset.c;
*(emcmot_hal_data->tooloffset_u) = emcmotStatus->tool_offset.u;
*(emcmot_hal_data->tooloffset_v) = emcmotStatus->tool_offset.v;
*(emcmot_hal_data->tooloffset_w) = emcmotStatus->tool_offset.w;
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint_data = &(emcmot_hal_data->joint[joint_num]);
joint->motor_pos_cmd =
joint->pos_cmd + joint->backlash_filt + joint->motor_offset;
*(joint_data->motor_offset) = joint->motor_offset;
*(joint_data->motor_pos_cmd) = joint->motor_pos_cmd;
*(joint_data->joint_pos_cmd) = joint->pos_cmd;
*(joint_data->joint_pos_fb) = joint->pos_fb;
*(joint_data->amp_enable) = GET_JOINT_ENABLE_FLAG(joint);
*(joint_data->coarse_pos_cmd) = joint->coarse_pos;
*(joint_data->joint_vel_cmd) = joint->vel_cmd;
*(joint_data->joint_acc_cmd) = joint->acc_cmd;
*(joint_data->backlash_corr) = joint->backlash_corr;
*(joint_data->backlash_filt) = joint->backlash_filt;
*(joint_data->backlash_vel) = joint->backlash_vel;
*(joint_data->f_error) = joint->ferror;
*(joint_data->f_error_lim) = joint->ferror_limit;
*(joint_data->free_pos_cmd) = joint->free_tp.pos_cmd;
*(joint_data->free_vel_lim) = joint->free_tp.max_vel;
*(joint_data->free_tp_enable) = joint->free_tp.enable;
*(joint_data->kb_jjog_active) = joint->kb_jjog_active;
*(joint_data->wheel_jjog_active) = joint->wheel_jjog_active;
*(joint_data->active) = GET_JOINT_ACTIVE_FLAG(joint);
*(joint_data->in_position) = GET_JOINT_INPOS_FLAG(joint);
*(joint_data->error) = GET_JOINT_ERROR_FLAG(joint);
*(joint_data->phl) = GET_JOINT_PHL_FLAG(joint);
*(joint_data->nhl) = GET_JOINT_NHL_FLAG(joint);
*(joint_data->f_errored) = GET_JOINT_FERROR_FLAG(joint);
*(joint_data->faulted) = GET_JOINT_FAULT_FLAG(joint);
if ( !GET_MOTION_ENABLE_FLAG() && (joint_is_lockable(joint_num))) {
*(joint_data->unlock) = 0;
}
if (IS_EXTRA_JOINT(joint_num) && get_homed(joint_num)) {
extrajoint_hal_t *ejoint_data;
int e = joint_num - NO_OF_KINS_JOINTS;
ejoint_data = &(emcmot_hal_data->ejoint[e]);
*(joint_data->motor_pos_cmd) = *(ejoint_data->posthome_cmd)
+ joint->motor_offset;
continue;
}
}
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis_data = &(emcmot_hal_data->axis[axis_num]);
*(axis_data->teleop_vel_cmd) = axis->teleop_vel_cmd;
*(axis_data->teleop_pos_cmd) = axis->teleop_tp.pos_cmd;
*(axis_data->teleop_vel_lim) = axis->teleop_tp.max_vel;
*(axis_data->teleop_tp_enable) = axis->teleop_tp.enable;
*(axis_data->kb_ajog_active) = axis->kb_ajog_active;
*(axis_data->wheel_ajog_active) = axis->wheel_ajog_active;
*(axis_data->pos_cmd) = *pcmd_p[axis_num]
- axis->ext_offset_tp.curr_pos;
}
}
static void update_status(void)
{
int joint_num, axis_num, dio, aio;
emcmot_joint_t *joint;
emcmot_joint_status_t *joint_status;
emcmot_axis_t *axis;
emcmot_axis_status_t *axis_status;
#ifdef WATCH_FLAGS
static int old_joint_flags[8];
static int old_motion_flag;
#endif
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
joint = &joints[joint_num];
joint_status = &(emcmotStatus->joint_status[joint_num]);
#ifdef WATCH_FLAGS
if ( old_joint_flags[joint_num] != joint->flag ) {
rtapi_print ( "Joint %d flag %04X -> %04X\n", joint_num, old_joint_flags[joint_num], joint->flag );
old_joint_flags[joint_num] = joint->flag;
}
#endif
joint_status->flag = joint->flag;
joint_status->homing = get_homing(joint_num);
joint_status->homed = get_homed(joint_num);
joint_status->pos_cmd = joint->pos_cmd;
joint_status->pos_fb = joint->pos_fb;
joint_status->vel_cmd = joint->vel_cmd;
joint_status->acc_cmd = joint->acc_cmd;
joint_status->ferror = joint->ferror;
joint_status->ferror_high_mark = joint->ferror_high_mark;
joint_status->backlash = joint->backlash;
joint_status->max_pos_limit = joint->max_pos_limit;
joint_status->min_pos_limit = joint->min_pos_limit;
joint_status->min_ferror = joint->min_ferror;
joint_status->max_ferror = joint->max_ferror;
}
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis_status = &(emcmotStatus->axis_status[axis_num]);
axis_status->teleop_vel_cmd = axis->teleop_vel_cmd;
axis_status->max_pos_limit = axis->max_pos_limit;
axis_status->min_pos_limit = axis->min_pos_limit;
}
emcmotStatus->eoffset_pose.tran.x = (&axes[0])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.tran.y = (&axes[1])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.tran.z = (&axes[2])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.a = (&axes[3])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.b = (&axes[4])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.c = (&axes[5])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.u = (&axes[6])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.v = (&axes[7])->ext_offset_tp.curr_pos;
emcmotStatus->eoffset_pose.w = (&axes[8])->ext_offset_tp.curr_pos;
emcmotStatus->external_offsets_applied = *(emcmot_hal_data->eoffset_active);
for (dio = 0; dio < emcmotConfig->numDIO; dio++) {
emcmotStatus->synch_di[dio] = *(emcmot_hal_data->synch_di[dio]);
emcmotStatus->synch_do[dio] = *(emcmot_hal_data->synch_do[dio]);
}
for (aio = 0; aio < emcmotConfig->numAIO; aio++) {
emcmotStatus->analog_input[aio] = *(emcmot_hal_data->analog_input[aio]);
emcmotStatus->analog_output[aio] = *(emcmot_hal_data->analog_output[aio]);
}
emcmotStatus->depth = tpQueueDepth(&emcmotDebug->coord_tp);
emcmotStatus->activeDepth = tpActiveDepth(&emcmotDebug->coord_tp);
emcmotStatus->id = tpGetExecId(&emcmotDebug->coord_tp);
emcmotStatus->reverse_run = emcmotDebug->coord_tp.reverse_run;
emcmotStatus->motionType = tpGetMotionType(&emcmotDebug->coord_tp);
emcmotStatus->queueFull = tcqFull(&emcmotDebug->coord_tp.queue);
if (emcmotDebug->stepping && emcmotDebug->idForStep != emcmotStatus->id) {
tpPause(&emcmotDebug->coord_tp);
emcmotDebug->stepping = 0;
emcmotStatus->paused = 1;
}
#ifdef WATCH_FLAGS
if ( old_motion_flag != emcmotStatus->motionFlag ) {
rtapi_print ( "Motion flag %04X -> %04X\n", old_motion_flag, emcmotStatus->motionFlag );
old_motion_flag = emcmotStatus->motionFlag;
}
#endif
}
static void sync_teleop_tp_to_carte_pos(int extfactor)
{
int axis_num;
emcmot_axis_t *axis;
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis->teleop_tp.curr_pos = *pcmd_p[axis_num]
+ extfactor * axis->ext_offset_tp.curr_pos;
}
}
static void sync_carte_pos_to_teleop_tp(int extfactor)
{
int axis_num;
emcmot_axis_t *axis;
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
*pcmd_p[axis_num] = axis->teleop_tp.curr_pos
+ extfactor * axis->ext_offset_tp.curr_pos;
}
}
static void apply_ext_offsets_to_carte_pos(int extfactor)
{
int axis_num;
emcmot_axis_t *axis;
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
*pcmd_p[axis_num] = *pcmd_p[axis_num]
+ extfactor * axis->ext_offset_tp.curr_pos;
}
}
static void initialize_external_offsets()
{
int axis_num;
emcmot_axis_t *axis;
axis_hal_t *axis_data;
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis_data = &(emcmot_hal_data->axis[axis_num]);
*(axis_data->external_offset) = 0;
*(axis_data->external_offset_requested) = 0;
axis->ext_offset_tp.pos_cmd = 0;
axis->ext_offset_tp.curr_pos = 0;
axis->ext_offset_tp.curr_vel = 0;
}
}
static void plan_external_offsets(void)
{
static int first_pass = 1;
int axis_num;
emcmot_axis_t *axis;
axis_hal_t *axis_data;
int new_eoffset_counts, delta;
static int last_eoffset_enable[EMCMOT_MAX_AXIS];
*(emcmot_hal_data->eoffset_active) = 0;
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
axis->ext_offset_tp.max_vel = axis->ext_offset_vel_limit;
axis->ext_offset_tp.max_acc = axis->ext_offset_acc_limit;
axis_data = &(emcmot_hal_data->axis[axis_num]);
new_eoffset_counts = *(axis_data->eoffset_counts);
delta = new_eoffset_counts - axis->old_eoffset_counts;
axis->old_eoffset_counts = new_eoffset_counts;
*(axis_data->external_offset) = axis->ext_offset_tp.curr_pos;
axis->ext_offset_tp.enable = 1;
if ( first_pass ) {
*(axis_data->external_offset) = 0;
continue;
}
ext_offset_epsilon = TINY_DP(axis->ext_offset_tp.max_acc,servo_period);
if (fabs(*(axis_data->external_offset)) > ext_offset_epsilon) {
*(emcmot_hal_data->eoffset_active) = 1;
}
if ( !*(axis_data->eoffset_enable) ) {
axis->ext_offset_tp.enable = 0;
if ( last_eoffset_enable[axis_num]
&& (fabs(*(axis_data->external_offset)) > ext_offset_epsilon)
&& GET_MOTION_ENABLE_FLAG()
&& axis->ext_offset_tp.enable
) {
#if 1
rtapi_print_msg(RTAPI_MSG_NONE,
"*** Axis_%c External Offset=%.4g eps=%.4g\n"
"*** External Offset disabled while NON-zero\n"
"*** To clear: re-enable & zero or use Machine-Off\n",
"XYZABCUVW"[axis_num],
*(axis_data->external_offset),
ext_offset_epsilon);
#else#endif
}
last_eoffset_enable[axis_num] = 0;
continue; }
last_eoffset_enable[axis_num] = 1;
if (*(axis_data->eoffset_clear)) {
axis->ext_offset_tp.pos_cmd = 0;
*(axis_data->external_offset_requested) = 0;
continue;
}
if ( delta == 0 ) { continue; }
if ( !checkAllHomed() ) { continue; }
if ( !GET_MOTION_ENABLE_FLAG() ) { continue; }
axis->ext_offset_tp.pos_cmd += delta * *(axis_data->eoffset_scale);
*(axis_data->external_offset_requested) = axis->ext_offset_tp.pos_cmd;
} first_pass = 0;
}
static int update_teleop_with_check(int axis_num,simple_tp_t *the_tp)
{
double save_curr_pos;
emcmot_axis_t *axis = &axes[axis_num];
save_curr_pos = the_tp->curr_pos;
simple_tp_update(the_tp, servo_period );
if ( (0 == axis->max_pos_limit) && (0 == axis->min_pos_limit) ) {
return 0;
}
if ( (axis->ext_offset_tp.curr_pos + axis->teleop_tp.curr_pos)
>= axis->max_pos_limit) {
the_tp->curr_pos = save_curr_pos;
the_tp->curr_vel = 0;
return 1;
}
if ( (axis->ext_offset_tp.curr_pos + axis->teleop_tp.curr_pos)
<= axis->min_pos_limit) {
the_tp->curr_pos = save_curr_pos;
the_tp->curr_vel = 0;
return 1;
}
return 0;
}
static int update_coord_with_bound(void)
{
int axis_num;
int ans = 0;
emcmot_axis_t *axis;
double save_pos_cmd[EMCMOT_MAX_AXIS];
double save_offset_cmd[EMCMOT_MAX_AXIS];
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
save_pos_cmd[axis_num] = *pcmd_p[axis_num];
save_offset_cmd[axis_num] = axis->ext_offset_tp.pos_cmd;
simple_tp_update(&(axis->ext_offset_tp), servo_period );
}
apply_ext_offsets_to_carte_pos(+1);
for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
axis = &axes[axis_num];
if ( (0 == axis->max_pos_limit) && (0 == axis->min_pos_limit) ) {
continue;
}
if (axis->ext_offset_tp.curr_pos == 0) {
continue; }
if (*pcmd_p[axis_num] >= axis->max_pos_limit) {
*pcmd_p[axis_num] = axis->max_pos_limit;
axis->ext_offset_tp.curr_pos = axis->max_pos_limit
- save_pos_cmd[axis_num];
if (axis->ext_offset_tp.pos_cmd > save_offset_cmd[axis_num]) {
axis->ext_offset_tp.pos_cmd = save_offset_cmd[axis_num];
}
axis->ext_offset_tp.curr_vel = 0;
ans++;
continue;
}
if (*pcmd_p[axis_num] <= axis->min_pos_limit) {
*pcmd_p[axis_num] = axis->min_pos_limit;
axis->ext_offset_tp.curr_pos = axis->min_pos_limit
- save_pos_cmd[axis_num];
if (axis->ext_offset_tp.pos_cmd < save_offset_cmd[axis_num]) {
axis->ext_offset_tp.pos_cmd = save_offset_cmd[axis_num];
}
axis->ext_offset_tp.curr_vel = 0;
ans++;
}
}
if (ans > 0) { return 1; }
return 0;
}