📄 control.c
字号:
if (*(axis_data->amp_fault)) { SET_JOINT_FAULT_FLAG(joint, 1); } else { SET_JOINT_FAULT_FLAG(joint, 0); } /* read home switch input */ if (*(axis_data->home_sw)) { SET_JOINT_HOME_SWITCH_FLAG(joint, 1); } else { SET_JOINT_HOME_SWITCH_FLAG(joint, 0); } /* read index pulse from HAL */ tmp = *(axis_data->index_pulse); /* detect rising edge of index pulse */ /*! \todo FIXME - should this be done in the homing function? that is the only place it is used... */ if (tmp && !joint->index_pulse) { joint->index_pulse_edge = 1; } else { joint->index_pulse_edge = 0; } joint->index_pulse = tmp; /* end of read and process axis inputs loop */ }}static void do_forward_kins(void){/* there are four possibilities for kinType: IDENTITY: Both forward and inverse kins are available, and they can used without an initial guess, even if one or more joints are not homed. In this case, we apply the forward kins to the joint->pos_fb to produce carte_pos_fb, and if all axes are homed we set carte_pos_fb_ok to 1 to indicate that the feedback data is good. BOTH: Both forward and inverse kins are available, but the forward kins need an initial guess, and/or the kins require all joints to be homed before they work properly. Here we must tread carefully. IF all the joints have been homed, we apply the forward kins to the joint->pos_fb to produce carte_pos_fb, and set carte_pos_fb_ok to indicate that the feedback is good. We use the previous value of carte_pos_fb as the initial guess. If all joints have not been homed, we don't call the kinematics, instead we set carte_pos_fb to the cartesean coordinates of home, as stored in the global worldHome, and we set carte_fb_ok to 0 to indicate that the feedback is invalid.\todo FIXME - maybe setting to home isn't the right thing to do. We need it to be set to home eventually, (right before the first attemt to run the kins), but that doesn't mean we should say we're at home when we're not. INVERSE_ONLY: Only inverse kinematics are available, forward kinematics cannot be used. So we have to fake it, the question is simply "what way of faking it is best". In free mode, or if all axes have not been homed, the feedback position is unknown. If we are in teleop or coord mode, or if we are in free mode and all axes are homed, and haven't been moved since they were homed, then we set carte_pos_fb to carte_pos_cmd, and set carte_pos_fb_ok to 1. If we are in free mode, and any axis is not homed, or any axis has moved since it was homed, we leave cart_pos_fb alone, and set carte_pos_fb_ok to 0. FORWARD_ONLY: Only forward kinematics are available, inverse kins cannot be used. This exists for completeness only, since EMC won't work without inverse kinematics.*//*! \todo FIXME FIXME FIXME - need to put a rate divider in here, run it at the traj rate */ double joint_pos[EMCMOT_MAX_AXIS]; int joint_num, all_homed, all_at_home, result; emcmot_joint_t *joint; all_homed = 1; all_at_home = 1; /* copy joint position feedback to local array */ for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint struct */ joint = &joints[joint_num]; /* copy feedback */ joint_pos[joint_num] = joint->pos_fb; /* check for homed, only if the current joint is active */ if (!GET_JOINT_ACTIVE_FLAG(joint)) { /* if joint is not active, don't even look at its limits */ continue; } if (!GET_JOINT_HOMED_FLAG(joint)) { all_homed = 0; all_at_home = 0; } else if (!GET_JOINT_AT_HOME_FLAG(joint)) { all_at_home = 0; } } switch (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()) { /* is previous value suitable for use as initial guess? */ if (!emcmotStatus->carte_pos_fb_ok) { /* no, use home position as initial guess */ emcmotStatus->carte_pos_fb = emcmotStatus->world_home; } /* calculate Cartesean position feedback from joint pos fb */ result = kinematicsForward(joint_pos, &emcmotStatus->carte_pos_fb, &fflags, &iflags); /* check to make sure kinematics converged */ if (result < 0) { /* error during kinematics calculations */ emcmotStatus->carte_pos_fb_ok = 0; } else { /* it worked! */ 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())) { /* use Cartesean position command as feedback value */ 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 check_soft_limits(void){ int joint_num; emcmot_joint_t *joint; int tmp; /* check for limits on all active axes */ for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; /* clear soft limits */ SET_JOINT_PSL_FLAG(joint, 0); SET_JOINT_NSL_FLAG(joint, 0); /* skip inactive or unhomed axes */ if (GET_JOINT_ACTIVE_FLAG(joint) && GET_JOINT_HOMED_FLAG(joint)) { /* check for soft limits */ if (joint->pos_fb > joint->max_pos_limit) { SET_JOINT_PSL_FLAG(joint, 1); } if (joint->pos_fb < joint->min_pos_limit) { SET_JOINT_NSL_FLAG(joint, 1); } } } /* this part takes action when the limits are hit - it may eventually be moved somewhere else - if not, it can be pulled into the loop above */ /* check flags, see if any joint is in limit */ tmp = 0; for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; if (GET_JOINT_PSL_FLAG(joint) || GET_JOINT_NSL_FLAG(joint)) { /* yes, on limit */ tmp = 1; } } /* check for transitions */ if (tmp) { /* on limit now, were we before? */ if (!emcmotStatus->onSoftLimit) { /* no, update status */ emcmotStatus->onSoftLimit = 1; /* abort everything, regardless of coord or free mode */ tpAbort(&emcmotDebug->queue); for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; /* shut off free mode planner */ joint->free_tp_enable = 0; } } } else { /* off limit now, were we before? */ if (emcmotStatus->onSoftLimit) { /* no, update status */ emcmotStatus->onSoftLimit = 0; } }}static void check_for_faults(void){ int joint_num; emcmot_joint_t *joint; /* check for various global fault conditions */ /* only check enable input if running */ if ( GET_MOTION_ENABLE_FLAG() != 0 ) { if ( *(emcmot_hal_data->enable) == 0 ) { reportError("motion stopped by enable input"); emcmotDebug->enabling = 0; } } /* check for various joint fault conditions */ for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; /* only check active, enabled axes */ if ( GET_JOINT_ACTIVE_FLAG(joint) && GET_JOINT_ENABLE_FLAG(joint) ) { /* check for hard limits */ if (GET_JOINT_PHL_FLAG(joint) || GET_JOINT_NHL_FLAG(joint)) { /* joint is on limit switch, should we trip? */ if (emcmotStatus->overrideLimits || GET_JOINT_HOMING_FLAG(joint)) { /* no, ignore limits */ } else { /* trip on limits */ if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d on limit switch error", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } } /* check for amp fault */ if (GET_JOINT_FAULT_FLAG(joint)) { /* axis is faulted, trip */ if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d amplifier fault", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } /* check for excessive following error */ if (GET_JOINT_FERROR_FLAG(joint)) { if (!GET_JOINT_ERROR_FLAG(joint)) { /* report the error just this once */ reportError("joint %d following error", joint_num); } SET_JOINT_ERROR_FLAG(joint, 1); emcmotDebug->enabling = 0; } /* end of if AXIS_ACTIVE_FLAG(joint) */ } /* end of check for joint faults loop */ }}static void set_operating_mode(void){ int joint_num; emcmot_joint_t *joint; axis_hal_t *axis_data; /* check for disabling */ if (!emcmotDebug->enabling && GET_MOTION_ENABLE_FLAG()) { /* clear out the motion emcmotDebug->queue and interpolators */ tpClear(&emcmotDebug->queue); for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ axis_data = &(emcmot_hal_data->axis[joint_num]); joint = &joints[joint_num]; /* disable free mode planner */ joint->free_tp_enable = 0; /* drain coord mode interpolators */ cubicDrain(&(joint->cubic)); if (GET_JOINT_ACTIVE_FLAG(joint)) { SET_JOINT_ENABLE_FLAG(joint, 0); SET_JOINT_HOMING_FLAG(joint, 0); joint->home_state = HOME_IDLE; } /* don't clear the joint error flag, since that may signify why we just went into disabled state */ } /* reset the trajectory interpolation counter, so that the kinematics functions called during the disabled state run at the nominal trajectory rate rather than the servo rate. It's loaded with emcmotConfig->interpolationRate when it goes to zero. *//*! \todo FIXME - interpolation is still under construction *//*! \todo Another #if 0 */#if 0 interpolationCounter = 0;#endif SET_MOTION_ENABLE_FLAG(0); /* don't clear the motion error flag, since that may signify why we just went into disabled state */ } /* check for emcmotDebug->enabling */ if (emcmotDebug->enabling && !GET_MOTION_ENABLE_FLAG()) { tpSetPos(&emcmotDebug->queue, emcmotStatus->carte_pos_cmd); for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ axis_data = &(emcmot_hal_data->axis[joint_num]); joint = &joints[joint_num]; joint->free_pos_cmd = joint->pos_cmd; if (GET_JOINT_ACTIVE_FLAG(joint)) { SET_JOINT_ENABLE_FLAG(joint, 1); SET_JOINT_HOMING_FLAG(joint, 0); joint->home_state = HOME_IDLE; } /* clear any outstanding axis errors when going into enabled state */ SET_JOINT_ERROR_FLAG(joint, 0); } SET_MOTION_ENABLE_FLAG(1); /* clear any outstanding motion errors when going into enabled state */ SET_MOTION_ERROR_FLAG(0); } /* check for entering teleop mode */ if (emcmotDebug->teleoperating && !GET_MOTION_TELEOP_FLAG()) { if (GET_MOTION_INPOS_FLAG()) { /* update coordinated emcmotDebug->queue position */ tpSetPos(&emcmotDebug->queue, emcmotStatus->carte_pos_cmd); /* drain the cubics so they'll synch up */ for (joint_num = 0; joint_num < EMCMOT_MAX_AXIS; joint_num++) { /* point to joint data */ joint = &joints[joint_num]; cubicDrain(&(joint->cubic)); } /* Initialize things to do when starting teleop mode. */ emcmotDebug->teleop_data.currentVel.tran.x = 0.0; emcmotDebug->teleop_data.currentVel.tran.y = 0.0; emcmotDebug->teleop_data.currentVel.tran.z = 0.0; emcmotDebug->teleop_data.currentVel.a = 0.0; emcmotDebug->teleop_data.currentVel.b = 0.0; emcmotDebug->teleop_data.currentVel.c = 0.0; emcmotDebug->teleop_data.desiredVel.tran.x = 0.0; emcmotDebug->teleop_data.desiredVel.tran.y = 0.0; emcmotDebug->teleop_data.desiredVel.tran.z = 0.0; emcmotDebug->teleop_data.desiredVel.a = 0.0; emcmotDebug->teleop_data.desiredVel.b = 0.0; emcmotDebug->teleop_data.desiredVel.c = 0.0; emcmotDebug->teleop_data.currentAccell.tran.x = 0.0; emcmotDebug->teleop_data.currentAccell.tran.y = 0.0; emcmotDebug->teleop_data.currentAccell.tran.z = 0.0; emcmotDebug->teleop_data.currentAccell.a = 0.0; emcmotDebug->teleop_data.currentAccell.b = 0.0; emcmotDebug->teleop_data.currentAccell.c = 0.0; emcmotDebug->teleop_data.desiredAccell.tran.x = 0.0; emcmotDebug->teleop_data.desiredAccell.tran.y = 0.0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -