shcom.cc
来自「CNC 的开放码,EMC2 V2.2.8版」· CC 代码 · 共 1,402 行 · 第 1/3 页
CC
1,402 行
/********************************************************************* Description: shcom.cc* Common functions for NML calls** Derived from a work by Fred Proctor & Will Shackleford* Further derived from work by jmkasunich, Alex Joni** Author: Eric H. Johnson* License: GPL Version 2* System: Linux** Copyright (c) 2006 All rights reserved.** Last change:* $Revision: 1.5 $* $Author: alex_joni $* $Date: 2007/08/05 23:27:44 $********************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <signal.h>#include <unistd.h>#include <ctype.h>#include <math.h>#include <sys/types.h>#include "rcs.hh"#include "posemath.h" // PM_POSE, TO_RAD#include "emc.hh" // EMC NML#include "emc_nml.hh"#include "canon.hh" // CANON_UNITS, CANON_UNITS_INCHES,MM,CM#include "emcglb.h" // EMC_NMLFILE, TRAJ_MAX_VELOCITY, etc.#include "emccfg.h" // DEFAULT_TRAJ_MAX_VELOCITY#include "inifile.hh" // INIFILE#include "nml_oi.hh" // nmlErrorFormat, NML_ERROR, etc#include "rcs_print.hh"#include "timer.hh" // esleep#include "shcom.hh" // Common NML communications functionsLINEAR_UNIT_CONVERSION linearUnitConversion;ANGULAR_UNIT_CONVERSION angularUnitConversion;int emcCommandSerialNumber;int saveEmcCommandSerialNumber;// the NML channels to the EMC taskRCS_CMD_CHANNEL *emcCommandBuffer;RCS_STAT_CHANNEL *emcStatusBuffer;EMC_STAT *emcStatus;// the NML channel for errorsNML *emcErrorBuffer;char error_string[LINELEN];char operator_text_string[LINELEN];char operator_display_string[LINELEN];// default value for timeout, 0 means wait foreverdouble emcTimeout;int programStartLine;EMC_UPDATE_TYPE emcUpdateType;EMC_WAIT_TYPE emcWaitType;void strupr(char *s){ int i; for (i = 0; i < (int)strlen(s); i++) if (s[i] > 96 && s[i] <= 'z') s[i] -= 32;}int emcTaskNmlGet(){ int retval = 0; // try to connect to EMC cmd if (emcCommandBuffer == 0) { emcCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "emcCommand", "xemc", EMC_NMLFILE); if (!emcCommandBuffer->valid()) { delete emcCommandBuffer; emcCommandBuffer = 0; retval = -1; } } // try to connect to EMC status if (emcStatusBuffer == 0) { emcStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "emcStatus", "xemc", EMC_NMLFILE); if (!emcStatusBuffer->valid() || EMC_STAT_TYPE != emcStatusBuffer->peek()) { delete emcStatusBuffer; emcStatusBuffer = 0; emcStatus = 0; retval = -1; } else { emcStatus = (EMC_STAT *) emcStatusBuffer->get_address(); } } return retval;}int emcErrorNmlGet(){ int retval = 0; if (emcErrorBuffer == 0) { emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "xemc", EMC_NMLFILE); if (!emcErrorBuffer->valid()) { delete emcErrorBuffer; emcErrorBuffer = 0; retval = -1; } } return retval;}int tryNml(){ double end; int good;#define RETRY_TIME 10.0 // seconds to wait for subsystems to come up#define RETRY_INTERVAL 1.0 // seconds between wait tries for a subsystem if (EMC_DEBUG & EMC_DEBUG_NML == 0) { set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag // messages } end = RETRY_TIME; good = 0; do { if (0 == emcTaskNmlGet()) { good = 1; break; } esleep(RETRY_INTERVAL); end -= RETRY_INTERVAL; } while (end > 0.0); if (EMC_DEBUG & EMC_DEBUG_NML == 0) { set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // inhibit diag // messages } if (!good) { return -1; } if (EMC_DEBUG & EMC_DEBUG_NML == 0) { set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag // messages } end = RETRY_TIME; good = 0; do { if (0 == emcErrorNmlGet()) { good = 1; break; } esleep(RETRY_INTERVAL); end -= RETRY_INTERVAL; } while (end > 0.0); if (EMC_DEBUG & EMC_DEBUG_NML == 0) { set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // inhibit diag // messages } if (!good) { return -1; } return 0;#undef RETRY_TIME#undef RETRY_INTERVAL}int updateStatus(){ NMLTYPE type; if (0 == emcStatus || 0 == emcStatusBuffer || !emcStatusBuffer->valid()) { return -1; } switch (type = emcStatusBuffer->peek()) { case -1: // error on CMS channel return -1; break; case 0: // no new data case EMC_STAT_TYPE: // new data // new data break; default: return -1; break; } return 0;}/* updateError() updates "errors," which are true errors and also operator display and text messages.*/int updateError(){ NMLTYPE type; if (0 == emcErrorBuffer || !emcErrorBuffer->valid()) { return -1; } switch (type = emcErrorBuffer->read()) { case -1: // error reading channel return -1; break; case 0: // nothing new break; case EMC_OPERATOR_ERROR_TYPE: strncpy(error_string, ((EMC_OPERATOR_ERROR *) (emcErrorBuffer->get_address()))-> error, LINELEN - 1); error_string[LINELEN - 1] = 0; break; case EMC_OPERATOR_TEXT_TYPE: strncpy(operator_text_string, ((EMC_OPERATOR_TEXT *) (emcErrorBuffer->get_address()))-> text, LINELEN - 1); operator_text_string[LINELEN - 1] = 0; break; case EMC_OPERATOR_DISPLAY_TYPE: strncpy(operator_display_string, ((EMC_OPERATOR_DISPLAY *) (emcErrorBuffer-> get_address()))->display, LINELEN - 1); operator_display_string[LINELEN - 1] = 0; break; case NML_ERROR_TYPE: strncpy(error_string, ((NML_ERROR *) (emcErrorBuffer->get_address()))->error, NML_ERROR_LEN - 1); error_string[NML_ERROR_LEN - 1] = 0; break; case NML_TEXT_TYPE: strncpy(operator_text_string, ((NML_TEXT *) (emcErrorBuffer->get_address()))->text, NML_TEXT_LEN - 1); operator_text_string[NML_TEXT_LEN - 1] = 0; break; case NML_DISPLAY_TYPE: strncpy(operator_display_string, ((NML_DISPLAY *) (emcErrorBuffer->get_address()))->display, NML_DISPLAY_LEN - 1); operator_display_string[NML_DISPLAY_LEN - 1] = 0; break; default: // if not recognized, set the error string sprintf(error_string, "unrecognized error %ld", type); return -1; break; } return 0;}#define EMC_COMMAND_DELAY 0.1 // how long to sleep between checks/* emcCommandWaitReceived() waits until the EMC reports that it got the command with the indicated serial_number. emcCommandWaitDone() waits until the EMC reports that it got the command with the indicated serial_number, and it's done, or error.*/int emcCommandWaitReceived(int serial_number){ double end = 0.0; while (emcTimeout <= 0.0 || end < emcTimeout) { updateStatus(); if (emcStatus->echo_serial_number == serial_number) { return 0; } esleep(EMC_COMMAND_DELAY); end += EMC_COMMAND_DELAY; } return -1;}int emcCommandWaitDone(int serial_number){ double end = 0.0; // first get it there if (0 != emcCommandWaitReceived(serial_number)) { return -1; } // now wait until it, or subsequent command (e.g., abort) is done while (emcTimeout <= 0.0 || end < emcTimeout) { updateStatus(); if (emcStatus->status == RCS_DONE) { return 0; } if (emcStatus->status == RCS_ERROR) { return -1; } esleep(EMC_COMMAND_DELAY); end += EMC_COMMAND_DELAY; } return -1;}/* Unit conversion Length and angle units in the EMC status buffer are in user units, as defined in the INI file in [TRAJ] LINEAR,ANGULAR_UNITS. These may differ from the program units, and when they are the display is confusing. It may be desirable to synchronize the display units with the program units automatically, and also to break this sync and allow independent display of position values. The global variable "linearUnitConversion" is set by the Tcl commands emc_linear_unit_conversion to correspond to either "inch", "mm", "cm", "auto", or "custom". This forces numbers to be returned in the units specified, in program units when "auto" is set, or not converted at all if "custom" is specified. Ditto for "angularUnitConversion", set by emc_angular_unit_conversion to "deg", "rad", "grad", "auto", or "custom". With no args, emc_linear/angular_unit_conversion return the setting. The functions convertLinearUnits and convertAngularUnits take a length or angle value, typically from the emcStatus structure, and convert it as indicated by linearUnitConversion and angularUnitConversion, resp.*//* to convert linear units, values are converted to mm, then to desired units*/double convertLinearUnits(double u){ double in_mm; /* convert u to mm */ in_mm = u / emcStatus->motion.traj.linearUnits; /* convert u to display units */ switch (linearUnitConversion) { case LINEAR_UNITS_MM: return in_mm; break; case LINEAR_UNITS_INCH: return in_mm * INCH_PER_MM; break; case LINEAR_UNITS_CM: return in_mm * CM_PER_MM; break; case LINEAR_UNITS_AUTO: switch (emcStatus->task.programUnits) { case CANON_UNITS_MM: return in_mm; break; case CANON_UNITS_INCHES: return in_mm * INCH_PER_MM; break; case CANON_UNITS_CM: return in_mm * CM_PER_MM; break; } break; case LINEAR_UNITS_CUSTOM: return u; break; } // If it ever gets here we have an error. return u;}/*! \todo Another #if 0 */#if 0static double convertAngularUnits(double u){ double in_deg; /* convert u to deg */ in_deg = u / emcStatus->motion.traj.angularUnits; /* convert u to display units */ switch (angularUnitConversion) { case ANGULAR_UNITS_DEG: return in_deg; break; case ANGULAR_UNITS_RAD: return in_deg * RAD_PER_DEG; break; case ANGULAR_UNITS_GRAD: return in_deg * GRAD_PER_DEG; break; case ANGULAR_UNITS_AUTO: return in_deg; /*! \todo FIXME-- program units always degrees now */ break; case ANGULAR_UNITS_CUSTOM: return u; break; } /* should never get here */ return u;}#endif// polarities for axis jogging, from ini filestatic int jogPol[EMC_AXIS_MAX];int sendDebug(int level){ EMC_SET_DEBUG debug_msg; debug_msg.debug = level; debug_msg.serial_number = ++emcCommandSerialNumber; emcCommandBuffer->write(debug_msg); if (emcWaitType == EMC_WAIT_RECEIVED) { return emcCommandWaitReceived(emcCommandSerialNumber); } else if (emcWaitType == EMC_WAIT_DONE) { return emcCommandWaitDone(emcCommandSerialNumber); } return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?