tp.c

来自「CNC 的开放码,EMC2 V2.2.8版」· C语言 代码 · 共 1,046 行 · 第 1/3 页

C
1,046
字号
    end_uvw.tran.x = end.u;    end_uvw.tran.y = end.v;    end_uvw.tran.z = end.w;    start_abc.tran.x = tp->goalPos.a;    start_abc.tran.y = tp->goalPos.b;    start_abc.tran.z = tp->goalPos.c;    end_abc.tran.x = end.a;    end_abc.tran.y = end.b;    end_abc.tran.z = end.c;    start_xyz.rot = identity_quat;    end_xyz.rot = identity_quat;    start_uvw.rot = identity_quat;    end_uvw.rot = identity_quat;    start_abc.rot = identity_quat;    end_abc.rot = identity_quat;    pmLineInit(&line_xyz, start_xyz, end_xyz);    pmLineInit(&line_uvw, start_uvw, end_uvw);    pmLineInit(&line_abc, start_abc, end_abc);    tc.cycle_time = tp->cycleTime;    if (!line_xyz.tmag_zero)         tc.target = line_xyz.tmag;    else if (!line_uvw.tmag_zero)        tc.target = line_uvw.tmag;    else        tc.target = line_abc.tmag;    tc.progress = 0.0;    tc.reqvel = vel;    tc.maxaccel = acc;    tc.feed_override = 0.0;    tc.maxvel = ini_maxvel;    tc.id = tp->nextId;    tc.active = 0;    tc.coords.line.xyz = line_xyz;    tc.coords.line.uvw = line_uvw;    tc.coords.line.abc = line_abc;    tc.motion_type = TC_LINEAR;    tc.canon_motion_type = type;    tc.blend_with_next = tp->termCond == TC_TERM_COND_BLEND;    tc.tolerance = tp->tolerance;    tc.synchronized = tp->synchronized;    tc.velocity_mode = tp->velocity_mode;    tc.uu_per_rev = tp->uu_per_rev;    tc.enables = enables;    if (tcqPut(&tp->queue, tc) == -1) {        rtapi_print_msg(RTAPI_MSG_ERR, "tcqPut failed.\n");	return -1;    }    tp->goalPos = end;      // remember the end of this move, as it's                            // the start of the next one.    tp->done = 0;    tp->depth = tcqLen(&tp->queue);    tp->nextId++;    return 0;}// likewise, this adds a circular (circle, arc, helix) move from// the end of the last move to this new position.  end is the// xyzabc of the destination, center/normal/turn specify the arc// in a way that makes sense to pmCircleInit (we don't care about// the details here.)  Note that degenerate arcs/circles are not// allowed; we are guaranteed to have a move in xyz so target is// always the circle/arc/helical length.int tpAddCircle(TP_STRUCT * tp, EmcPose end,		PmCartesian center, PmCartesian normal, int turn, int type,                double vel, double ini_maxvel, double acc, unsigned char enables){    TC_STRUCT tc;    PmCircle circle;    PmLine line_uvw, line_abc;    PmPose start_xyz, end_xyz;    PmPose start_uvw, end_uvw;    PmPose start_abc, end_abc;    double helix_z_component;   // z of the helix's cylindrical coord system    double helix_length;    PmQuaternion identity_quat = { 1.0, 0.0, 0.0, 0.0 };    if (!tp || tp->aborting) 	return -1;    start_xyz.tran = tp->goalPos.tran;    end_xyz.tran = end.tran;    start_abc.tran.x = tp->goalPos.a;    start_abc.tran.y = tp->goalPos.b;    start_abc.tran.z = tp->goalPos.c;    end_abc.tran.x = end.a;    end_abc.tran.y = end.b;    end_abc.tran.z = end.c;    start_uvw.tran.x = tp->goalPos.u;    start_uvw.tran.y = tp->goalPos.v;    start_uvw.tran.z = tp->goalPos.w;    end_uvw.tran.x = end.u;    end_uvw.tran.y = end.v;    end_uvw.tran.z = end.w;    start_xyz.rot = identity_quat;    end_xyz.rot = identity_quat;    start_uvw.rot = identity_quat;    end_uvw.rot = identity_quat;    start_abc.rot = identity_quat;    end_abc.rot = identity_quat;    pmCircleInit(&circle, start_xyz, end_xyz, center, normal, turn);    pmLineInit(&line_uvw, start_uvw, end_uvw);    pmLineInit(&line_abc, start_abc, end_abc);    // find helix length    pmCartMag(circle.rHelix, &helix_z_component);    helix_length = pmSqrt(pmSq(circle.angle * circle.radius) +                          pmSq(helix_z_component));    tc.cycle_time = tp->cycleTime;    tc.target = helix_length;    tc.progress = 0.0;    tc.reqvel = vel;    tc.maxaccel = acc;    tc.feed_override = 0.0;    tc.maxvel = ini_maxvel;    tc.id = tp->nextId;    tc.active = 0;    tc.coords.circle.xyz = circle;    tc.coords.circle.uvw = line_uvw;    tc.coords.circle.abc = line_abc;    tc.motion_type = TC_CIRCULAR;    tc.canon_motion_type = type;    tc.blend_with_next = tp->termCond == TC_TERM_COND_BLEND;    tc.tolerance = tp->tolerance;    tc.synchronized = tp->synchronized;    tc.velocity_mode = tp->velocity_mode;    tc.uu_per_rev = tp->uu_per_rev;    tc.enables = enables;    if (tcqPut(&tp->queue, tc) == -1) {	return -1;    }    tp->goalPos = end;    tp->done = 0;    tp->depth = tcqLen(&tp->queue);    tp->nextId++;    return 0;}void tcRunCycle(TC_STRUCT *tc, double *v, int *on_final_decel) {    double discr, maxnewvel, newvel, newaccel=0;    if(!tc->blending) tc->vel_at_blend_start = tc->currentvel;    discr = 0.5 * tc->cycle_time * tc->currentvel - (tc->target - tc->progress);    if(discr > 0.0) {        // should never happen: means we've overshot the target        newvel = maxnewvel = 0.0;    } else {        discr = 0.25 * pmSq(tc->cycle_time) - 2.0 / tc->maxaccel * discr;        newvel = maxnewvel = -0.5 * tc->maxaccel * tc->cycle_time +             tc->maxaccel * pmSqrt(discr);    }    if(newvel <= 0.0) {        // also should never happen - if we already finished this tc, it was        // caught above        newvel = newaccel = 0.0;        tc->progress = tc->target;    } else {        // constrain velocity        if(newvel > tc->reqvel * tc->feed_override)             newvel = tc->reqvel * tc->feed_override;        if(newvel > tc->maxvel) newvel = tc->maxvel;        // get resulting acceleration        newaccel = (newvel - tc->currentvel) / tc->cycle_time;                // constrain acceleration and get resulting velocity        if(newaccel > 0.0 && newaccel > tc->maxaccel) {            newaccel = tc->maxaccel;            newvel = tc->currentvel + newaccel * tc->cycle_time;        }        if(newaccel < 0.0 && newaccel < -tc->maxaccel) {            newaccel = -tc->maxaccel;            newvel = tc->currentvel + newaccel * tc->cycle_time;        }        // update position in this tc        tc->progress += (newvel + tc->currentvel) * 0.5 * tc->cycle_time;    }    tc->currentvel = newvel;    if(v) *v = newvel;    if(on_final_decel) *on_final_decel = fabs(maxnewvel - newvel) < 0.001;}// This is the brains of the operation.  It's called every TRAJ period// and is expected to set tp->currentPos to the new machine position.// Lots of other tp fields (depth, done, etc) have to be twiddled to// communicate the status; I think those are spelled out here correctly// and I can't clean it up without breaking the API that the TP presents// to motion.  It's not THAT bad and in the interest of not touching// stuff outside this directory, I'm going to leave it for now.int tpRunCycle(TP_STRUCT * tp, long period){    // vel = (new position - old position) / cycle time    // (two position points required)    //    // acc = (new vel - old vel) / cycle time    // (three position points required)    TC_STRUCT *tc, *nexttc;    double primary_vel;    int on_final_decel;    EmcPose primary_before, primary_after;    EmcPose secondary_before, secondary_after;    EmcPose primary_displacement, secondary_displacement;    static double spindleoffset;    static int waiting = 0;    double save_vel;    emcmotStatus->tcqlen = tcqLen(&tp->queue);    tc = tcqItem(&tp->queue, 0, period);    if(!tc) {        // this means the motion queue is empty.  This can represent        // the end of the program OR QUEUE STARVATION.  In either case,        // I want to stop.  Some may not agree that's what it should do.        tcqInit(&tp->queue);        tp->goalPos = tp->currentPos;        tp->done = 1;        tp->depth = tp->activeDepth = 0;        tp->aborting = 0;        tp->execId = 0;        tp->motionType = 0;        tpResume(tp);	// when not executing a move, use the current enable flags	emcmotStatus->enables_queued = emcmotStatus->enables_new;        return 0;    }    if (tc->target == tc->progress) {        // if we're synced, and this move is ending, save the        // spindle position so the next synced move can be in        // the right place.        if(tc->synchronized)            spindleoffset += tc->target/tc->uu_per_rev;        else            spindleoffset = 0.0;        // done with this move        tcqRemove(&tp->queue, 1);        // so get next move        tc = tcqItem(&tp->queue, 0, period);        if(!tc) return 0;    }    if (tc->motion_type == TC_RIGIDTAP) {        switch (tc->coords.rigidtap.state) {        case TAPPING:            if (tc->progress >= tc->coords.rigidtap.reversal_target) {                // command reversal                emcmotStatus->spindle.speed *= -1;                tc->coords.rigidtap.state = REVERSING;            }            break;        case REVERSING:            if (tc->reqvel == 0.0) {                PmPose start, end;                PmLine *aux = &tc->coords.rigidtap.aux_xyz;                // we've stopped, so set a new target at the original position                tc->coords.rigidtap.spindlerevs_at_reversal = emcmotStatus->spindleRevs;                                pmLinePoint(&tc->coords.rigidtap.xyz, tc->progress, &start);                end = tc->coords.rigidtap.xyz.start;                pmLineInit(aux, start, end);                tc->coords.rigidtap.reversal_target = aux->tmag;                tc->target = aux->tmag + 10. * tc->uu_per_rev;                tc->progress = 0.0;                tc->coords.rigidtap.state = RETRACTION;            }            break;        case RETRACTION:            if (tc->progress >= tc->coords.rigidtap.reversal_target) {                emcmotStatus->spindle.speed *= -1;                tc->coords.rigidtap.state = FINAL_REVERSAL;            }            break;        case FINAL_REVERSAL:            if (tc->reqvel == 0.0) {                PmPose start, end;                PmLine *aux = &tc->coords.rigidtap.aux_xyz;                pmLinePoint(aux, tc->progress, &start);                end = tc->coords.rigidtap.xyz.start;                pmLineInit(aux, start, end);                tc->target = aux->tmag;                tc->progress = 0.0;                tc->synchronized = 0;                tc->reqvel = tc->maxvel;                                tc->coords.rigidtap.state = FINAL_PLACEMENT;            }            break;        case FINAL_PLACEMENT:            // this is a regular move now, it'll stop at target above.            break;        }    }    // this is no longer the segment we were waiting for    if(waiting && waiting != tc->id)         waiting = 0;    if(waiting) {        if(emcmotStatus->spindle_index_enable) {            /* haven't passed index yet */            return 0;        } else {            /* passed index, start the move */            emcmotStatus->spindleSync = 1;            waiting=0;        }    }    if(!tc->synchronized) emcmotStatus->spindleSync = 0;    // now we have the active tc.  get the upcoming one, if there is one.    // it's not an error if there isn't another one - we just don't    // do blending.  This happens in MDI for instance.    if(!emcmotDebug->stepping && tc->blend_with_next)         nexttc = tcqItem(&tp->queue, 1, period);    else        nexttc = NULL;    if(!tc->synchronized && nexttc && nexttc->synchronized && !nexttc->velocity_mode) {        // we'll have to wait for spindle sync; might as well        // stop at the right place (don't blend)        tc->blend_with_next = 0;        nexttc = NULL;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?