📄 emccanon.cc
字号:
/********************************************************************* Description: emccanon.cc* Canonical definitions for 3-axis NC application** Derived from a work by Fred Proctor & Will Shackleford** Author:* License: GPL Version 2* System: Linux* * Copyright (c) 2004 All rights reserved.********************************************************************//* Notes: Units ----- Values are stored internally as mm and degree units, e.g, program offsets, end point, tool length offset. These are "internal units". "External units" are the units used by the EMC motion planner. All lengths and units output by the interpreter are converted to internal units here, using FROM_PROG_LEN,ANG, and then TO_EXT_LEN(),ANG are called to convert these to external units. Tool Length Offsets ------------------- The interpreter does not subtract off tool length offsets. It calls USE_TOOL_LENGTH_OFFSETS(length), which we record here and apply to all appropriate values subsequently. */#include "config.h"#include <stdio.h>#include <stdarg.h>#include <math.h>#include <string.h> // strncpy()#include <ctype.h> // isspace()#include "emc.hh" // EMC NML#include "emc_nml.hh"#include "canon.hh" // these decls#include "interpl.hh" // interp_list#include "emcglb.h" // TRAJ_MAX_VELOCITY#include "emcpos.h"static int debug_velacc = 0;static double css_maximum, css_numerator;static const double tiny = 1e-10;#ifndef MIN#define MIN(a,b) ((a)<(b)?(a):(b))#endif#ifndef MIN3#define MIN3(a,b,c) (MIN(MIN((a),(b)),(c)))#endif#ifndef MAX#define MAX(a,b) ((a)>(b)?(a):(b))#endif#ifndef MAX3#define MAX3(a,b,c) (MAX(MAX((a),(b)),(c)))#endif#ifndef MAX4#define MAX4(a,b,c,d) (MAX(MAX((a),(b)),MAX((c),(d))))#endif#ifndef MAX9#define MAX9(a,b,c,d,e,f,g,h,i) (MAX3((MAX3(a,b,c)),(MAX3(d,e,f)),(MAX3(g,h,i))))#endif/* macros for converting internal (mm/deg) units to external units */#define TO_EXT_LEN(mm) ((mm) * GET_EXTERNAL_LENGTH_UNITS())#define TO_EXT_ANG(deg) ((deg) * GET_EXTERNAL_ANGLE_UNITS())/* macros for converting external units to internal (mm/deg) units */#define FROM_EXT_LEN(ext) ((ext) / GET_EXTERNAL_LENGTH_UNITS())#define FROM_EXT_ANG(ext) ((ext) / GET_EXTERNAL_ANGLE_UNITS())/* macros for converting internal (mm/deg) units to program units */#define TO_PROG_LEN(mm) ((mm) / (lengthUnits == CANON_UNITS_INCHES ? 25.4 : lengthUnits == CANON_UNITS_CM ? 10.0 : 1.0))#define TO_PROG_ANG(deg) (deg)/* macros for converting program units to internal (mm/deg) units */#define FROM_PROG_LEN(prog) ((prog) * (lengthUnits == CANON_UNITS_INCHES ? 25.4 : lengthUnits == CANON_UNITS_CM ? 10.0 : 1.0))#define FROM_PROG_ANG(prog) (prog)static PM_QUATERNION quat(1, 0, 0, 0);static void flush_segments(void);/* These decls were from the old 3-axis canon.hh, and refer functions defined here that are used for convenience but no longer have decls in the 6-axis canon.hh. So, we declare them here now.*/extern void CANON_ERROR(const char *fmt, ...);/* Origin offsets, length units, and active plane are all maintained here in this file. Controller runs in absolute mode, and does not have plane select concept. programOrigin is stored in mm always, and converted when set or read. When it's applied to positions, convert positions to mm units first and then add programOrigin. Units are then converted from mm to external units, as reported by the GET_EXTERNAL_LENGTH_UNITS() function. */static CANON_POSITION programOrigin(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);static CANON_UNITS lengthUnits = CANON_UNITS_MM;static CANON_PLANE activePlane = CANON_PLANE_XY;static int feed_mode = 0;/* canonEndPoint is the last programmed end point, stored in case it's needed for subsequent calculations. It's in absolute frame, mm units. */static CANON_POSITION canonEndPoint;static void canonUpdateEndPoint(double x, double y, double z, double a, double b, double c, double u, double v, double w){ canonEndPoint.x = x; canonEndPoint.y = y; canonEndPoint.z = z; canonEndPoint.a = a; canonEndPoint.b = b; canonEndPoint.c = c; canonEndPoint.u = u; canonEndPoint.v = v; canonEndPoint.w = w;}/* External call to update the canon end point. Called by emctask during skipping of lines (run-from-line) */void CANON_UPDATE_END_POINT(double x, double y, double z, double a, double b, double c, double u, double v, double w){ canonUpdateEndPoint(FROM_PROG_LEN(x),FROM_PROG_LEN(y),FROM_PROG_LEN(z), FROM_PROG_ANG(a),FROM_PROG_ANG(b),FROM_PROG_ANG(c), FROM_PROG_LEN(u),FROM_PROG_LEN(v),FROM_PROG_LEN(w));}/* motion control mode is used to signify blended v. stop-at-end moves. Set to 0 (invalid) at start, so first call will send command out */static CANON_MOTION_MODE canonMotionMode = 0;/* motion path-following tolerance is used to set the max path-following deviation during CANON_CONTINUOUS. If this param is 0, then it will behave as emc always did, allowing almost any deviation trying to keep speed up. */static double canonMotionTolerance = 0.0;/* Spindle speed is saved here */static double spindleSpeed = 0.0;/* Prepped tool is saved here */static int preppedTool = 0;/* optional program stop */static bool optional_program_stop = ON; //set enabled by default (previous EMC behaviour)/* optional block delete */static bool block_delete = ON; //set enabled by default (previous EMC behaviour)/* Tool length offset is saved here */static double currentXToolOffset = 0.0;static double currentZToolOffset = 0.0;/* Feed rate is saved here; values are in mm/sec or deg/sec. It will be initially set in INIT_CANON() below.*/static double currentLinearFeedRate = 0.0;static double currentAngularFeedRate = 0.0;/* Used to indicate whether the current move is linear, angular, or a combination of both. */ //AJ says: linear means axes XYZ move (lines or even circles) // angular means axes ABC movestatic int cartesian_move = 0;static int angular_move = 0;static double toExtVel(double vel) { if (cartesian_move && !angular_move) { return TO_EXT_LEN(vel); } else if (!cartesian_move && angular_move) { return TO_EXT_ANG(vel); } else if (cartesian_move && angular_move) { return TO_EXT_LEN(vel); } else { //seems this case was forgotten, neither linear, neither angular move (we are only sending vel) return TO_EXT_LEN(vel); } }static double toExtAcc(double acc) { return toExtVel(acc); }/* Representation */void SET_ORIGIN_OFFSETS(double x, double y, double z, double a, double b, double c, double u, double v, double w){ EMC_TRAJ_SET_ORIGIN set_origin_msg; flush_segments(); /* convert to mm units */ x = FROM_PROG_LEN(x); y = FROM_PROG_LEN(y); z = FROM_PROG_LEN(z); a = FROM_PROG_ANG(a); b = FROM_PROG_ANG(b); c = FROM_PROG_ANG(c); u = FROM_PROG_LEN(u); v = FROM_PROG_LEN(v); w = FROM_PROG_LEN(w); programOrigin.x = x; programOrigin.y = y; programOrigin.z = z; programOrigin.a = a; programOrigin.b = b; programOrigin.c = c; programOrigin.u = u; programOrigin.v = v; programOrigin.w = w; /* append it to interp list so it gets updated at the right time, not at read-ahead time */ set_origin_msg.origin.tran.x = TO_EXT_LEN(programOrigin.x); set_origin_msg.origin.tran.y = TO_EXT_LEN(programOrigin.y); set_origin_msg.origin.tran.z = TO_EXT_LEN(programOrigin.z); set_origin_msg.origin.a = TO_EXT_ANG(programOrigin.a); set_origin_msg.origin.b = TO_EXT_ANG(programOrigin.b); set_origin_msg.origin.c = TO_EXT_ANG(programOrigin.c); set_origin_msg.origin.u = TO_EXT_LEN(programOrigin.u); set_origin_msg.origin.v = TO_EXT_LEN(programOrigin.v); set_origin_msg.origin.w = TO_EXT_LEN(programOrigin.w); interp_list.append(set_origin_msg);}void USE_LENGTH_UNITS(CANON_UNITS in_unit){ lengthUnits = in_unit; emcStatus->task.programUnits = in_unit;}/* Free Space Motion */void SET_TRAVERSE_RATE(double rate){ // nothing need be done here}void SET_FEED_MODE(int mode) { flush_segments(); feed_mode = mode; if(feed_mode == 0) STOP_SPEED_FEED_SYNCH();}void SET_FEED_RATE(double rate){ if(feed_mode) { START_SPEED_FEED_SYNCH(rate, 1); currentLinearFeedRate = rate; } else { /* convert from /min to /sec */ rate /= 60.0; /* convert to traj units (mm & deg) if needed */ double newLinearFeedRate = FROM_PROG_LEN(rate), newAngularFeedRate = FROM_PROG_ANG(rate); if(newLinearFeedRate != currentLinearFeedRate || newAngularFeedRate != currentAngularFeedRate) flush_segments(); currentLinearFeedRate = newLinearFeedRate; currentAngularFeedRate = newAngularFeedRate; }}void SET_FEED_REFERENCE(CANON_FEED_REFERENCE reference){ // nothing need be done here}double getStraightAcceleration(double x, double y, double z, double a, double b, double c, double u, double v, double w){ double dx, dy, dz, du, dv, dw, da, db, dc; double tx, ty, tz, tu, tv, tw, ta, tb, tc, tmax; double acc, dtot; acc = 0.0; // if a move to nowhere // Compute absolute travel distance for each axis: dx = fabs(x - canonEndPoint.x); dy = fabs(y - canonEndPoint.y); dz = fabs(z - canonEndPoint.z); da = fabs(a - canonEndPoint.a); db = fabs(b - canonEndPoint.b); dc = fabs(c - canonEndPoint.c); du = fabs(u - canonEndPoint.u); dv = fabs(v - canonEndPoint.v); dw = fabs(w - canonEndPoint.w); if(dx < tiny) dx = 0.0; if(dy < tiny) dy = 0.0; if(dz < tiny) dz = 0.0; if(da < tiny) da = 0.0; if(db < tiny) db = 0.0; if(dc < tiny) dc = 0.0; if(du < tiny) du = 0.0; if(dv < tiny) dv = 0.0; if(dw < tiny) dw = 0.0; if(debug_velacc) printf("getStraightAcceleration dx %g dy %g dz %g da %g db %g dc %g du %g dv %g dw %g ", dx, dy, dz, da, db, dc, du, dv, dw); // Figure out what kind of move we're making. This is used to determine // the units of vel/acc. if (dx <= 0.0 && dy <= 0.0 && dz <= 0.0 && du <= 0.0 && dv <= 0.0 && dw <= 0.0) { cartesian_move = 0; } else { cartesian_move = 1; } if (da <= 0.0 && db <= 0.0 && dc <= 0.0) { angular_move = 0; } else { angular_move = 1; } // Pure linear move: if (cartesian_move && !angular_move) { tx = dx? (dx / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[0])): 0.0; ty = dy? (dy / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[1])): 0.0; tz = dz? (dz / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[2])): 0.0; tu = du? (du / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[6])): 0.0; tv = dv? (dv / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[7])): 0.0; tw = dw? (dw / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[8])): 0.0; tmax = MAX3(tx, ty ,tz); tmax = MAX4(tu, tv, tw, tmax); if(dx || dy || dz) dtot = sqrt(dx * dx + dy * dy + dz * dz); else dtot = sqrt(du * du + dv * dv + dw * dw); if (tmax > 0.0) { acc = dtot / tmax; } } // Pure angular move: else if (!cartesian_move && angular_move) { ta = da? (da / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[3])): 0.0; tb = db? (db / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[4])): 0.0; tc = dc? (dc / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[5])): 0.0; tmax = MAX3(ta, tb, tc); dtot = sqrt(da * da + db * db + dc * dc); if (tmax > 0.0) { acc = dtot / tmax; } } // Combination angular and linear move: else if (cartesian_move && angular_move) { tx = dx? (dx / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[0])): 0.0; ty = dy? (dy / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[1])): 0.0; tz = dz? (dz / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[2])): 0.0; ta = da? (da / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[3])): 0.0; tb = db? (db / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[4])): 0.0; tc = dc? (dc / FROM_EXT_ANG(AXIS_MAX_ACCELERATION[5])): 0.0; tu = du? (du / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[6])): 0.0; tv = dv? (dv / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[7])): 0.0; tw = dw? (dw / FROM_EXT_LEN(AXIS_MAX_ACCELERATION[8])): 0.0; tmax = MAX9(tx, ty, tz, ta, tb, tc, tu, tv, tw);/* According to NIST IR6556 Section 2.1.2.5 Paragraph A a combnation move is handled like a linear move, except that the angular axes are allowed sufficient time to complete their motion coordinated with the motion of the linear axes.*/ if(dx || dy || dz) dtot = sqrt(dx * dx + dy * dy + dz * dz); else dtot = sqrt(du * du + dv * dv + dw * dw); if (tmax > 0.0) { acc = dtot / tmax; } } if(debug_velacc) printf("cartesian %d ang %d acc %g\n", cartesian_move, angular_move, acc); return acc;}double getStraightVelocity(double x, double y, double z, double a, double b, double c, double u, double v, double w){ double dx, dy, dz, da, db, dc, du, dv, dw; double tx, ty, tz, ta, tb, tc, tu, tv, tw, tmax; double vel, dtot;/* If we get a move to nowhere (!cartesian_move && !angular_move) we might as well go there at the currentLinearFeedRate...*/ vel = currentLinearFeedRate; // Compute absolute travel distance for each axis: dx = fabs(x - canonEndPoint.x); dy = fabs(y - canonEndPoint.y); dz = fabs(z - canonEndPoint.z); da = fabs(a - canonEndPoint.a); db = fabs(b - canonEndPoint.b); dc = fabs(c - canonEndPoint.c); du = fabs(u - canonEndPoint.u); dv = fabs(v - canonEndPoint.v); dw = fabs(w - canonEndPoint.w); if(dx < tiny) dx = 0.0; if(dy < tiny) dy = 0.0; if(dz < tiny) dz = 0.0; if(da < tiny) da = 0.0; if(db < tiny) db = 0.0; if(dc < tiny) dc = 0.0; if(du < tiny) du = 0.0; if(dv < tiny) dv = 0.0; if(dw < tiny) dw = 0.0; if(debug_velacc) printf("getStraightVelocity dx %g dy %g dz %g da %g db %g dc %g du %g dv %g dw %g ", dx, dy, dz, da, db, dc, du, dv, dw); // Figure out what kind of move we're making: if (dx <= 0.0 && dy <= 0.0 && dz <= 0.0 && du <= 0.0 && dv <= 0.0 && dw <= 0.0) { cartesian_move = 0; } else { cartesian_move = 1; } if (da <= 0.0 && db <= 0.0 && dc <= 0.0) { angular_move = 0; } else { angular_move = 1; } // Pure linear move: if (cartesian_move && !angular_move) { tx = dx? fabs(dx / FROM_EXT_LEN(AXIS_MAX_VELOCITY[0])): 0.0; ty = dy? fabs(dy / FROM_EXT_LEN(AXIS_MAX_VELOCITY[1])): 0.0; tz = dz? fabs(dz / FROM_EXT_LEN(AXIS_MAX_VELOCITY[2])): 0.0; tu = du? fabs(du / FROM_EXT_LEN(AXIS_MAX_VELOCITY[6])): 0.0; tv = dv? fabs(dv / FROM_EXT_LEN(AXIS_MAX_VELOCITY[7])): 0.0; tw = dw? fabs(dw / FROM_EXT_LEN(AXIS_MAX_VELOCITY[8])): 0.0; tmax = MAX3(tx, ty ,tz);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -