⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tp.c

📁 Source code for an Numeric Cmputer
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************* Description: tp.c*   Trajectory planner based on TC elements**   Derived from a work by Fred Proctor & Will Shackleford** Author:* License: GPL Version 2* System: Linux*    * Copyright (c) 2004 All rights reserved.********************************************************************/#ifdef ULAPI#include <stdio.h>#include <stdlib.h>#endif#include "rtapi.h"		/* rtapi_print_msg */#include "posemath.h"#include "tc.h"#include "tp.h"#include "../motion/motion.h"/* how close to accel limit we should go */#define ACCEL_USAGE 0.95extern emcmot_status_t *emcmotStatus;int output_chan = 0;int tpCreate(TP_STRUCT * tp, int _queueSize, TC_STRUCT * tcSpace){    if (0 == tp) {	return -1;    }    if (_queueSize <= 0) {	tp->queueSize = TP_DEFAULT_QUEUE_SIZE;    } else {	tp->queueSize = _queueSize;    }    /* create the queue */    if (-1 == tcqCreate(&tp->queue, tp->queueSize, tcSpace)) {	return -1;    }    /* init the rest of our data */    return tpInit(tp);}/*  tpClear() is a "soft init" in the sense that the TP_STRUCT configuration  parameters (cycleTime, vMax, and aMax) are left alone, but the queue is  cleared, and the flags are set to an empty, ready queue. The currentPos  is left alone, and goalPos is set to this position.  vScale is set to vRestore.  This function is intended to put the motion queue in the state it would  be if all queued motions finished at the current position. */int tpClear(TP_STRUCT * tp){    tcqInit(&tp->queue);    tp->goalPos.tran.x = tp->currentPos.tran.x;    tp->goalPos.tran.y = tp->currentPos.tran.y;    tp->goalPos.tran.z = tp->currentPos.tran.z;    tp->goalPos.a = tp->currentPos.a;    tp->goalPos.b = tp->currentPos.b;    tp->goalPos.c = tp->currentPos.c;    tp->nextId = 0;    tp->execId = 0;    tp->motionType = 0;    tp->termCond = TC_TERM_COND_BLEND;    tp->tolerance = 0.0;    tp->done = 1;    tp->depth = tp->activeDepth = 0;    tp->aborting = 0;    tp->pausing = 0;    tp->vScale = tp->vRestore;    tp->synchronized = 0;    tp->uu_per_rev = 0.0;    emcmotStatus->spindleSync = 0;    return 0;}int tpInit(TP_STRUCT * tp){    tp->cycleTime = 0.0;    tp->vLimit = 0.0;    tp->vScale = tp->vRestore = 1.0;    tp->aMax = 0.0;    tp->vMax = 0.0;    tp->ini_maxvel = 0.0;    tp->wMax = 0.0;    tp->wDotMax = 0.0;    tp->currentPos.tran.x = 0.0;    tp->currentPos.tran.y = 0.0;    tp->currentPos.tran.z = 0.0;    tp->currentPos.a = 0.0;    tp->currentPos.b = 0.0;    tp->currentPos.c = 0.0;        return tpClear(tp);}int tpSetCycleTime(TP_STRUCT * tp, double secs){    if (0 == tp || secs <= 0.0) {	return -1;    }    tp->cycleTime = secs;    return 0;}// This is called before adding lines or circles, specifying// vMax (the velocity requested by the F word) and// ini_maxvel, the max velocity possible before meeting// a machine constraint caused by an AXIS's max velocity.// (the TP is allowed to go up to this high when feed // override >100% is requested)  These settings apply to// subsequent moves until changed.int tpSetVmax(TP_STRUCT * tp, double vMax, double ini_maxvel){    if (0 == tp || vMax <= 0.0 || ini_maxvel <= 0.0) {	return -1;    }    tp->vMax = vMax;    tp->ini_maxvel = ini_maxvel;    return 0;}// I think this is the [TRAJ] max velocity.  This should// be the max velocity of the TOOL TIP, not necessarily// any particular axis.  This applies to subsequent moves// until changed.int tpSetVlimit(TP_STRUCT * tp, double vLimit){    if (0 == tp || vLimit <= 0.0) {	return -1;    }    tp->vLimit = vLimit;    return 0;}// feed override, 1.0 = 100%int tpSetVscale(TP_STRUCT * tp, double scale){    TC_STRUCT *thisTc;    int t;    int depth;    if (0 == tp) {	return -1;    }    if (scale < 0.0) {	/* clamp it */	scale = 0.0;    }    /* record the scale factor */    if (tp->pausing) {	/* if we're pausing, our scale is 0 and needs to stay there so that	   it's applied to any added motions. We'll put the requested scale	   in the restore value so that when we resume the new scale is	   applied. Also, don't send this down to the queued motions--	   they're already paused */	tp->vRestore = scale;    } else {	/* we're not pausing, so it goes right in and is applied to the	   global value for subsequent moves, and also all queued moves */	tp->vScale = scale;	depth = tcqLen(&tp->queue);	for (t = 0; t < depth; t++) {	    thisTc = tcqItem(&tp->queue, t);            thisTc->feed_override = scale;	}    }    return 0;}// Set max accelint tpSetAmax(TP_STRUCT * tp, double aMax){    if (0 == tp || aMax <= 0.0) {	return -1;    }    tp->aMax = aMax;    return 0;}/*  tpSetId() sets the id that will be used for the next appended motions.  nextId is incremented so that the next time a motion is appended its id  will be one more than the previous one, modulo a signed int. If  you want your own ids for each motion, call this before each motion  you append and stick what you want in here.  */int tpSetId(TP_STRUCT * tp, int id){    if (0 == tp) {	return -1;    }    tp->nextId = id;    return 0;}/*  tpGetExecId() returns the id of the last motion that is currently  executing.  */int tpGetExecId(TP_STRUCT * tp){    if (0 == tp) {	return -1;    }    return tp->execId;}/*  tpSetTermCond(tp, cond) sets the termination condition for all subsequent  queued moves. If cond is TC_TERM_STOP, motion comes to a stop before  a subsequent move begins. If cond is TC_TERM_BLEND, the following move  is begun when the current move decelerates.  */int tpSetTermCond(TP_STRUCT * tp, int cond, double tolerance){    if (0 == tp) {	return -1;    }    if (cond != TC_TERM_COND_STOP && cond != TC_TERM_COND_BLEND) {	return -1;    }    tp->termCond = cond;    tp->tolerance = tolerance;    return 0;}// Used to tell the tp the initial position.  It sets// the current position AND the goal position to be the same.  // Used only at TP initialization and when switching modes.int tpSetPos(TP_STRUCT * tp, EmcPose pos){    if (0 == tp) {	return -1;    }    tp->currentPos = pos;    tp->goalPos = pos;    return 0;}// Add a straight line to the tc queue.  This is a coordinated// move in any or all of the six axes.  it goes from the end// of the previous move to the new end specified here at the// currently-active accel and vel settings from the tp struct.int tpAddLine(TP_STRUCT * tp, EmcPose end, int type){    TC_STRUCT tc;    PmLine line_xyz, line_abc;    PmPose start_xyz, end_xyz, start_abc, end_abc;    PmQuaternion identity_quat = { 1.0, 0.0, 0.0, 0.0 };    if (!tp) {        rtapi_print_msg(RTAPI_MSG_ERR, "TP is null\n");        return -1;    }    if (tp->aborting) {        rtapi_print_msg(RTAPI_MSG_ERR, "TP is aborting\n");	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_xyz.rot = identity_quat;    end_xyz.rot = identity_quat;    start_abc.rot = identity_quat;    end_abc.rot = identity_quat;    pmLineInit(&line_xyz, start_xyz, end_xyz);    pmLineInit(&line_abc, start_abc, end_abc);    tc.cycle_time = tp->cycleTime;    tc.target = line_xyz.tmag < 1e-6? line_abc.tmag: line_xyz.tmag;    tc.progress = 0.0;    tc.reqvel = tp->vMax;    tc.maxaccel = tp->aMax * ACCEL_USAGE;    tc.feed_override = tp->vScale;    tc.maxvel = tp->ini_maxvel * ACCEL_USAGE;    tc.id = tp->nextId;    tc.active = 0;    tc.coords.line.xyz = line_xyz;    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.uu_per_rev = tp->uu_per_rev;    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){    TC_STRUCT tc;    PmCircle circle;    PmLine line_abc;    PmPose start_xyz, end_xyz, 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_xyz.rot = identity_quat;    end_xyz.rot = identity_quat;    start_abc.rot = identity_quat;    end_abc.rot = identity_quat;    pmCircleInit(&circle, start_xyz, end_xyz, center, normal, turn);    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 = tp->vMax;    tc.maxaccel = tp->aMax * ACCEL_USAGE;    tc.feed_override = tp->vScale;    tc.maxvel = tp->ini_maxvel * ACCEL_USAGE;    tc.id = tp->nextId;    tc.active = 0;    tc.coords.circle.xyz = circle;    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.uu_per_rev = tp->uu_per_rev;    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;        if(tc->motion_type == TC_CIRCULAR &&

⌨️ 快捷键说明

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