Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

emccanon.cc

Go to the documentation of this file.
00001 /*
00002   emccanon.cc
00003 
00004   Canonical definitions for 3-axis NC application
00005 
00006   Modification history:
00007 
00008   23-May-2001  FMP added setting of new EMC_TASK_STAT::programUnits
00009   in USE_LENTH_UNITS, so the GUI can know what units the program uses
00010   13-May-2001 KJO Added return statement in setString() to eliminate 
00011   compiler warning.   
00012   8-Nov-2000 WPS made changes to make this interface compatible
00013    withe the new interpreter.
00014   7-Aug-2000  FMP added hot comments for PROBEOPEN, PROBECLOSE
00015   3-Aug-2000  FMP got rid of CANON_UPDATE_POSITION(), and put its body in
00016   GET_EXTERNAL_POSITION(). Since GET_EXTERNAL_POSITION is called whenever
00017   CANON_UPDATE_POSITION() was called, this has the same effect. The reason
00018   for doing this is to relieve the interpreter of the responsibility of
00019   handling the canonEndPoint variables, which it doesn't care about.
00020   7-Mar-2000  FMP changed ARC_FEED to limit feed rate to axis max
00021   velocities, as was done for STRAIGHT_TRAVERSE below.
00022   3-Mar-2000  FMP changed STRAIGHT_FEED to limit feed rate to axis max
00023   velocities, as was done for STRAIGHT_TRAVERSE below.
00024   23-Feb-2000  FMP changed STRAIGHT_TRAVERSE to use maximal feed rate based
00025   on individual axis max feed rates. Added CANON_UPDATE_POSITION() to handle
00026   updating canonEndPoint when move was aborted.
00027   22-Feb-2000 WPS modified ARC_FEED again. In the previous fix I included
00028   some additional unnecesary  and incorrect conditions for detecting the full
00029   circle that results in too many rotations.
00030   2/7/00 WPS modified ARC_FEED to add an additional rotation when
00031   the starting and ending positions are equal.
00032   2-Jun-1999  FMP added setting of feed rate in INIT_CANON from
00033   TRAJ_DEFAULT_VELOCITY
00034   11-Jan-1999  FMP subtracted tool length offset from Z position in
00035   GET_EXTERNAL_POSITION(), a fix for Jon Elson's email report of this bug:
00036   MDI,G43H<tool with some length>,MANUAL,jog Z,MDI,G1X1F60, and the
00037   Z moves.
00038   23-Dec-1998  FMP put tool length offset and program origin on the
00039   interp list to prevent display of the read-ahead values of these
00040   15-Oct-1998  FMP implemented MESSAGE with queue of EMC_OPERATOR_DISPLAY,
00041   CANON_ERROR with queue of EMC_OPERATOR_ERROR
00042   11-Aug-1998  FMP fixed bug in CANON_PLANE_XZ offset and aligment of
00043   args, thanks to Angelo Brousalis for this one
00044   3-Aug-1998  FMP added GET_TOOL_LENGTH_OFFSET()
00045   12-Jun-1998  FMP added canonMotionMode flag, anticipating mods to
00046   motion controller for stop-at-end flag to inhibit blending
00047   21-May-1998  FMP fixed GET_EXTERNAL_POSITION to return position with
00048   offsets subtracted off-- this fixed the problem where axes that were
00049   not specified in the interpreter moved (now that <interpreter>_synch()
00050   is called in emctask.cc).
00051   15-May-1998  FMP added TRAJ_MAX_VELOCITY global
00052   14-Apr-1998  FMP set default traverse and feed rates to 10 mm/sec
00053   1-Apr-1998  FMP added spindleOn flag for resending CW, CCW if speed change
00054   24-Feb-1998  FMP added TO_EXT_LEN, FROM_PROG_LEN, etc.
00055   20-Feb-1998  FMP added tool length offsets
00056   13-Jan-1998 FMP set rot values in straight feed
00057   2-Dec-1997  FMP changed NML to EMC vocabulary
00058   17-Oct-1997  FMP created
00059 */
00060 
00061 /*
00062 
00063   Notes:
00064 
00065   Units
00066   -----
00067   Values are stored internally as mm and degree units, e.g, program
00068   offsets, end point, tool length offset.  These are "internal
00069   units". "External units" are the units used by the EMC motion planner.
00070   All lengths and units output by the interpreter are converted to
00071   internal units here, using FROM_PROG_LEN,ANG, and then
00072   TO_EXT_LEN(),ANG are called to convert these to external units.
00073 
00074   Tool Length Offsets
00075   -------------------
00076   The interpreter does not subtract off tool length offsets. It calls
00077   USE_TOOL_LENGTH_OFFSETS(length), which we record here and apply to
00078   all subsequent Z values.
00079   */
00080 
00081 
00082 /* ident tag */
00083 #ifndef __GNUC__
00084 #ifndef __attribute__
00085 #define __attribute__(x)
00086 #endif
00087 #endif
00088 
00089 static char __attribute__((unused)) ident[] = "$Id: emccanon.cc,v 1.15 2001/07/14 17:32:54 paul_c Exp $";
00090 
00091 #include <stdio.h>
00092 #include <stdarg.h>
00093 #include <math.h>
00094 #include <string.h>             // strncpy()
00095 #include <ctype.h>              // isspace()
00096 #include "emc.hh"               // EMC NML
00097 #include "canon.hh"             // these decls
00098 #include "interpl.hh"           // interp_list
00099 #include "emcglb.h"             // TRAJ_MAX_VELOCITY
00100 #include "emcpos.h"
00101 
00102 static PM_QUATERNION quat(1, 0, 0, 0);
00103 
00104 /*
00105   Origin offsets, length units, and active plane are all maintained
00106   here in this file. Controller runs in absolute mode, and does not
00107   have plane select concept.
00108 
00109   programOrigin is stored in mm always, and converted when set or read.
00110   When it's applied to positions, convert positions to mm units first
00111   and then add programOrigin.
00112 
00113   Units are then converted from mm to external units, as reported by
00114   the GET_EXTERNAL_LENGTH_UNITS() function.
00115   */
00116 static CANON_POSITION programOrigin(0.0, 0.0, 0.0);
00117 static CANON_UNITS lengthUnits = CANON_UNITS_MM;
00118 static CANON_PLANE activePlane = CANON_PLANE_XY;
00119 
00120 /*
00121   canonEndPoint is the last programmed end point, stored in case it's
00122   needed for subsequent calculations. It's in absolute frame, mm units.
00123   */
00124 static CANON_POSITION canonEndPoint;
00125 static void canonUpdateEndPoint(double x, double y, double z, double a, double b, double c)
00126 {
00127   canonEndPoint.x = x;
00128   canonEndPoint.y = y;
00129   canonEndPoint.z = z;
00130   canonEndPoint.a = a; 
00131   canonEndPoint.b = b; 
00132   canonEndPoint.c = c; 
00133 }
00134 
00135 /* motion control mode is used to signify blended v. stop-at-end moves.
00136    Set to 0 (invalid) at start, so first call will send command out */
00137 static CANON_MOTION_MODE canonMotionMode = 0;
00138 
00139 /* macros for converting internal (mm/deg) units to external units */
00140 #define TO_EXT_LEN(mm) ((mm) * GET_EXTERNAL_LENGTH_UNITS())
00141 #define TO_EXT_ANG(deg) ((deg) * GET_EXTERNAL_ANGLE_UNITS())
00142 
00143 /* macros for converting external units to internal (mm/deg) units */
00144 #define FROM_EXT_LEN(ext) ((ext) / GET_EXTERNAL_LENGTH_UNITS())
00145 #define FROM_EXT_ANG(ext) ((ext) / GET_EXTERNAL_ANGLE_UNITS())
00146 
00147 /* macros for converting internal (mm/deg) units to program units */
00148 #define TO_PROG_LEN(mm) ((mm) / (lengthUnits == CANON_UNITS_INCHES ? 25.4 : lengthUnits == CANON_UNITS_CM ? 10.0 : 1.0))
00149 #define TO_PROG_ANG(deg) (deg)
00150 
00151 /* macros for converting program units to internal (mm/deg) units */
00152 #define FROM_PROG_LEN(prog) ((prog) * (lengthUnits == CANON_UNITS_INCHES ? 25.4 : lengthUnits == CANON_UNITS_CM ? 10.0 : 1.0))
00153 #define FROM_PROG_ANG(prog) (prog)
00154 
00155 /*
00156   Spindle speed is saved here
00157   */
00158 static double spindleSpeed = 0.0;
00159 
00160 /*
00161   Prepped tool is saved here
00162   */
00163 static int preppedTool = 0;
00164 
00165 /*
00166   Feed and traverse rates are saved here; values are in mm/sec. They
00167   will be initially set in INIT_CANON(
00168 ) below.
00169   */
00170 static double currentLinearFeedRate = 1.0;
00171 static double currentLinearTraverseRate = 1.0;
00172 static double currentAngularFeedRate = 1.0;
00173 static double currentAngularTraverseRate = 1.0;
00174 
00175 static int pure_angular_move =0; // Set to 1 if and only if there is no change in x,y,z and atleast one change in a,b or c.
00176  
00177 
00178 /*
00179   Tool length offset is saved here
00180   */
00181 static double currentToolLengthOffset = 0.0;
00182 
00183 /*
00184   EMC traj interface uses one speed. For storing and applying separate
00185   feed and traverse rates, a flag for which was last applied is used.
00186   Requests for motions check this flag and if the improper speed was
00187   last set the proper one is set before the command goes out.
00188   */
00189 
00190 static double lastVelSet = -1;
00191 
00192 // sends a request to set the vel, which is in internal units/sec
00193 static int properVelocity(double vel)
00194 {
00195   EMC_TRAJ_SET_VELOCITY velMsg;
00196 
00197   if (! pure_angular_move) {
00198     velMsg.velocity = TO_EXT_LEN(vel);
00199   }
00200   else {
00201     velMsg.velocity = TO_EXT_ANG(vel);
00202   }      
00203 
00204   if (velMsg.velocity != lastVelSet) {
00205     lastVelSet = velMsg.velocity;
00206     interp_list.append(velMsg);
00207   }
00208 
00209   return 0;
00210 }
00211 
00212 /* Representation */
00213 
00214 void SET_ORIGIN_OFFSETS(double x, double y, double z,
00215                         double a, double b, double c)
00216 {
00217   EMC_TRAJ_SET_ORIGIN set_origin_msg;
00218 
00219   /* convert to mm units */
00220   x = FROM_PROG_LEN(x);
00221   y = FROM_PROG_LEN(y);
00222   z = FROM_PROG_LEN(z);
00223 
00224   programOrigin.x = x;
00225   programOrigin.y = y;
00226   programOrigin.z = z;
00227 
00228   /* append it to interp list so it gets updated at the right time,
00229      not at read-ahead time */
00230   set_origin_msg.origin.tran.x = TO_EXT_LEN(programOrigin.x);
00231   set_origin_msg.origin.tran.y = TO_EXT_LEN(programOrigin.y);
00232   set_origin_msg.origin.tran.z = TO_EXT_LEN(programOrigin.z);
00233   set_origin_msg.origin.a = a;
00234   set_origin_msg.origin.b = b;
00235   set_origin_msg.origin.c = c;
00236 
00237   interp_list.append(set_origin_msg);
00238 }
00239 
00240 void USE_LENGTH_UNITS(CANON_UNITS in_unit)
00241 {
00242   lengthUnits = in_unit;
00243 
00244   emcStatus->task.programUnits = in_unit;
00245 }
00246 
00247 /* Free Space Motion */
00248 
00249 void SET_TRAVERSE_RATE(double rate)
00250 {
00251   double vmax;
00252 
00253 
00254   /* convert from /min to /sec */
00255   rate /= 60.0;
00256 
00257   /* convert to traj units (mm) if needed */
00258   currentLinearTraverseRate = FROM_PROG_LEN(rate);
00259   currentAngularTraverseRate = FROM_PROG_ANG(rate);
00260 
00261 
00262   /* make sure it's less than system max velocity */
00263   vmax  = FROM_EXT_LEN(TRAJ_MAX_VELOCITY);
00264   if (currentLinearTraverseRate > vmax) {
00265     currentLinearTraverseRate = vmax;
00266   }
00267 
00268 }
00269 
00270 void STRAIGHT_TRAVERSE(double x, double y, double z,
00271                        double a, double b, double c)
00272 {
00273   EMC_TRAJ_LINEAR_MOVE linearMoveMsg;
00274   double dx, dy, dz, da, db, dc, dtot;
00275   double tx, ty, tz, ta, tb, tc, tmax;
00276   double vel;
00277 
00278   // convert to mm units
00279   x = FROM_PROG_LEN(x);
00280   y = FROM_PROG_LEN(y);
00281   z = FROM_PROG_LEN(z);
00282   a = FROM_PROG_ANG(a);
00283   b = FROM_PROG_ANG(b);
00284   c = FROM_PROG_ANG(c);
00285 
00286   x += programOrigin.x;
00287   y += programOrigin.y;
00288   z += programOrigin.z;
00289   a += programOrigin.a;
00290   b += programOrigin.b;
00291   c += programOrigin.c;
00292 
00293   z += currentToolLengthOffset;
00294 
00295   // now x, y, z, and b are in absolute mm or degree units
00296 
00297   linearMoveMsg.end.tran.x = TO_EXT_LEN(x);
00298   linearMoveMsg.end.tran.y = TO_EXT_LEN(y);
00299   linearMoveMsg.end.tran.z = TO_EXT_LEN(z);
00300 
00301   // fill in the orientation
00302   linearMoveMsg.end.a = TO_EXT_ANG(a);
00303   linearMoveMsg.end.b = TO_EXT_ANG(b);
00304   linearMoveMsg.end.c = TO_EXT_ANG(c);
00305 
00306   // compute maximal feed rate
00307 
00308   pure_angular_move = 0;
00309 
00310   dx = x - canonEndPoint.x;
00311   dy = y - canonEndPoint.y;
00312   dz = z - canonEndPoint.z;
00313   da = a - canonEndPoint.a;
00314   db = b - canonEndPoint.b;
00315   dc = c - canonEndPoint.c;
00316   dtot = sqrt(dx*dx + dy*dy + dz*dz);
00317   if (dtot <= 0.0) {
00318     dtot = sqrt(da*da + db*db + dc*dc);
00319     if (dtot > 0.0) {
00320       pure_angular_move  =1;
00321     }
00322   }
00323 
00324   if (! pure_angular_move) {
00325     tx = fabs(dx / FROM_EXT_LEN(AXIS_MAX_VELOCITY[0]));
00326     ty = fabs(dy / FROM_EXT_LEN(AXIS_MAX_VELOCITY[1]));
00327     tz = fabs(dz / FROM_EXT_LEN(AXIS_MAX_VELOCITY[2]));
00328     tmax = tx > ty ? tx : ty;
00329     tmax = tz > tmax ? tz : tmax;
00330 
00331     if (tmax <= 0.0) {
00332       vel = currentLinearTraverseRate;
00333     }
00334     else {
00335       vel = dtot/tmax;
00336       if (vel > currentLinearTraverseRate) {
00337         vel = currentLinearTraverseRate;
00338       }
00339     }
00340 
00341   }
00342   else {
00343     ta = fabs(da / FROM_EXT_ANG(AXIS_MAX_VELOCITY[3]));
00344     tb = fabs(db / FROM_EXT_ANG(AXIS_MAX_VELOCITY[4]));
00345     tc = fabs(dc / FROM_EXT_ANG(AXIS_MAX_VELOCITY[5]));
00346     tmax = ta > tb ? ta : tb;
00347     tmax = tc > tmax ? tc : tmax;
00348 
00349     if (tmax <= 0.0) {
00350       vel = currentAngularTraverseRate;
00351     }
00352     else {
00353       vel = dtot/tmax;
00354       if (vel > currentAngularTraverseRate) {
00355         vel = currentAngularTraverseRate;
00356       }
00357     }
00358 
00359   }
00360 
00361   // ensure proper feed rate
00362   properVelocity(vel);
00363 
00364   interp_list.append(linearMoveMsg);
00365 
00366   canonUpdateEndPoint(x, y, z, a, b, c);
00367 }
00368 
00369 /* Machining Attributes */
00370 
00371 void SET_FEED_RATE(double rate)
00372 {
00373   double vmax;
00374 
00375   /* convert from /min to /sec */
00376   rate /= 60.0;
00377 
00378   /* convert to traj units (mm) if needed */
00379   currentLinearFeedRate = FROM_PROG_LEN(rate);
00380   currentAngularFeedRate = FROM_PROG_ANG(rate);
00381 
00382 
00383   /* make sure it's less than system max velocity */
00384   vmax = FROM_EXT_LEN(TRAJ_MAX_VELOCITY);
00385   if (currentLinearFeedRate > vmax) {
00386     currentLinearFeedRate = vmax;
00387   }
00388 }
00389 
00390 void SET_FEED_REFERENCE(CANON_FEED_REFERENCE reference)
00391 {
00392   // nothing need be done here
00393 }
00394 
00395 void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode)
00396 {
00397   EMC_TRAJ_SET_TERM_COND setTermCondMsg;
00398 
00399   if (mode != canonMotionMode)
00400     {
00401       canonMotionMode = mode;
00402 
00403       switch (mode)
00404         {
00405         case CANON_CONTINUOUS:
00406           setTermCondMsg.cond = EMC_TRAJ_TERM_COND_BLEND;
00407           break;
00408 
00409         default:
00410           setTermCondMsg.cond = EMC_TRAJ_TERM_COND_STOP;
00411           break;
00412         }
00413 
00414       interp_list.append(setTermCondMsg);
00415     }
00416 }
00417 
00418 CANON_MOTION_MODE GET_MOTION_CONTROL_MODE()
00419 {
00420   return canonMotionMode;
00421 }
00422 
00423 void SELECT_PLANE(CANON_PLANE in_plane)
00424 {
00425   activePlane = in_plane;
00426 }
00427 
00428 void SET_CUTTER_RADIUS_COMPENSATION(double radius)
00429 {
00430   // nothing need be done here
00431 }
00432 
00433 void START_CUTTER_RADIUS_COMPENSATION(int side)
00434 {
00435   // nothing need be done here
00436 }
00437 
00438 void STOP_CUTTER_RADIUS_COMPENSATION()
00439 {
00440   // nothing need be done here
00441 }
00442 
00443 void START_SPEED_FEED_SYNCH()
00444 {
00445   // FIXME-- unimplemented
00446 }
00447 
00448 void STOP_SPEED_FEED_SYNCH()
00449 {
00450   // FIXME-- unimplemented
00451 }
00452 
00453 void SELECT_MOTION_MODE(CANON_MOTION_MODE mode)
00454 {
00455   // nothing need be done here
00456 }
00457 
00458 /* Machining Functions */
00459 
00460 /* FIXME-- check arc feed against max velocity, using some sort of
00461    suboptimal check, like tangential distance */
00462 void ARC_FEED(double first_end, double second_end,
00463               double first_axis, double second_axis, int rotation,
00464               double axis_end_point,
00465               double a, double b, double c)
00466 {
00467   EmcPose end;
00468   PM_CARTESIAN center, normal;
00469   EMC_TRAJ_CIRCULAR_MOVE circularMoveMsg;
00470   EMC_TRAJ_LINEAR_MOVE linearMoveMsg;
00471   int full_circle_in_active_plane = 0;
00472   double v1, v2, vel;
00473 
00474   // convert to absolute mm units
00475   first_axis = FROM_PROG_LEN(first_axis);
00476   second_axis = FROM_PROG_LEN(second_axis);
00477   first_end = FROM_PROG_LEN(first_end);
00478   second_end = FROM_PROG_LEN(second_end);
00479   axis_end_point = FROM_PROG_LEN(axis_end_point);
00480 
00481   // associate x with x, etc., offset by program origin, and set normals
00482   switch (activePlane) {
00483   case CANON_PLANE_XY:
00484 
00485     // offset and align args properly
00486     end.tran.x = first_end + programOrigin.x;
00487     end.tran.y = second_end + programOrigin.y;
00488     end.tran.z = axis_end_point + programOrigin.z;
00489     end.tran.z += currentToolLengthOffset;
00490     if (canonEndPoint.x == end.tran.x &&
00491         canonEndPoint.y == end.tran.y)
00492       {
00493         full_circle_in_active_plane = 1;
00494       }
00495     center.x = first_axis + programOrigin.x;
00496     center.y = second_axis + programOrigin.y;
00497     center.z = end.tran.z;
00498     normal.x = 0.0;
00499     normal.y = 0.0;
00500     normal.z = 1.0;
00501 
00502     // limit vel to min of X-Y-F
00503     vel = currentLinearFeedRate;
00504     v1 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[0]);
00505     v2 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[1]);
00506     if (vel > v1) {
00507       vel = v1;
00508     }
00509     if (vel > v2) {
00510       vel = v2;
00511     }
00512 
00513     break;
00514 
00515   case CANON_PLANE_YZ:
00516 
00517     // offset and align args properly
00518     end.tran.y = first_end + programOrigin.y;
00519     end.tran.z = second_end + programOrigin.z;
00520     end.tran.x = axis_end_point + programOrigin.x;
00521     end.tran.z += currentToolLengthOffset;
00522     if (canonEndPoint.z == end.tran.z &&
00523         canonEndPoint.y == end.tran.y) {
00524       full_circle_in_active_plane = 1;
00525     }
00526 
00527     center.y = first_axis + programOrigin.y;
00528     center.z = second_axis + programOrigin.z;
00529     center.x = end.tran.x;
00530     normal.y = 0.0;
00531     normal.z = 0.0;
00532     normal.x = 1.0;
00533 
00534     // limit vel to min of Y-Z-F
00535     vel = currentLinearFeedRate;
00536     v1 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[1]);
00537     v2 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[2]);
00538     if (vel > v1) {
00539       vel = v1;
00540     }
00541     if (vel > v2) {
00542       vel = v2;
00543     }
00544 
00545     break;
00546 
00547   case CANON_PLANE_XZ:
00548 
00549     // offset and align args properly
00550     end.tran.z = first_end + programOrigin.z;
00551     end.tran.x = second_end + programOrigin.x;
00552     end.tran.y = axis_end_point + programOrigin.y;
00553     end.tran.z += currentToolLengthOffset;
00554     if (canonEndPoint.x== end.tran.x &&
00555         canonEndPoint.z == end.tran.z)
00556       {
00557         full_circle_in_active_plane = 1;
00558       }
00559 
00560     center.z = first_axis + programOrigin.z;
00561     center.x = second_axis + programOrigin.x;
00562     center.y = end.tran.y;
00563     normal.z = 0.0;
00564     normal.x = 0.0;
00565     normal.y = 1.0;
00566 
00567     // limit vel to min of X-Z-F
00568     vel = currentLinearFeedRate;
00569     v1 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[0]);
00570     v2 = FROM_EXT_LEN(AXIS_MAX_VELOCITY[2]);
00571     if (vel > v1) {
00572       vel = v1;
00573     }
00574     if (vel > v2) {
00575       vel = v2;
00576     }
00577 
00578     break;
00579   }
00580 
00581   // set proper velocity
00582   properVelocity(vel);
00583 
00584   /*
00585     mapping of rotation to turns:
00586 
00587     rotation  turns
00588     --------  -----
00589     0         none (linear move)
00590     1         0
00591     2         1
00592     -1        -1
00593     -2        -2
00594   */
00595 
00596   if (rotation == 0) {
00597     // linear move
00598 
00599     linearMoveMsg.end.tran.x = TO_EXT_LEN(end.tran.x);
00600     linearMoveMsg.end.tran.y = TO_EXT_LEN(end.tran.y);
00601     linearMoveMsg.end.tran.z = TO_EXT_LEN(end.tran.z);
00602 
00603     // fill in the orientation
00604     linearMoveMsg.end.a = a;
00605     linearMoveMsg.end.b = b;
00606     linearMoveMsg.end.c = c;
00607     
00608 
00609     interp_list.append(linearMoveMsg);
00610   }
00611   else if (rotation > 0) {
00612 
00613 #if 0
00614     // This should not be needed anymore with fix in _posemath.c 
00615     // If starting and ending on same point move around the
00616     // circle, don't just stay put.
00617     if (full_circle_in_active_plane) {
00618       rotation++;
00619     }
00620 #endif
00621 
00622     circularMoveMsg.end.tran.x = TO_EXT_LEN(end.tran.x);
00623     circularMoveMsg.end.tran.y = TO_EXT_LEN(end.tran.y);
00624     circularMoveMsg.end.tran.z = TO_EXT_LEN(end.tran.z);
00625 
00626     circularMoveMsg.center.x = TO_EXT_LEN(center.x);
00627     circularMoveMsg.center.y = TO_EXT_LEN(center.y);
00628     circularMoveMsg.center.z = TO_EXT_LEN(center.z);
00629 
00630     circularMoveMsg.normal.x = TO_EXT_LEN(normal.x);
00631     circularMoveMsg.normal.y = TO_EXT_LEN(normal.y);
00632     circularMoveMsg.normal.z = TO_EXT_LEN(normal.z);
00633 
00634     circularMoveMsg.turn = rotation - 1;
00635 
00636     // fill in the orientation
00637     circularMoveMsg.end.a = a;
00638     circularMoveMsg.end.b = b;
00639     circularMoveMsg.end.c = c;
00640 
00641 
00642     interp_list.append(circularMoveMsg);
00643   }
00644   else {
00645     // reverse turn
00646 
00647 #if 0
00648     // This should not be needed anymore with fix in _posemath.c 
00649     // If starting and ending on same point move around the
00650     // circle, don't just stay put.
00651     if (full_circle_in_active_plane) {
00652       rotation--;
00653     }
00654 #endif
00655     circularMoveMsg.end.tran.x = TO_EXT_LEN(end.tran.x);
00656     circularMoveMsg.end.tran.y = TO_EXT_LEN(end.tran.y);
00657     circularMoveMsg.end.tran.z = TO_EXT_LEN(end.tran.z);
00658 
00659     circularMoveMsg.center.x = TO_EXT_LEN(center.x);
00660     circularMoveMsg.center.y = TO_EXT_LEN(center.y);
00661     circularMoveMsg.center.z = TO_EXT_LEN(center.z);
00662 
00663     circularMoveMsg.normal.x = TO_EXT_LEN(normal.x);
00664     circularMoveMsg.normal.y = TO_EXT_LEN(normal.y);
00665     circularMoveMsg.normal.z = TO_EXT_LEN(normal.z);
00666 
00667     circularMoveMsg.turn = rotation;
00668 
00669 
00670     // fill in the orientation
00671     circularMoveMsg.end.a = a;
00672     circularMoveMsg.end.b = b;
00673     circularMoveMsg.end.c = c;
00674 
00675     interp_list.append(circularMoveMsg);
00676   }
00677 
00678 
00679   // update the end point
00680   canonUpdateEndPoint(end.tran.x, end.tran.y, end.tran.z, a, b, c);
00681 }
00682 
00683 void STRAIGHT_FEED(double x, double y, double z, double a, double b, double c)
00684 {
00685   EMC_TRAJ_LINEAR_MOVE linearMoveMsg;
00686   double dx, dy, dz, da, db, dc, dtot;
00687   double tx, ty, tz, ta, tb, tc, tmax;
00688   double vel;
00689 
00690   // convert to mm units
00691   x = FROM_PROG_LEN(x);
00692   y = FROM_PROG_LEN(y);
00693   z = FROM_PROG_LEN(z);  
00694   a = FROM_PROG_ANG(a);
00695   b = FROM_PROG_ANG(b);
00696   c = FROM_PROG_ANG(c);
00697 
00698   x += programOrigin.x;
00699   y += programOrigin.y;
00700   z += programOrigin.z; 
00701   a += programOrigin.a;
00702   b += programOrigin.b;
00703   c += programOrigin.c;
00704 
00705   z += currentToolLengthOffset;
00706 
00707   // now x, y, z, and b are in absolute mm or degree units
00708 
00709   linearMoveMsg.end.tran.x = TO_EXT_LEN(x);
00710   linearMoveMsg.end.tran.y = TO_EXT_LEN(y);
00711   linearMoveMsg.end.tran.z = TO_EXT_LEN(z);
00712 
00713   // fill in the orientation
00714   linearMoveMsg.end.a = TO_EXT_ANG(a);
00715   linearMoveMsg.end.b = TO_EXT_ANG(b);
00716   linearMoveMsg.end.c = TO_EXT_ANG(c);
00717 
00718   // compute maximal feed rate
00719 
00720   pure_angular_move = 0;
00721 
00722   dx = x - canonEndPoint.x;
00723   dy = y - canonEndPoint.y;
00724   dz = z - canonEndPoint.z;
00725   da = a - canonEndPoint.a;
00726   db = b - canonEndPoint.b;
00727   dc = c - canonEndPoint.c;
00728   dtot = sqrt(dx*dx + dy*dy + dz*dz);
00729   if (dtot <= 0.0) {
00730     dtot = sqrt(da*da + db*db + dc*dc);
00731     if (dtot > 0.0) {
00732       pure_angular_move  =1;
00733     }
00734   }
00735 
00736   if (!pure_angular_move) {
00737     tx = fabs(dx / FROM_EXT_LEN(AXIS_MAX_VELOCITY[0]));
00738     ty = fabs(dy / FROM_EXT_LEN(AXIS_MAX_VELOCITY[1]));
00739     tz = fabs(dz / FROM_EXT_LEN(AXIS_MAX_VELOCITY[2]));
00740     tmax = tx > ty ? tx : ty;
00741     tmax = tz > tmax ? tz : tmax;
00742 
00743     if (tmax <= 0.0) {
00744       vel = currentLinearFeedRate;
00745     }
00746     else {
00747       vel = dtot/tmax;
00748       if (vel > currentLinearFeedRate) {
00749         vel = currentLinearFeedRate;
00750       }
00751     }
00752 
00753   }
00754   else {
00755     ta = fabs(da / FROM_EXT_ANG(AXIS_MAX_VELOCITY[3]));
00756     tb = fabs(db / FROM_EXT_ANG(AXIS_MAX_VELOCITY[4]));
00757     tc = fabs(dc / FROM_EXT_ANG(AXIS_MAX_VELOCITY[5]));
00758     tmax = ta > tb ? ta : tb;
00759     tmax = tc > tmax ? tc : tmax;
00760 
00761     if (tmax <= 0.0) {
00762       vel = currentAngularFeedRate;
00763     }
00764     else {
00765       vel = dtot/tmax;
00766       if (vel > currentAngularFeedRate) {
00767         vel = currentAngularFeedRate;
00768       }
00769     }
00770   }
00771 
00772   // ensure proper feed rate
00773   properVelocity(vel);
00774 
00775   interp_list.append(linearMoveMsg);
00776 
00777   canonUpdateEndPoint(x, y, z, a, b, c);
00778 }
00779 
00780 /*
00781   STRAIGHT_PROBE is exactly the same as STRAIGHT_FEED, except that it
00782   uses a probe message instead of a linear move message.
00783 */
00784 void STRAIGHT_PROBE(double x, double y, double z, double a, double b, double c)
00785 {
00786   EMC_TRAJ_PROBE probeMsg;
00787   double dx, dy, dz, dtot;
00788   double tx, ty, tz, tmax;
00789   double vel;
00790 
00791   // convert to mm units
00792   x = FROM_PROG_LEN(x);
00793   y = FROM_PROG_LEN(y);
00794   z = FROM_PROG_LEN(z);
00795 
00796   x += programOrigin.x;
00797   y += programOrigin.y;
00798   z += programOrigin.z;
00799 
00800   z += currentToolLengthOffset;
00801 
00802   // now x, y, z, and b are in absolute mm or degree units
00803 
00804   probeMsg.pos.tran.x = TO_EXT_LEN(x);
00805   probeMsg.pos.tran.y = TO_EXT_LEN(y);
00806   probeMsg.pos.tran.z = TO_EXT_LEN(z);
00807 
00808   // compute maximal feed rate
00809 
00810   dx = x - canonEndPoint.x;
00811   dy = y - canonEndPoint.y;
00812   dz = z - canonEndPoint.z;
00813   dtot = sqrt(dx*dx + dy*dy + dz*dz);
00814 
00815   tx = fabs(dx / FROM_EXT_LEN(AXIS_MAX_VELOCITY[0]));
00816   ty = fabs(dy / FROM_EXT_LEN(AXIS_MAX_VELOCITY[1]));
00817   tz = fabs(dz / FROM_EXT_LEN(AXIS_MAX_VELOCITY[2]));
00818   tmax = tx > ty ? tx : ty;
00819   tmax = tz > tmax ? tz : tmax;
00820 
00821   if (tmax <= 0.0) {
00822     vel = currentLinearFeedRate;
00823   }
00824   else {
00825     vel = dtot/tmax;
00826     if (vel > currentLinearFeedRate) {
00827       vel = currentLinearFeedRate;
00828     }
00829   }
00830 
00831   // ensure proper feed rate
00832   properVelocity(vel);
00833 
00834   // fill in the orientation
00835   probeMsg.pos.a = a;
00836   probeMsg.pos.b = b;
00837   probeMsg.pos.c = c;
00838 
00839   interp_list.append(probeMsg);
00840 
00841   canonUpdateEndPoint(x, y, z, a, b,c);
00842 }
00843 
00844 void DWELL(double seconds)
00845 {
00846   EMC_TRAJ_DELAY delayMsg;
00847 
00848   delayMsg.delay = seconds;
00849 
00850   interp_list.append(delayMsg);
00851 }
00852 
00853 /* Spindle Functions */
00854 void SPINDLE_RETRACT_TRAVERSE()
00855 {
00856   // FIXME-- unimplemented
00857 }
00858 
00859 /* 0 is off, -1 is CCW, 1 is CW; used as flag if settting speed again */
00860 static int spindleOn = 0;
00861 
00862 void START_SPINDLE_CLOCKWISE()
00863 {
00864   EMC_SPINDLE_ON emc_spindle_on_msg;
00865 
00866   emc_spindle_on_msg.speed = spindleSpeed;
00867 
00868   interp_list.append(emc_spindle_on_msg);
00869 
00870   spindleOn = 1;
00871 }
00872 
00873 void START_SPINDLE_COUNTERCLOCKWISE()
00874 {
00875   EMC_SPINDLE_ON emc_spindle_on_msg;
00876 
00877   emc_spindle_on_msg.speed = - spindleSpeed;
00878 
00879   interp_list.append(emc_spindle_on_msg);
00880 
00881   spindleOn = -1;
00882 }
00883 
00884 void SET_SPINDLE_SPEED(double r)
00885 {
00886   // speed is in RPMs everywhere
00887   spindleSpeed = r;
00888 
00889   // check if we need to resend command
00890   if (spindleOn == 1)
00891     {
00892       START_SPINDLE_CLOCKWISE();
00893     }
00894   else if (spindleOn == -1)
00895     {
00896       START_SPINDLE_COUNTERCLOCKWISE();
00897     }
00898 }
00899 
00900 void STOP_SPINDLE_TURNING()
00901 {
00902   EMC_SPINDLE_OFF emc_spindle_off_msg;
00903 
00904   interp_list.append(emc_spindle_off_msg);
00905 
00906   spindleOn = 0;
00907 }
00908 
00909 void SPINDLE_RETRACT()
00910 {
00911   // FIXME-- unimplemented
00912 }
00913 
00914 void ORIENT_SPINDLE(double orientation, CANON_DIRECTION direction)
00915 {
00916   // FIXME-- unimplemented
00917 }
00918 
00919 void USE_NO_SPINDLE_FORCE()
00920 {
00921   // FIXME-- unimplemented
00922 }
00923 
00924 /* Tool Functions */
00925 
00926 /*
00927   EMC has no tool length offset. To implement it, we save it here,
00928   and apply it when necessary
00929   */
00930 void USE_TOOL_LENGTH_OFFSET(double length)
00931 {
00932   EMC_TRAJ_SET_OFFSET set_offset_msg;
00933 
00934   /* convert to mm units for internal canonical use */
00935   currentToolLengthOffset = FROM_PROG_LEN(length);
00936 
00937   /* append it to interp list so it gets updated at the right time,
00938      not at read-ahead time */
00939   set_offset_msg.offset.tran.x = 0.0;
00940   set_offset_msg.offset.tran.y = 0.0;
00941   set_offset_msg.offset.tran.z = TO_EXT_LEN(currentToolLengthOffset);
00942   set_offset_msg.offset.a = 0.0;
00943   set_offset_msg.offset.b = 0.0;
00944   set_offset_msg.offset.c = 0.0;
00945 
00946   interp_list.append(set_offset_msg);
00947 }
00948 
00949 void CHANGE_TOOL(int slot)
00950 {
00951   EMC_TOOL_LOAD load_tool_msg;
00952 
00953   interp_list.append(load_tool_msg);
00954 }
00955 
00956 void SELECT_TOOL(int slot)
00957 {
00958   EMC_TOOL_PREPARE prep_for_tool_msg;
00959 
00960   prep_for_tool_msg.tool = slot;
00961 
00962   interp_list.append(prep_for_tool_msg);
00963 }
00964 
00965 /* Misc Functions */
00966 
00967 void CLAMP_AXIS(CANON_AXIS axis)
00968 {
00969   // FIXME-- unimplemented
00970 }
00971 
00972 /*
00973   setString and addString initializes or adds src to dst, never exceeding
00974   dst's maxlen chars.
00975 */
00976 
00977 static char * setString(char *dst, const char *src, int maxlen)
00978 {
00979   dst[0] = 0;
00980   strncat(dst, src, maxlen - 1);
00981   dst[maxlen - 1] = 0;
00982   return dst;
00983 }
00984 
00985 static char * addString(char *dst, const char *src, int maxlen)
00986 {
00987   int dstlen = strlen(dst);
00988   int srclen = strlen(src);
00989   int actlen;
00990 
00991   if (srclen >= maxlen - dstlen) {
00992     actlen = maxlen - dstlen - 1;
00993     dst[maxlen - 1] = 0;
00994   }
00995   else {
00996     actlen = srclen;
00997   }
00998 
00999   strncat(dst, src, actlen);
01000 
01001   return dst;
01002 }
01003 
01004 /*
01005   The probe file is opened with a hot-comment (PROBEOPEN <filename>),
01006   and the results of each probed point are written to that file.
01007   The file is closed with a (PROBECLOSE) comment.
01008 */
01009 
01010 static FILE *probefile = NULL;
01011 
01012 void COMMENT(char *comment)
01013 {
01014   // nothing need be done here, but you can play tricks with hot comments
01015 
01016 #define MSGLEN 256
01017   char msg[MSGLEN];
01018   char probefilename[MSGLEN];
01019   char *ptr;
01020 
01021   // set RPY orientation for subsequent moves
01022   if (!strncmp(comment, "RPY", strlen("RPY"))) {
01023     PM_RPY rpy;
01024     // it's RPY <R> <P> <Y>
01025     if (3 != sscanf(comment, "%*s %lf %lf %lf", &rpy.r, &rpy.p, &rpy.y)) {
01026       // print current orientation
01027       printf("rpy = %f %f %f, quat = %f %f %f %f\n",
01028              rpy.r, rpy.p, rpy.y,
01029              quat.s, quat.x, quat.y, quat.z);
01030     }
01031     else {
01032       // set and print orientation
01033       quat = rpy;
01034       printf("rpy = %f %f %f, quat = %f %f %f %f\n",
01035              rpy.r, rpy.p, rpy.y,
01036              quat.s, quat.x, quat.y, quat.z);
01037     }
01038     return;
01039   }
01040 
01041   // open probe output file
01042   if (!strncmp(comment, "PROBEOPEN", strlen("PROBEOPEN"))) {
01043     // position ptr to first char after PROBEOPEN
01044     ptr = &comment[strlen("PROBEOPEN")];
01045     // and step over white space to name, or NULL
01046     while (isspace(*ptr)) {
01047       ptr++;
01048     }
01049     setString(probefilename, ptr, MSGLEN);
01050     if (NULL == (probefile = fopen(probefilename, "w"))) {
01051       // pop up a warning message
01052       setString(msg, "can't open probe file ", MSGLEN);
01053       addString(msg, probefilename, MSGLEN);
01054       MESSAGE(msg);
01055       probefile = NULL;
01056     }
01057     return;
01058   }
01059 
01060   // close probe output file
01061   if (!strncmp(comment, "PROBECLOSE", strlen("PROBECLOSE"))) {
01062     if (probefile != NULL) {
01063       fclose(probefile);
01064       probefile = NULL;
01065     }
01066     return;
01067   }
01068 
01069   return;
01070 }
01071 
01072 void DISABLE_FEED_OVERRIDE()
01073 {
01074   // FIXME-- unimplemented
01075 }
01076 
01077 void DISABLE_SPEED_OVERRIDE()
01078 {
01079   // FIXME-- unimplemented
01080 }
01081 
01082 void ENABLE_FEED_OVERRIDE()
01083 {
01084   // FIXME-- unimplemented
01085 }
01086 
01087 void ENABLE_SPEED_OVERRIDE()
01088 {
01089   // FIXME-- unimplemented
01090 }
01091 
01092 void FLOOD_OFF()
01093 {
01094   EMC_COOLANT_FLOOD_OFF flood_off_msg;
01095 
01096   interp_list.append(flood_off_msg);
01097 }
01098 
01099 void FLOOD_ON()
01100 {
01101   EMC_COOLANT_FLOOD_ON flood_on_msg;
01102 
01103   interp_list.append(flood_on_msg);
01104 }
01105 
01106 void MESSAGE(char *s)
01107 {
01108   EMC_OPERATOR_DISPLAY operator_display_msg;
01109 
01110   operator_display_msg.id = 0;
01111   strncpy(operator_display_msg.display, s, EMC_OPERATOR_DISPLAY_LEN);
01112   operator_display_msg.display[EMC_OPERATOR_DISPLAY_LEN - 1] = 0;
01113 
01114   interp_list.append(operator_display_msg);
01115 }
01116 
01117 void MIST_OFF()
01118 {
01119   EMC_COOLANT_MIST_OFF mist_off_msg;
01120 
01121   interp_list.append(mist_off_msg);
01122 }
01123 
01124 void MIST_ON()
01125 {
01126   EMC_COOLANT_MIST_ON mist_on_msg;
01127 
01128   interp_list.append(mist_on_msg);
01129 }
01130 
01131 void PALLET_SHUTTLE()
01132 {
01133   // FIXME-- unimplemented
01134 }
01135 
01136 void TURN_PROBE_OFF()
01137 {
01138   // don't do anything-- this is called when the probing is done
01139 }
01140 
01141 void TURN_PROBE_ON()
01142 {
01143   EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG clearMsg;
01144 
01145   interp_list.append(clearMsg);
01146 }
01147 
01148 void UNCLAMP_AXIS(CANON_AXIS axis)
01149 {
01150   // FIXME-- unimplemented
01151 }
01152 
01153 /* Program Functions */
01154 
01155 void PROGRAM_STOP()
01156 {
01157   /*
01158     implement this as a pause. A resume will cause motion to proceed.
01159    */
01160   EMC_TASK_PLAN_PAUSE pauseMsg;
01161 
01162   interp_list.append(pauseMsg);
01163 }
01164 
01165 void OPTIONAL_PROGRAM_STOP()
01166 {
01167   // FIXME-- implemented as PROGRAM_STOP, that is, no option
01168   PROGRAM_STOP();
01169 }
01170 
01171 void PROGRAM_END()
01172 {
01173   EMC_TASK_PLAN_END endMsg;
01174 
01175   interp_list.append(endMsg);
01176 }
01177 
01178 /* returns the current x, y, z origin offsets */
01179 CANON_VECTOR GET_PROGRAM_ORIGIN()
01180 {
01181   CANON_VECTOR origin;
01182 
01183   /* and convert from mm units to interpreter units */
01184   origin.x = TO_PROG_LEN(programOrigin.x);
01185   origin.y = TO_PROG_LEN(programOrigin.y);
01186   origin.z = TO_PROG_LEN(programOrigin.z);
01187 
01188   return origin;                /* in program units */
01189 }
01190 
01191 /* returns the current active units */
01192 CANON_UNITS GET_LENGTH_UNITS()
01193 {
01194   return lengthUnits;
01195 }
01196 
01197 CANON_PLANE GET_PLANE()
01198 {
01199   return activePlane;
01200 }
01201 
01202 double GET_TOOL_LENGTH_OFFSET()
01203 {
01204   return TO_EXT_LEN(currentToolLengthOffset);
01205 }
01206 
01207 /*
01208   INIT_CANON()
01209 
01210   Initialize canonical local variables to defaults
01211   */
01212 void INIT_CANON()
01213 {
01214   // initialize locals to original values
01215   programOrigin.x = 0.0;
01216   programOrigin.y = 0.0;
01217   programOrigin.z = 0.0;
01218   programOrigin.a = 0.0;
01219   programOrigin.b = 0.0;
01220   programOrigin.c = 0.0;
01221   activePlane = CANON_PLANE_XY;
01222   canonEndPoint.x = 0.0;
01223   canonEndPoint.y = 0.0;
01224   canonEndPoint.z = 0.0;
01225   canonEndPoint.a = 0.0;
01226   canonEndPoint.b = 0.0;
01227   canonEndPoint.c = 0.0;
01228   SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS);
01229   spindleSpeed = 0.0;
01230   preppedTool = 0;
01231   currentLinearFeedRate = FROM_EXT_LEN(TRAJ_DEFAULT_VELOCITY); // from emcglb.h
01232   currentLinearTraverseRate = FROM_EXT_LEN(TRAJ_MAX_VELOCITY); // from emcglb.h
01233   currentAngularFeedRate = 0.0;
01234   currentAngularTraverseRate = 0.0;
01235   currentToolLengthOffset = 0.0;
01236   lengthUnits = CANON_UNITS_MM;
01237 }
01238 
01239 /* Sends error message */
01240 void CANON_ERROR(const char *fmt, ...)
01241 {
01242   va_list ap;
01243   EMC_OPERATOR_ERROR operator_error_msg;
01244 
01245   operator_error_msg.id = 0;
01246   if (fmt != NULL) {
01247     va_start(ap, fmt);
01248     vsprintf(operator_error_msg.error, fmt, ap);
01249     va_end(ap);
01250   }
01251   else {
01252     operator_error_msg.error[0] = 0;
01253   }
01254 
01255   interp_list.append(operator_error_msg);
01256 }
01257 
01258 /*
01259   GET_EXTERNAL_TOOL_TABLE(int pocket)
01260 
01261   Returns the tool table structure associated with pocket. Note that
01262   pocket can run from 0 (by definition, no tool), to pocket CANON_TOOL_MAX - 1.
01263 
01264   The value from emc status is in user units. We need to convert these
01265   to interpreter units, by calling FROM_EXT_LEN() to get them to mm, and
01266   then switching on lengthUnits.
01267   */
01268 CANON_TOOL_TABLE GET_EXTERNAL_TOOL_TABLE(int pocket)
01269 {
01270   CANON_TOOL_TABLE retval;
01271 
01272   if (pocket < 0 || pocket >= CANON_TOOL_MAX) {
01273     retval.id = 0;
01274     retval.length = 0.0;
01275     retval.diameter = 0.0;
01276   }
01277   else {
01278     retval = emcStatus->io.tool.toolTable[pocket];
01279 
01280     // convert from user to program units
01281     retval.length = TO_PROG_LEN(FROM_EXT_LEN(retval.length));
01282     retval.diameter = TO_PROG_LEN(FROM_EXT_LEN(retval.diameter));
01283   }
01284 
01285   return retval;
01286 }
01287 
01288 CANON_POSITION GET_EXTERNAL_POSITION()
01289 {
01290   CANON_POSITION position;
01291   EmcPose pos;
01292 
01293   pos = emcStatus->motion.traj.position;
01294 
01295   // first update internal record of last position
01296   canonEndPoint.x = FROM_EXT_LEN(pos.tran.x) - programOrigin.x;
01297   canonEndPoint.y = FROM_EXT_LEN(pos.tran.y) - programOrigin.y;
01298   canonEndPoint.z = FROM_EXT_LEN(pos.tran.z) - programOrigin.z;
01299   canonEndPoint.z = FROM_EXT_LEN(pos.tran.z) - programOrigin.z;
01300   canonEndPoint.z -= currentToolLengthOffset;
01301 
01302 
01303   canonEndPoint.a = FROM_EXT_ANG(pos.a) - programOrigin.a;
01304   canonEndPoint.b = FROM_EXT_ANG(pos.b) - programOrigin.b;
01305   canonEndPoint.c = FROM_EXT_ANG(pos.c) - programOrigin.c;
01306 
01307   
01308 
01309   // now calculate position in program units, for interpreter
01310   position.x = TO_PROG_LEN(canonEndPoint.x);
01311   position.y = TO_PROG_LEN(canonEndPoint.y);
01312   position.z = TO_PROG_LEN(canonEndPoint.z);
01313   position.z -= TO_PROG_LEN(currentToolLengthOffset);
01314 
01315 
01316   position.a = TO_PROG_ANG(canonEndPoint.a);
01317   position.b = TO_PROG_ANG(canonEndPoint.b);
01318   position.c = TO_PROG_ANG(canonEndPoint.c);
01319 
01320   return position;
01321 }
01322 
01323 CANON_POSITION GET_EXTERNAL_PROBE_POSITION()
01324 {
01325   CANON_POSITION position;
01326   EmcPose pos;
01327   static CANON_POSITION last_probed_position;
01328 
01329   pos = emcStatus->motion.traj.probedPosition;
01330 
01331   // first update internal record of last position
01332   canonEndPoint.x = FROM_EXT_LEN(pos.tran.x) - programOrigin.x;
01333   canonEndPoint.y = FROM_EXT_LEN(pos.tran.y) - programOrigin.y;
01334   canonEndPoint.z = FROM_EXT_LEN(pos.tran.z) - programOrigin.z;
01335   canonEndPoint.z -= currentToolLengthOffset;
01336 
01337   canonEndPoint.a = FROM_EXT_ANG(pos.a) - programOrigin.a;
01338   canonEndPoint.b = FROM_EXT_ANG(pos.b) - programOrigin.b;
01339   canonEndPoint.c = FROM_EXT_ANG(pos.c) - programOrigin.c;  
01340 
01341   // now calculate position in program units, for interpreter
01342   position.x = TO_PROG_LEN(canonEndPoint.x);
01343   position.y = TO_PROG_LEN(canonEndPoint.y);
01344   position.z = TO_PROG_LEN(canonEndPoint.z);
01345   position.z -= TO_PROG_LEN(currentToolLengthOffset);
01346 
01347   position.a = TO_PROG_ANG(canonEndPoint.a);
01348   position.b = TO_PROG_ANG(canonEndPoint.b);
01349   position.c = TO_PROG_ANG(canonEndPoint.c);
01350 
01351   // FIXME-- back end of hot comment
01352   if (probefile != NULL) {
01353       if (last_probed_position.x != position.x ||
01354           last_probed_position.y != position.y ||
01355           last_probed_position.z != position.z) {
01356         fprintf(probefile, "%f %f %f\n", position.x, position.y, position.z);
01357         last_probed_position = position;
01358       }
01359   }
01360   
01361   return position;
01362 }
01363 
01364 double GET_EXTERNAL_PROBE_VALUE()
01365 {
01366   // only for analog non-contact probe, so force a 0
01367   return 0.0;
01368 }
01369 
01370 int IS_EXTERNAL_QUEUE_EMPTY()
01371 {
01372   return emcStatus->motion.traj.queue == 0 ? 1 : 0;
01373 }
01374 
01375 // feed rate wanted is in program units per minute
01376 double GET_EXTERNAL_FEED_RATE()
01377 {
01378   double feed;
01379 
01380   // convert from external to program units
01381   feed = TO_PROG_LEN(FROM_EXT_LEN(emcStatus->motion.traj.velocity));
01382 
01383   // now convert from per-sec to per-minute
01384   feed *= 60.0;
01385 
01386   return feed;
01387 }
01388 
01389 // traverse rate wanted is in program units per minute
01390 double GET_EXTERNAL_TRAVERSE_RATE()
01391 {
01392   double traverse;
01393 
01394   // convert from external to program units
01395   traverse = TO_PROG_LEN(FROM_EXT_LEN(emcStatus->motion.traj.maxVelocity));
01396 
01397   // now convert from per-sec to per-minute
01398   traverse *= 60.0;
01399 
01400   return traverse;
01401 }
01402 
01403 double GET_EXTERNAL_LENGTH_UNITS()
01404 {
01405   double u;
01406 
01407   u = emcStatus->motion.traj.linearUnits;
01408 
01409   if (u == 0) {
01410     CANON_ERROR("external length units are zero");
01411     return 1.0;
01412   }
01413   else {
01414     return u;
01415   }
01416 }
01417 
01418 double GET_EXTERNAL_ANGLE_UNITS()
01419 {
01420   double u;
01421 
01422   u = emcStatus->motion.traj.angularUnits;
01423 
01424   if (u == 0) {
01425     CANON_ERROR("external angle units are zero");
01426     return 1.0;
01427   }
01428   else {
01429     return u;
01430   }
01431 }
01432 
01433 int GET_EXTERNAL_TOOL()
01434 {
01435   return emcStatus->io.tool.toolInSpindle;
01436 }
01437 
01438 int GET_EXTERNAL_MIST()
01439 {
01440   return emcStatus->io.coolant.mist;
01441 }
01442 
01443 int GET_EXTERNAL_FLOOD()
01444 {
01445   return emcStatus->io.coolant.flood;
01446 }
01447 
01448 int GET_EXTERNAL_POCKET()
01449 {
01450   return emcStatus->io.tool.toolPrepped;
01451 }
01452 
01453 double GET_EXTERNAL_SPEED()
01454 {
01455   // speed is in RPMs everywhere
01456   return emcStatus->io.spindle.speed;
01457 }
01458 
01459 CANON_DIRECTION GET_EXTERNAL_SPINDLE()
01460 {
01461   if (emcStatus->io.spindle.speed == 0)
01462     {
01463       return CANON_STOPPED;
01464     }
01465 
01466   if (emcStatus->io.spindle.speed >= 0.0)
01467     {
01468       return CANON_CLOCKWISE;
01469     }
01470 
01471   return CANON_COUNTERCLOCKWISE;
01472 }
01473 
01474 int GET_EXTERNAL_TOOL_MAX()
01475 {
01476   return CANON_TOOL_MAX;
01477 }
01478 
01479 
01480 // Added to support new interpreter
01481 #ifdef NEW_INTERPRETER
01482 
01483 char                     _parameter_file_name[PARAMETER_FILE_NAME_LENGTH];/*Not static.Driver writes*/
01484 
01485 void GET_EXTERNAL_PARAMETER_FILE_NAME(
01486  char * file_name,       /* string: to copy file name into       */
01487  int max_size)           /* maximum number of characters to copy */
01488 {
01489   // Paranoid checks
01490   if( 0 == file_name )
01491     return;
01492 
01493   if(max_size < 0)
01494     return;
01495   
01496   if (strlen(_parameter_file_name) < ((size_t )max_size))
01497     strcpy(file_name, _parameter_file_name);
01498   else
01499     file_name[0] =  0;
01500 }
01501 
01502 /***********************************************************************/
01503 
01504 /* rs274ngc_ini_load()
01505 
01506 Returned Value: RS274NGC_OK, RS274NGC_ERROR
01507 
01508 Side Effects:
01509    An INI file containing values for global variables is used to
01510    update the globals
01511 
01512 Called By:
01513    rs274ngc_init()
01514 
01515 The file looks like this:
01516 
01517 [RS274NGC]
01518 VARIABLE_FILE = rs274ngc.var
01519 
01520 */
01521 
01522 #include "inifile.h"            // INIFILE
01523 
01524 int rs274ngc_ini_load(const char *filename)
01525 {
01526   INIFILE inifile;
01527   const char *inistring;
01528 
01529   // open it
01530   if (-1 == inifile.open(filename))
01531     {
01532       return -1;
01533     }
01534 
01535   if (NULL != (inistring = inifile.find("PARAMETER_FILE", "RS274NGC")))
01536     {
01537       // found it
01538       strncpy(_parameter_file_name, inistring,PARAMETER_FILE_NAME_LENGTH);
01539     }
01540   else
01541     {
01542       // not found, leave RS274NGC_PARAMETER_FILE alone
01543     }
01544 
01545   // close it
01546   inifile.close();
01547 
01548   return 0;
01549 }
01550 
01551 
01552 double GET_EXTERNAL_POSITION_X(void)
01553 {
01554   CANON_POSITION position;
01555   position = GET_EXTERNAL_POSITION();
01556   return position.x;
01557 }
01558 
01559 double GET_EXTERNAL_POSITION_Y(void)
01560 {
01561   CANON_POSITION position;
01562   position = GET_EXTERNAL_POSITION();
01563   return position.y;
01564 }
01565 
01566 double GET_EXTERNAL_POSITION_Z(void)
01567 {
01568   CANON_POSITION position;
01569   position = GET_EXTERNAL_POSITION();
01570   return position.z;
01571 }
01572 
01573 
01574 double GET_EXTERNAL_POSITION_A(void)
01575 {
01576   CANON_POSITION position;
01577   position = GET_EXTERNAL_POSITION();
01578   return position.a;
01579 }
01580 
01581 
01582 double GET_EXTERNAL_POSITION_B(void)
01583 {
01584   CANON_POSITION position;
01585   position = GET_EXTERNAL_POSITION();
01586   return position.b;
01587 }
01588 
01589 
01590 double GET_EXTERNAL_POSITION_C(void)
01591 {
01592   CANON_POSITION position;
01593   position = GET_EXTERNAL_POSITION();
01594   return position.c;
01595 }
01596 
01597 
01598 
01599 double GET_EXTERNAL_PROBE_POSITION_X(void)
01600 {
01601   CANON_POSITION position;
01602   position = GET_EXTERNAL_PROBE_POSITION();
01603   return position.x;
01604 }
01605 
01606 double GET_EXTERNAL_PROBE_POSITION_Y(void)
01607 {
01608   CANON_POSITION position;
01609   position = GET_EXTERNAL_PROBE_POSITION();
01610   return position.y;
01611 }
01612 
01613 double GET_EXTERNAL_PROBE_POSITION_Z(void)
01614 {
01615   CANON_POSITION position;
01616   position = GET_EXTERNAL_PROBE_POSITION();
01617   return position.z;
01618 }
01619 
01620 double GET_EXTERNAL_PROBE_POSITION_A(void)
01621 {
01622   CANON_POSITION position;
01623   position = GET_EXTERNAL_PROBE_POSITION();
01624   return position.a;
01625 }
01626 
01627 double GET_EXTERNAL_PROBE_POSITION_B(void)
01628 {
01629   CANON_POSITION position;
01630   position = GET_EXTERNAL_PROBE_POSITION();
01631   return position.b;
01632 }
01633 
01634 double GET_EXTERNAL_PROBE_POSITION_C(void)
01635 {
01636   CANON_POSITION position;
01637   position = GET_EXTERNAL_PROBE_POSITION();
01638   return position.c;
01639 }
01640 
01641 
01642 CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE()
01643 {
01644   return canonMotionMode;
01645 }
01646 
01647 CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE()
01648 {
01649   return lengthUnits;
01650 }
01651 
01652 int GET_EXTERNAL_QUEUE_EMPTY(void)
01653 {
01654   return emcStatus->motion.traj.queue == 0 ? 1 : 0;
01655 }
01656 
01657 int GET_EXTERNAL_TOOL_SLOT()
01658 {
01659   return emcStatus->io.tool.toolInSpindle;
01660 }
01661 
01662 CANON_PLANE GET_EXTERNAL_PLANE()
01663 {
01664   return activePlane;
01665 }
01666 
01667 
01668 #endif // NEW_INTERPRETER

Generated on Sun Dec 2 15:27:38 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001