#include "rtapi.h"
#include "rtapi_math.h"
#include "motion.h"
#include "hal.h"
#include "mot_priv.h"
#include "homing.h"
#define ABS(x) (((x) < 0) ? -(x) : (x))
#define _(s) (s)
#define HOME_DELAY 0.100
#define MAX_HOME_SEQUENCES EMCMOT_MAX_JOINTS
static home_sequence_state_t sequence_state;
static int home_sequence = -1;
static bool homing_active;
typedef enum {
HOME_IDLE = 0,
HOME_START, HOME_UNLOCK, HOME_UNLOCK_WAIT, HOME_INITIAL_BACKOFF_START, HOME_INITIAL_BACKOFF_WAIT, HOME_INITIAL_SEARCH_START, HOME_INITIAL_SEARCH_WAIT, HOME_SET_COARSE_POSITION, HOME_FINAL_BACKOFF_START, HOME_FINAL_BACKOFF_WAIT, HOME_RISE_SEARCH_START, HOME_RISE_SEARCH_WAIT, HOME_FALL_SEARCH_START, HOME_FALL_SEARCH_WAIT, HOME_SET_SWITCH_POSITION, HOME_INDEX_ONLY_START, HOME_INDEX_SEARCH_START, HOME_INDEX_SEARCH_WAIT, HOME_SET_INDEX_POSITION, HOME_FINAL_MOVE_START, HOME_FINAL_MOVE_WAIT, HOME_LOCK, HOME_LOCK_WAIT, HOME_FINISHED, HOME_ABORT} home_state_t;
static int immediate_state;
typedef struct {
home_state_t home_state; bool homing; bool homed; bool home_sw; bool index_enable; bool at_home;
bool sync_final_move; bool joint_in_sequence;
int pause_timer;
double home_offset; double home; double home_final_vel; double home_search_vel; double home_latch_vel; int home_flags; int home_sequence; bool volatile_home; bool home_is_synchronized;
} home_local_data;
static home_local_data H[EMCMOT_MAX_JOINTS];
typedef struct {
hal_bit_t *home_sw; hal_bit_t *homing; hal_bit_t *homed; hal_bit_t *index_enable; hal_s32_t *home_state; } one_joint_home_data_t;
typedef struct {
one_joint_home_data_t jhd[EMCMOT_MAX_JOINTS];
} all_joints_home_data_t;
static all_joints_home_data_t *joint_home_data = 0;
static void home_start_move(emcmot_joint_t * joint, double vel)
{
double joint_range;
joint_range = joint->max_pos_limit - joint->min_pos_limit;
if (vel > 0.0) {
joint->free_tp.pos_cmd = joint->pos_cmd + 2.0 * joint_range;
} else {
joint->free_tp.pos_cmd = joint->pos_cmd - 2.0 * joint_range;
}
if (fabs(vel) < joint->vel_limit) {
joint->free_tp.max_vel = fabs(vel);
} else {
joint->free_tp.max_vel = joint->vel_limit;
}
joint->free_tp.enable = 1;
}
static void home_do_moving_checks(emcmot_joint_t * joint,int jno)
{
if (joint->on_pos_limit || joint->on_neg_limit) {
if (!(H[jno].home_flags & HOME_IGNORE_LIMITS)) {
reportError(_("hit limit in home state %d"), H[jno].home_state);
H[jno].home_state = HOME_ABORT;
immediate_state = 1;
return;
}
}
if (!joint->free_tp.active) {
joint->free_tp.enable = 0;
reportError(_("end of move in home state %d"), H[jno].home_state);
H[jno].home_state = HOME_ABORT;
immediate_state = 1;
return;
}
}
static void update_home_is_synchronized(void) {
int jno,joint_num;
for (jno = 0; jno < ALL_JOINTS; jno++) {
H[jno].home_is_synchronized = 0;
}
for (jno = 0; jno < ALL_JOINTS; jno++) {
if (H[jno].home_sequence < 0) {
H[jno].home_is_synchronized = 1;
continue;
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
if (joint_num == jno) continue;
if ( ( H[joint_num].home_sequence < 0)
&& (ABS(H[joint_num].home_sequence) == H[jno].home_sequence) ) {
H[jno].home_is_synchronized = 1;
H[joint_num].home_is_synchronized = 1;
}
}
}
}
void homing_init(void)
{
int i;
homing_active = 0;
for (i=0; i < EMCMOT_MAX_JOINTS; i++) {
H[i].home_state = HOME_IDLE;
H[i].home_search_vel = 0;
H[i].home_latch_vel = 0;
H[i].home_final_vel = 0;
H[i].home_offset = 0;
H[i].home = 0;
H[i].home_flags = 0;
H[i].home_sequence = -1;
H[i].volatile_home = 0;
}
}
int export_joint_home_pins(int njoints,int id)
{
int jno,retval;
one_joint_home_data_t *addr;
joint_home_data = hal_malloc(sizeof(all_joints_home_data_t));
if (joint_home_data == 0) {
rtapi_print_msg(RTAPI_MSG_ERR, _("HOMING: all_joints_home_data_t malloc failed\n"));
return -1;
}
retval = 0;
for (jno = 0; jno < njoints; jno++) {
addr = &(joint_home_data->jhd[jno]);
if ((retval = hal_pin_bit_newf(HAL_IN, &(addr->home_sw), id,
"joint.%d.home-sw-in", jno)) != 0) break;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->homing), id,
"joint.%d.homing", jno)) != 0) break;
if ((retval = hal_pin_bit_newf(HAL_OUT, &(addr->homed), id,
"joint.%d.homed", jno)) != 0) break;
if ((retval = hal_pin_s32_newf(HAL_OUT, &(addr->home_state), id,
"joint.%d.home-state", jno)) != 0) break;
if ((retval = hal_pin_bit_newf(HAL_IO, &(addr->index_enable), id,
"joint.%d.index-enable", jno)) != 0) break;
}
return retval;
}
void read_homing_in_pins(int njoints)
{
int jno;
one_joint_home_data_t *addr;
for (jno = 0; jno < njoints; jno++) {
addr = &(joint_home_data->jhd[jno]);
H[jno].home_sw = *(addr->home_sw); H[jno].index_enable = *(addr->index_enable); }
}
void write_homing_out_pins(int njoints)
{
int jno;
one_joint_home_data_t *addr;
for (jno = 0; jno < njoints; jno++) {
addr = &(joint_home_data->jhd[jno]);
*(addr->homing) = H[jno].homing; *(addr->homed) = H[jno].homed; *(addr->home_state) = H[jno].home_state; *(addr->index_enable) = H[jno].index_enable; }
}
void set_home_sequence_state(home_sequence_state_t s_state) {
sequence_state = s_state;
}
void set_home_abort(int jno) {
H[jno].home_state = HOME_ABORT;
}
void set_home_start(int jno) {
H[jno].home_state = HOME_START;
}
void set_home_idle(int jno) {
H[jno].home_state = HOME_IDLE;
}
void set_joint_homing(int jno,bool value) {
H[jno].homing = value;
}
void set_joint_homed(int jno,bool value) {
H[jno].homed = value;
}
void set_joint_at_home(int jno, bool value) {
H[jno].at_home = value;
}
void set_joint_homing_params(int jno,
double offset,
double home,
double home_final_vel,
double home_search_vel,
double home_latch_vel,
int home_flags,
int home_sequence,
bool volatile_home
)
{
H[jno].home_offset = offset;
H[jno].home = home;
H[jno].home_final_vel = home_final_vel;
H[jno].home_search_vel = home_search_vel;
H[jno].home_latch_vel = home_latch_vel;
H[jno].home_flags = home_flags;
H[jno].home_sequence = home_sequence;
H[jno].volatile_home = volatile_home;
update_home_is_synchronized();
}
void update_joint_homing_params (int jno,
double offset,
double home,
int home_sequence
)
{
H[jno].home_offset = offset;
H[jno].home = home;
H[jno].home_sequence = home_sequence;
update_home_is_synchronized();
}
bool get_homing_is_active() {
return homing_active;
}
int get_home_sequence(int jno) {
return H[jno].home_sequence;
}
bool get_homing(int jno) {
return H[jno].homing;
}
bool get_homed(int jno) {
return H[jno].homed;
}
bool get_index_enable(int jno) {
return H[jno].index_enable;
}
bool get_home_is_volatile(int jno) {
return H[jno].volatile_home;
}
bool get_home_needs_unlock_first(int jno) {
return (H[jno].home_flags & HOME_UNLOCK_FIRST) ? 1 : 0;
}
bool get_home_is_idle(int jno) {
return H[jno].home_state == HOME_IDLE ? 1 : 0;
}
bool get_homing_at_index_search_wait(int jno) {
return H[jno].home_state == HOME_INDEX_SEARCH_WAIT ? 1 : 0;
}
home_sequence_state_t get_home_sequence_state(void) {
return sequence_state;
}
void do_homing_sequence(void)
{
int i,ii;
int special_case_sync_all;
int seen = 0;
emcmot_joint_t *joint;
int sequence_is_set = 0;
if(home_sequence == -1) {
sequence_state = HOME_SEQUENCE_IDLE;
home_sequence = 0;
}
switch( sequence_state ) {
case HOME_SEQUENCE_IDLE:
break;
case HOME_SEQUENCE_DO_ONE_JOINT:
for (i=0; i < ALL_JOINTS; i++) {
joint = &joints[i];
if (H[i].home_state == HOME_START) {
H[i].joint_in_sequence = 1;
home_sequence = ABS(H[i].home_sequence);
} else {
if (H[i].joint_in_sequence) {
} else {
H[i].joint_in_sequence = 0;
}
}
}
sequence_is_set = 1;
case HOME_SEQUENCE_DO_ONE_SEQUENCE:
if (!sequence_is_set) {
for (i=0; i < ALL_JOINTS; i++) {
joint = &joints[i];
if (H[i].home_state == HOME_START) {
if ( sequence_is_set
&& (ABS(H[i].home_sequence) != home_sequence)) {
reportError(
"homing.c Unexpected joint=%d jsequence=%d seq=%d\n"
,i,H[i].home_sequence,home_sequence);
}
home_sequence = ABS(H[i].home_sequence);
sequence_is_set = 1;
}
H[i].joint_in_sequence = 1; if ( (H[i].home_state != HOME_START)
|| (home_sequence != ABS(H[i].home_sequence))
) {
H[i].joint_in_sequence = 0;
}
}
}
sequence_state = HOME_SEQUENCE_START;
case HOME_SEQUENCE_START:
if (!sequence_is_set) {
for (i=0; i < EMCMOT_MAX_JOINTS; i++) {
joint = &joints[i];
H[i].joint_in_sequence = 1;
if (H[i].home_sequence >100) {
H[i].joint_in_sequence = 0; }
}
sequence_is_set = 1;
home_sequence = 0;
}
for(i=0; i < MAX_HOME_SEQUENCES; i++) {
H[i].sync_final_move = 0; }
for(i=0; i < ALL_JOINTS; i++) {
if (!H[i].joint_in_sequence) continue;
joint = &joints[i];
if ( (H[i].home_flags & HOME_NO_REHOME)
&& H[i].homed
) {
continue;
} else {
H[i].homed = 0;
}
if (H[i].home_sequence < 0) {
for(ii=0; ii < ALL_JOINTS; ii++) {
if (H[ii].home_sequence == ABS(H[i].home_sequence)) {
H[ii].home_sequence = H[i].home_sequence;
}
}
}
}
special_case_sync_all = 1; for(i=0; i < ALL_JOINTS; i++) {
joint = &joints[i];
if (H[i].home_sequence != -1) {special_case_sync_all = 0;}
}
if (special_case_sync_all) {
home_sequence = 1;
}
for(i=0; i < ALL_JOINTS; i++) {
if (!H[i].joint_in_sequence) continue;
joint = &joints[i];
if ( H[i].home_state != HOME_IDLE && H[i].home_state != HOME_START) {
sequence_state = HOME_SEQUENCE_IDLE;
return;
}
}
homing_active = 1;
case HOME_SEQUENCE_START_JOINTS:
for(i=0; i < ALL_JOINTS; i++) {
joint = &joints[i];
if(ABS(H[i].home_sequence) == home_sequence) {
if (!H[i].joint_in_sequence) continue;
joint->free_tp.enable = 0;
H[i].home_state = HOME_START;
seen++;
}
}
if (seen || home_sequence == 0) {
sequence_state = HOME_SEQUENCE_WAIT_JOINTS;
} else {
sequence_state = HOME_SEQUENCE_IDLE;
homing_active = 0;
}
break;
case HOME_SEQUENCE_WAIT_JOINTS:
for(i=0; i < ALL_JOINTS; i++) {
if (!H[i].joint_in_sequence) continue;
joint = &joints[i];
if(ABS(H[i].home_sequence) != home_sequence) {
continue;
}
if(H[i].home_state != HOME_IDLE) {
seen = 1;
continue;
}
if (!H[i].at_home) {
sequence_state = HOME_SEQUENCE_IDLE;
homing_active = 0;
return;
}
}
if(!seen) {
home_sequence ++;
sequence_state = HOME_SEQUENCE_START_JOINTS;
}
break;
default:
reportError(_("unknown state '%d' during homing sequence"),
sequence_state);
sequence_state = HOME_SEQUENCE_IDLE;
homing_active = 0;
break;
}
}
void do_homing(void)
{
int joint_num;
emcmot_joint_t *joint;
double offset, tmp;
int home_sw_active, homing_flag;
homing_flag = 0;
if (emcmotStatus->motion_state != EMCMOT_MOTION_FREE) {
return;
}
for (joint_num = 0; joint_num < ALL_JOINTS; joint_num++) {
if (!H[joint_num].joint_in_sequence) continue;
joint = &joints[joint_num];
if (!GET_JOINT_ACTIVE_FLAG(joint)) {
continue;
}
home_sw_active = H[joint_num].home_sw;
if (H[joint_num].home_state != HOME_IDLE) {
homing_flag = 1;
}
do {
immediate_state = 0;
switch (H[joint_num].home_state) {
case HOME_IDLE:
break;
case HOME_START:
if (H[joint_num].home_flags & HOME_IS_SHARED && home_sw_active) {
reportError(
_("Cannot home while shared home switch is closed j=%d"),
joint_num);
H[joint_num].home_state = HOME_IDLE;
break;
}
if ( (H[joint_num].home_flags & HOME_NO_REHOME)
&& H[joint_num].homed
) {
H[joint_num].home_state = HOME_IDLE;
break; } else {
H[joint_num].homing = 1;
H[joint_num].homed = 0;
}
H[joint_num].at_home = 0;
joint->free_tp.enable = 0;
H[joint_num].pause_timer = 0;
if (H[joint_num].home_flags & HOME_ABSOLUTE_ENCODER) {
H[joint_num].home_flags &= ~HOME_IS_SHARED; H[joint_num].home_state = HOME_SET_SWITCH_POSITION;
immediate_state = 1;
H[joint_num].homed = 1;
break;
}
if (H[joint_num].home_flags & HOME_UNLOCK_FIRST) {
H[joint_num].home_state = HOME_UNLOCK;
} else {
H[joint_num].home_state = HOME_UNLOCK_WAIT;
immediate_state = 1;
}
break;
case HOME_UNLOCK:
emcmotSetRotaryUnlock(joint_num, 1);
H[joint_num].home_state = HOME_UNLOCK_WAIT;
break;
case HOME_UNLOCK_WAIT:
if ((H[joint_num].home_flags & HOME_UNLOCK_FIRST) &&
!emcmotGetRotaryIsUnlocked(joint_num)) break;
if (H[joint_num].home_search_vel == 0.0) {
if (H[joint_num].home_latch_vel == 0.0) {
H[joint_num].home_state = HOME_SET_SWITCH_POSITION;
immediate_state = 1;
} else if (H[joint_num].home_flags & HOME_USE_INDEX) {
H[joint_num].home_state = HOME_INDEX_ONLY_START;
immediate_state = 1;
} else {
reportError(_("invalid homing config: non-zero LATCH_VEL needs either SEARCH_VEL or USE_INDEX"));
H[joint_num].home_state = HOME_IDLE;
}
} else {
if (H[joint_num].home_latch_vel != 0.0) {
H[joint_num].home_state = HOME_INITIAL_SEARCH_START;
immediate_state = 1;
} else {
reportError(_("invalid homing config: non-zero SEARCH_VEL needs LATCH_VEL"));
H[joint_num].home_state = HOME_IDLE;
}
}
break;
case HOME_INITIAL_BACKOFF_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
home_start_move(joint, - H[joint_num].home_search_vel);
H[joint_num].home_state = HOME_INITIAL_BACKOFF_WAIT;
break;
case HOME_INITIAL_BACKOFF_WAIT:
if (! home_sw_active) {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_INITIAL_SEARCH_START;
immediate_state = 1;
break;
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_INITIAL_SEARCH_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
if (home_sw_active) {
H[joint_num].home_state = HOME_INITIAL_BACKOFF_START;
immediate_state = 1;
break;
}
home_start_move(joint, H[joint_num].home_search_vel);
H[joint_num].home_state = HOME_INITIAL_SEARCH_WAIT;
break;
case HOME_INITIAL_SEARCH_WAIT:
if (home_sw_active) {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_SET_COARSE_POSITION;
immediate_state = 1;
break;
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_SET_COARSE_POSITION:
offset = H[joint_num].home_offset - joint->pos_fb;
joint->pos_cmd += offset;
joint->pos_fb += offset;
joint->free_tp.curr_pos += offset;
joint->motor_offset -= offset;
tmp = H[joint_num].home_search_vel * H[joint_num].home_latch_vel;
if (tmp > 0.0) {
H[joint_num].home_state = HOME_FINAL_BACKOFF_START;
} else {
H[joint_num].home_state = HOME_FALL_SEARCH_START;
}
immediate_state = 1;
break;
case HOME_FINAL_BACKOFF_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
if (! home_sw_active) {
reportError(
_("Home switch inactive before start of backoff move j=%d"),
joint_num);
H[joint_num].home_state = HOME_IDLE;
break;
}
home_start_move(joint, - H[joint_num].home_search_vel);
H[joint_num].home_state = HOME_FINAL_BACKOFF_WAIT;
break;
case HOME_FINAL_BACKOFF_WAIT:
if (! home_sw_active) {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_RISE_SEARCH_START;
immediate_state = 1;
break;
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_RISE_SEARCH_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
if (home_sw_active) {
reportError(
_("Home switch active before start of latch move j=%d"),
joint_num);
H[joint_num].home_state = HOME_IDLE;
break;
}
home_start_move(joint, H[joint_num].home_latch_vel);
H[joint_num].home_state = HOME_RISE_SEARCH_WAIT;
break;
case HOME_RISE_SEARCH_WAIT:
if (home_sw_active) {
if (H[joint_num].home_flags & HOME_USE_INDEX) {
H[joint_num].home_state = HOME_INDEX_SEARCH_START;
immediate_state = 1;
break;
} else {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_SET_SWITCH_POSITION;
immediate_state = 1;
break;
}
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_FALL_SEARCH_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
if (!home_sw_active) {
reportError(
_("Home switch inactive before start of latch move j=%d"),
joint_num);
H[joint_num].home_state = HOME_IDLE;
break;
}
home_start_move(joint, H[joint_num].home_latch_vel);
H[joint_num].home_state = HOME_FALL_SEARCH_WAIT;
break;
case HOME_FALL_SEARCH_WAIT:
if (!home_sw_active) {
if (H[joint_num].home_flags & HOME_USE_INDEX) {
H[joint_num].home_state = HOME_INDEX_SEARCH_START;
immediate_state = 1;
break;
} else {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_SET_SWITCH_POSITION;
immediate_state = 1;
break;
}
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_SET_SWITCH_POSITION:
if (H[joint_num].home_flags & HOME_ABSOLUTE_ENCODER) {
offset = H[joint_num].home_offset;
} else {
offset = H[joint_num].home_offset - joint->pos_fb;
}
joint->pos_cmd += offset;
joint->pos_fb += offset;
joint->free_tp.curr_pos += offset;
joint->motor_offset -= offset;
if (H[joint_num].home_flags & HOME_ABSOLUTE_ENCODER) {
if (H[joint_num].home_flags & HOME_NO_FINAL_MOVE) {
H[joint_num].home_state = HOME_FINISHED;
immediate_state = 1;
H[joint_num].homed = 1;
break;
}
}
H[joint_num].home_state = HOME_FINAL_MOVE_START;
immediate_state = 1;
break;
case HOME_INDEX_ONLY_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
offset = H[joint_num].home_offset - joint->pos_fb;
joint->pos_cmd += offset;
joint->pos_fb += offset;
joint->free_tp.curr_pos += offset;
joint->motor_offset -= offset;
H[joint_num].index_enable = 1;
home_start_move(joint, H[joint_num].home_latch_vel);
H[joint_num].home_state = HOME_INDEX_SEARCH_WAIT;
break;
case HOME_INDEX_SEARCH_START:
H[joint_num].index_enable = 1;
H[joint_num].home_state = HOME_INDEX_SEARCH_WAIT;
immediate_state = 1;
home_do_moving_checks(joint,joint_num);
break;
case HOME_INDEX_SEARCH_WAIT:
if ( H[joint_num].index_enable == 0 ) {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_SET_INDEX_POSITION;
immediate_state = 1;
break;
}
home_do_moving_checks(joint,joint_num);
break;
case HOME_SET_INDEX_POSITION:
joint->motor_offset = - H[joint_num].home_offset;
joint->pos_fb = joint->motor_pos_fb -
(joint->backlash_filt + joint->motor_offset);
joint->pos_cmd = joint->pos_fb;
joint->free_tp.curr_pos = joint->pos_fb;
if (H[joint_num].home_flags & HOME_INDEX_NO_ENCODER_RESET) {
offset = H[joint_num].home_offset - joint->pos_fb;
joint->pos_cmd += offset;
joint->pos_fb += offset;
joint->free_tp.curr_pos += offset;
joint->motor_offset -= offset;
}
H[joint_num].home_state = HOME_FINAL_MOVE_START;
immediate_state = 1;
break;
case HOME_FINAL_MOVE_START:
if (joint->free_tp.active) {
H[joint_num].pause_timer = 0;
break;
}
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
H[joint_num].pause_timer++;
if (H[joint_num].home_sequence < 0) {
if (!H[home_sequence].sync_final_move) break;
} else {
break;
}
}
if ( (H[joint_num].home_sequence < 0)
&& ( ABS(H[joint_num].home_sequence) == home_sequence)
) {
if (!H[home_sequence].sync_final_move) {
int jno;
emcmot_joint_t *jtmp;
H[home_sequence].sync_final_move = 1; for (jno = 0; jno < ALL_JOINTS; jno++) {
jtmp = &joints[jno];
if (!H[jno].joint_in_sequence) continue;
if (ABS(H[jno].home_sequence) != home_sequence) {continue;}
if (H[jno].home_flags & HOME_ABSOLUTE_ENCODER) {continue;}
if ( (H[jno].home_state != HOME_FINAL_MOVE_START)
||
(jtmp->free_tp.active)
) {
H[home_sequence].sync_final_move = 0;
break;
}
}
if (!H[home_sequence].sync_final_move) break;
}
}
H[joint_num].pause_timer = 0;
joint->free_tp.pos_cmd = H[joint_num].home;
if (H[joint_num].home_final_vel > 0) {
joint->free_tp.max_vel = fabs(H[joint_num].home_final_vel);
if (joint->free_tp.max_vel > joint->vel_limit)
joint->free_tp.max_vel = joint->vel_limit;
} else {
joint->free_tp.max_vel = joint->vel_limit;
}
joint->free_tp.enable = 1;
H[joint_num].home_state = HOME_FINAL_MOVE_WAIT;
break;
case HOME_FINAL_MOVE_WAIT:
if (!joint->free_tp.active) {
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_LOCK;
immediate_state = 1;
break;
}
if (joint->on_pos_limit || joint->on_neg_limit) {
if (!(H[joint_num].home_flags & HOME_IGNORE_LIMITS)) {
reportError(_("hit limit in home state j=%d"),joint_num);
H[joint_num].home_state = HOME_ABORT;
immediate_state = 1;
break;
}
}
break;
case HOME_LOCK:
if (H[joint_num].home_flags & HOME_UNLOCK_FIRST) {
emcmotSetRotaryUnlock(joint_num, 0);
} else {
immediate_state = 1;
}
H[joint_num].home_state = HOME_LOCK_WAIT;
break;
case HOME_LOCK_WAIT:
if ((H[joint_num].home_flags & HOME_UNLOCK_FIRST) &&
emcmotGetRotaryIsUnlocked(joint_num)) break;
H[joint_num].home_state = HOME_FINISHED;
immediate_state = 1;
break;
case HOME_FINISHED:
H[joint_num].homing = 0;
H[joint_num].homed = 1;
H[joint_num].at_home = 1;
H[joint_num].home_state = HOME_IDLE;
immediate_state = 1;
H[joint_num].joint_in_sequence = 0;
if (checkAllHomed()) { switch_to_teleop_mode();
homing_flag = 0;
}
break;
case HOME_ABORT:
H[joint_num].homing = 0;
H[joint_num].homed = 0;
H[joint_num].at_home = 0;
H[joint_num].joint_in_sequence = 0;
joint->free_tp.enable = 0;
H[joint_num].home_state = HOME_IDLE;
H[joint_num].index_enable = 0;
immediate_state = 1;
break;
default:
reportError(_("unknown state '%d' during homing j=%d"),
H[joint_num].home_state,joint_num);
H[joint_num].home_state = HOME_ABORT;
immediate_state = 1;
break;
}
} while (immediate_state);
}
if ( homing_flag ) {
homing_active = 1;
} else {
if (sequence_state == HOME_SEQUENCE_IDLE) {
homing_active = 0;
}
}
}
bool get_home_is_synchronized(int jno) {
return H[jno].home_is_synchronized;
}