#ifndef INTERP_INTERNAL_HH
#define INTERP_INTERNAL_HH
#include <algorithm>
#include "config.h"
#include <limits.h>
#include <stdio.h>
#include <set>
#include <map>
#include <bitset>
#include "canon.hh"
#include "emcpos.h"
#include "libintl.h"
#include <boost/python/object_fwd.hpp>
#include <cmath>
#include "interp_parameter_def.hh"
#include "interp_fwd.hh"
#include "interp_base.hh"
#define _(s) gettext(s)
template<class T>
T R2D(T r) { return r * (180. / M_PI); }
template<class T>
T D2R(T r) { return r * (M_PI / 180.); }
template<class T>
T SQ(T a) { return a*a; }
template<class T>
inline int round_to_int(T x) {
return (int)std::nearbyint(x);
}
#define G83_RAPID_DELTA 0.010
#define MAX_NESTED_REMAPS 10
#define MM_PER_INCH 25.4
#define CENTER_ARC_RADIUS_TOLERANCE_INCH (2 * 0.001 * M_SQRT2)
#define MIN_CENTER_ARC_RADIUS_TOLERANCE_INCH 0.00004
#define RADIUS_TOLERANCE_INCH 0.00005
#define CENTER_ARC_RADIUS_TOLERANCE_MM (2 * 0.01 * M_SQRT2)
#define MIN_CENTER_ARC_RADIUS_TOLERANCE_MM 0.001
#define RADIUS_TOLERANCE_MM (RADIUS_TOLERANCE_INCH * MM_PER_INCH)
#define SPIRAL_RELATIVE_TOLERANCE 0.001
#define TOLERANCE_CONCAVE_CORNER 0.05
#define TOLERANCE_EQUAL 0.0001
static inline bool equal(double a, double b)
{
return (fabs(a - b) < TOLERANCE_EQUAL);
}
#define TINY 1e-12
#define MAX_EMS 4
enum FEED_MODE {
UNITS_PER_MINUTE=0,
INVERSE_TIME=1,
UNITS_PER_REVOLUTION=2
};
enum CUTTER_COMP_DIRECTION {
RIGHT = 1,
LEFT = 2,
};
enum SPINDLE_MODE {
CONSTANT_RPM,
CONSTANT_SURFACE
};
enum UnaryOperations
{
ABS = 1,
ACOS = 2,
ASIN = 3,
ATAN = 4,
COS = 5,
EXP = 6,
FIX = 7,
FUP = 8,
LN = 9,
ROUND = 10,
SIN = 11,
SQRT = 12,
TAN = 13,
EXISTS = 14,
};
enum BinaryOperations
{
NO_OPERATION = 0,
DIVIDED_BY = 1,
MODULO = 2,
POWER = 3,
TIMES = 4,
AND2 = 5,
EXCLUSIVE_OR = 6,
MINUS = 7,
NON_EXCLUSIVE_OR = 8,
PLUS = 9,
RIGHT_BRACKET = 10,
LT = 11,
EQ = 12,
NE = 13,
LE = 14,
GE = 15,
GT = 16,
RELATIONAL_OP_FIRST = 11,
RELATIONAL_OP_LAST = 16,
};
enum OCodes
{
O_none = 0,
O_sub = 1,
O_endsub = 2,
O_call = 3,
O_do = 4,
O_while = 5,
O_if = 6,
O_elseif = 7,
O_else = 8,
O_endif = 9,
O_break = 10,
O_continue = 11,
O_endwhile = 12,
O_return = 13,
O_repeat = 14,
O_endrepeat = 15,
M_98 = 16,
M_99 = 17,
O_ = 18,
};
enum GCodes
{
G_0 = 0,
G_1 = 10,
G_2 = 20,
G_3 = 30,
G_4 = 40,
G_5 = 50,
G_5_1 = 51,
G_5_2 = 52,
G_5_3 = 53,
G_7 = 70,
G_8 = 80,
G_10 = 100,
G_17 = 170,
G_17_1 = 171,
G_18 = 180,
G_18_1 = 181,
G_19 = 190,
G_19_1 = 191,
G_20 = 200,
G_21 = 210,
G_28 = 280,
G_28_1 = 281,
G_30 = 300,
G_30_1 = 301,
G_33 = 330,
G_33_1 = 331,
G_38_2 = 382,
G_38_3 = 383,
G_38_4 = 384,
G_38_5 = 385,
G_40 = 400,
G_41 = 410,
G_41_1 = 411,
G_42 = 420,
G_42_1 = 421,
G_43 = 430,
G_43_1 = 431,
G_43_2 = 432,
G_49 = 490,
G_50 = 500,
G_51 = 510,
G_52 = 520,
G_53 = 530,
G_54 = 540,
G_55 = 550,
G_56 = 560,
G_57 = 570,
G_58 = 580,
G_59 = 590,
G_59_1 = 591,
G_59_2 = 592,
G_59_3 = 593,
G_61 = 610,
G_61_1 = 611,
G_64 = 640,
G_73 = 730,
G_74 = 740,
G_76 = 760,
G_80 = 800,
G_81 = 810,
G_82 = 820,
G_83 = 830,
G_84 = 840,
G_85 = 850,
G_86 = 860,
G_87 = 870,
G_88 = 880,
G_89 = 890,
G_90 = 900,
G_90_1 = 901,
G_91 = 910,
G_91_1 = 911,
G_92 = 920,
G_92_1 = 921,
G_92_2 = 922,
G_92_3 = 923,
G_93 = 930,
G_94 = 940,
G_95 = 950,
G_96 = 960,
G_97 = 970,
G_98 = 980,
G_99 = 990,
};
std::string toString(GCodes g);
#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"
#define RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX ".bak"
#define INTERP_SUB_PARAMS 30
#define INTERP_SUB_ROUTINE_LEVELS 10
#define INTERP_FIRST_SUBROUTINE_PARAM 1
#define MAX_NAMED_PARAMETERS 50
enum DISTANCE_MODE
{
MODE_ABSOLUTE,
MODE_INCREMENTAL,
};
enum RETRACT_MODE
{
R_PLANE,
OLD_Z,
};
const char *strstore(const char *s);
enum phases {
NO_REMAPPED_STEPS,
STEP_COMMENT,
STEP_SPINDLE_MODE,
STEP_FEED_MODE,
STEP_SET_FEED_RATE,
STEP_SET_SPINDLE_SPEED,
STEP_PREPARE,
STEP_M_5,
STEP_M_6,
STEP_RETAIN_G43,
STEP_M_7,
STEP_M_8,
STEP_M_9,
STEP_M_10,
STEP_DWELL,
STEP_SET_PLANE,
STEP_LENGTH_UNITS,
STEP_LATHE_DIAMETER_MODE,
STEP_CUTTER_COMP,
STEP_TOOL_LENGTH_OFFSET,
STEP_COORD_SYSTEM,
STEP_CONTROL_MODE,
STEP_DISTANCE_MODE,
STEP_IJK_DISTANCE_MODE,
STEP_RETRACT_MODE,
STEP_MODAL_0,
STEP_MOTION,
STEP_MGROUP4,
MAX_STEPS
};
enum ModalGroups
{
GM_MODAL_0 = 0,
GM_MOTION = 1,
GM_SET_PLANE = 2,
GM_DISTANCE_MODE = 3,
GM_IJK_DISTANCE_MODE = 4,
GM_FEED_MODE = 5,
GM_LENGTH_UNITS = 6,
GM_CUTTER_COMP = 7,
GM_TOOL_LENGTH_OFFSET = 8,
GM_RETRACT_MODE = 10,
GM_COORD_SYSTEM = 12,
GM_CONTROL_MODE = 13,
GM_SPINDLE_MODE = 14,
GM_LATHE_DIAMETER_MODE = 15,
GM_MAX_MODAL_GROUPS
};
struct remap_struct {
const char *name;
const char *argspec;
#define MCODE_DEFAULT_MODAL_GROUP 10
#define GCODE_DEFAULT_MODAL_GROUP 1
int modal_group;
int motion_code; const char *prolog_func; const char *remap_py; const char *remap_ngc; const char *epilog_func; };
struct nocase_cmp
{
bool operator()(const char* s1, const char* s2) const
{
return strcasecmp(s1, s2) < 0;
}
};
typedef std::map<const char *,remap,nocase_cmp> remap_map;
typedef remap_map::iterator remap_iterator;
typedef std::map<int, remap_pointer> int_remap_map;
typedef int_remap_map::iterator int_remap_iterator;
#define REMAP_FUNC(r) (r->remap_ngc ? r->remap_ngc: \
(r->remap_py ? r->remap_py : "BUG-no-remap-func"))
struct block_struct
{
block_struct ();
bool a_flag;
double a_number;
bool b_flag;
double b_number;
bool c_flag;
double c_number;
char comment[256];
double d_number_float;
bool d_flag;
int dollar_number;
bool dollar_flag;
bool e_flag;
double e_number;
bool f_flag;
double f_number;
int g_modes[GM_MAX_MODAL_GROUPS];
bool h_flag;
int h_number;
bool i_flag;
double i_number;
bool j_flag;
double j_number;
bool k_flag;
double k_number;
int l_number;
bool l_flag;
int line_number;
int saved_line_number; int n_number;
int motion_to_be;
int m_count;
int m_modes[11];
int user_m;
double p_number;
bool p_flag;
double q_number;
bool q_flag;
bool r_flag;
double r_number;
bool s_flag;
double s_number;
bool t_flag;
int t_number;
bool u_flag;
double u_number;
bool v_flag;
double v_number;
bool w_flag;
double w_number;
bool x_flag;
double x_number;
bool y_flag;
double y_number;
bool z_flag;
double z_number;
int radius_flag;
double radius;
int theta_flag;
double theta;
long offset; int o_type;
int call_type; const char *o_name; double params[INTERP_SUB_PARAMS];
int param_cnt;
std::bitset<MAX_STEPS> breadcrumbs;
#define TICKOFF(step) block->breadcrumbs[step] = 1
#define TODO(step) (block->breadcrumbs[step] == 0)
#define ONCE(step) (TODO(step) ? TICKOFF(step),1 : 0)
#define ONCE_M(step) (TODO(STEP_M_ ## step) ? TICKOFF(STEP_M_ ## step),1 : 0)
remap_pointer executing_remap; std::set<int> remappings; int phase;
#define STEP_REMAPPED_IN_BLOCK(bp, step) (bp->remappings.find(step) != bp->remappings.end())
bool builtin_used;
};
enum call_states {
CS_NORMAL,
CS_REEXEC_PROLOG,
CS_REEXEC_PYBODY,
CS_REEXEC_EPILOG,
CS_REEXEC_PYOSUB,
};
enum call_types {
CT_NONE, CT_NGC_OWORD_SUB, CT_NGC_M98_SUB, CT_PYTHON_OWORD_SUB, CT_REMAP, };
enum retopts { RET_NONE, RET_DOUBLE, RET_INT, RET_YIELD, RET_STOPITERATION, RET_ERRORMSG };
struct parameter_value_struct {
double value;
unsigned attr;
};
typedef std::map<const char *, parameter_value, nocase_cmp> parameter_map;
typedef parameter_map::iterator parameter_map_iterator;
#define PA_READONLY 1
#define PA_GLOBAL 2
#define PA_UNSET 4
#define PA_USE_LOOKUP 8
#define PA_FROM_INI 16
#define PA_PYTHON 32
#define OVERRIDE_READONLY 1
#define MAX_REMAPOPTS 20
#define M_MODE_OK(m) ((m > 3) && (m < 11))
#define G_MODE_OK(m) (m == 1)
struct pycontext_impl;
struct pycontext {
pycontext();
pycontext(const struct pycontext &);
pycontext &operator=(const struct pycontext &);
~pycontext();
pycontext_impl *impl;
};
struct context_struct {
context_struct();
void clear();
long position; int sequence_number; const char *filename; const char *subName; int m98_loop_counter; double saved_params[INTERP_SUB_PARAMS];
parameter_map named_params;
unsigned char context_status; int saved_g_codes[ACTIVE_G_CODES]; int saved_m_codes[ACTIVE_M_CODES]; double saved_settings[ACTIVE_SETTINGS]; int call_type; pycontext pystuff;
};
#define CONTEXT_VALID 1
#define CONTEXT_RESTORE_ON_RETURN 2
#define REMAP_FRAME 4
struct offset_struct {
int type;
const char *filename; long offset; int sequence_number;
int repeat_count;
};
typedef std::map<const char *, offset, nocase_cmp> offset_map_type;
typedef std::map<const char *, offset, nocase_cmp>::iterator offset_map_iterator;
#define STACK_LEN 50
#define STACK_ENTRY_LEN 80
#define MAX_SUB_DIRS 10
struct setup
{
setup();
~setup();
double AA_axis_offset; double AA_current; double AA_origin_offset; double BB_axis_offset; double BB_current; double BB_origin_offset; double CC_axis_offset; double CC_current; double CC_origin_offset;
double u_axis_offset, u_current, u_origin_offset;
double v_axis_offset, v_current, v_origin_offset;
double w_axis_offset, w_current, w_origin_offset;
int active_g_codes[ACTIVE_G_CODES]; int active_m_codes[ACTIVE_M_CODES]; double active_settings[ACTIVE_SETTINGS]; bool arc_not_allowed; double axis_offset_x; double axis_offset_y; double axis_offset_z; block blocks[MAX_NESTED_REMAPS];
int remap_level;
#define CONTROLLING_BLOCK(s) ((s).blocks[(s).remap_level])
#define EXECUTING_BLOCK(s) ((s).blocks[0])
char blocktext[LINELEN]; CANON_MOTION_MODE control_mode; int current_pocket; double current_x; double current_y; double current_z; double cutter_comp_radius; int cutter_comp_orientation; int cutter_comp_side; double cycle_cc; double cycle_i; double cycle_j; double cycle_k; int cycle_l; double cycle_p; double cycle_q; double cycle_r; double cycle_il; int cycle_il_flag; DISTANCE_MODE distance_mode; DISTANCE_MODE ijk_distance_mode; int feed_mode; bool feed_override; double feed_rate; char filename[PATH_MAX]; FILE *file_pointer; bool flood; CANON_UNITS length_units; double center_arc_radius_tolerance_inch; double center_arc_radius_tolerance_mm; int line_length; char linetext[LINELEN]; bool mist; int motion_mode; int origin_index; double origin_offset_x; double origin_offset_y; double origin_offset_z; double rotation_xy; double parameters[interp_param_global::RS274NGC_MAX_PARAMETERS]; int parameter_occurrence; int parameter_numbers[MAX_NAMED_PARAMETERS]; double parameter_values[MAX_NAMED_PARAMETERS]; int named_parameter_occurrence;
const char *named_parameters[MAX_NAMED_PARAMETERS];
double named_parameter_values[MAX_NAMED_PARAMETERS];
bool percent_flag; CANON_PLANE plane; bool probe_flag; bool input_flag; bool toolchange_flag; int input_index; bool input_digital; bool cutter_comp_firstmove; double program_x; double program_y; double program_z; RETRACT_MODE retract_mode; int random_toolchanger; int selected_pocket; int selected_tool; int sequence_number; int num_spindles; int active_spindle; double speed[EMCMOT_MAX_SPINDLES]; SPINDLE_MODE spindle_mode[EMCMOT_MAX_SPINDLES]; CANON_SPEED_FEED_MODE speed_feed_mode; bool speed_override[EMCMOT_MAX_SPINDLES]; CANON_DIRECTION spindle_turning[EMCMOT_MAX_SPINDLES]; char stack[STACK_LEN][STACK_ENTRY_LEN]; int stack_index; EmcPose tool_offset; int pockets_max; CANON_TOOL_TABLE tool_table[CANON_POCKETS_MAX]; double traverse_rate; double orient_offset;
int defining_sub; const char *sub_name; int doing_continue; int doing_break; int executed_if; const char *skipping_o; const char *skipping_to_sub; int skipping_start; double test_value; double return_value; int value_returned; int call_level; context sub_context[INTERP_SUB_ROUTINE_LEVELS];
int call_state; offset_map_type offset_map;
bool adaptive_feed; bool feed_hold; int loggingLevel; int debugmask; char log_file[PATH_MAX];
char program_prefix[PATH_MAX]; const char *subroutines[MAX_SUB_DIRS]; int use_lazy_close; int lazy_closing; char wizard_root[PATH_MAX];
int tool_change_at_g30;
int tool_change_quill_up;
int tool_change_with_spindle_on;
int a_axis_wrapped;
int b_axis_wrapped;
int c_axis_wrapped;
int a_indexer_jnum;
int b_indexer_jnum;
int c_indexer_jnum;
bool lathe_diameter_mode; bool mdi_interrupt;
int feature_set;
int disable_fanuc_style_sub;
bool loop_on_main_m99;
int disable_g92_persistence;
#define FEATURE(x) (_setup.feature_set & FEATURE_ ## x)
#define FEATURE_RETAIN_G43 0x00000001
#define FEATURE_OWORD_N_ARGS 0x00000002
#define FEATURE_INI_VARS 0x00000004
#define FEATURE_HAL_PIN_VARS 0x00000008
#define FEATURE_NO_DOWNCASE_OWORD 0x00000010
#define FEATURE_OWORD_WARNONLY 0x00000020
boost::python::object *pythis; const char *on_abort_command;
int_remap_map g_remapped,m_remapped;
remap_map remaps;
#define INIT_FUNC "__init__"
#define DELETE_FUNC "__delete__"
int init_once;
};
extern class PythonPlugin *python_plugin;
#define PYUSABLE (((python_plugin) != NULL) && (python_plugin->usable()))
inline bool is_a_cycle(int motion) {
return ((motion > G_80) && (motion < G_90)) || (motion == G_73) || (motion == G_74);
}
#define ERM(fmt, ...) \
do { \
setError (fmt, ## __VA_ARGS__); \
_setup.stack_index = 0; \
strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
_setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
_setup.stack_index++; \
_setup.stack[_setup.stack_index][0] = 0; \
} while(0)
#define ERS(fmt, ...) \
do { \
setError (fmt, ## __VA_ARGS__); \
_setup.stack_index = 0; \
strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
_setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
_setup.stack_index++; \
_setup.stack[_setup.stack_index][0] = 0; \
return INTERP_ERROR; \
} while(0)
#define ERN(error_code) \
do { \
_setup.stack_index = 0; \
strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
_setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
_setup.stack_index++; \
_setup.stack[_setup.stack_index][0] = 0; \
return error_code; \
} while(0)
#define ERP(error_code) \
do { \
if (_setup.stack_index < STACK_LEN - 1) { \
strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
_setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
_setup.stack_index++; \
_setup.stack[_setup.stack_index][0] = 0; \
} \
return error_code; \
} while(0)
#define CHKS(bad, fmt, ...) \
do { \
if (bad) { \
ERS(fmt, ## __VA_ARGS__); \
} \
} while(0)
#define CHKN(bad, error_code) \
do { \
if (bad) { \
ERN(error_code); \
} \
} while(0)
#define CHP(call) \
do { \
int CHP__status = (call); \
if (CHP__status != INTERP_OK) { \
ERP(CHP__status); \
} \
} while(0)
#define OERR(fmt, ...) \
do { \
if (FEATURE(OWORD_WARNONLY)) \
fprintf(stderr,fmt, ## __VA_ARGS__); \
else \
ERS(fmt, ## __VA_ARGS__); \
} while(0)
#define CYCLE_MACRO(call) for (repeat = block->l_number; \
repeat > 0; \
repeat--) \
{ \
aa = (aa + aa_increment); \
bb = (bb + bb_increment); \
if(radius_increment) { \
double radius, theta; \
CHKS((bb == 0 && aa == 0), _("Incremental motion with polar coordinates is indeterminate when at the origin")); \
theta = atan2(bb, aa); \
radius = hypot(bb, aa) + radius_increment; \
aa = radius * cos(theta); \
bb = radius * sin(theta); \
} \
if(theta_increment) { \
double radius, theta; \
CHKS((bb == 0 && aa == 0), _("Incremental motion with polar coordinates is indeterminate when at the origin")); \
theta = atan2(bb, aa) + theta_increment; \
radius = hypot(bb, aa); \
aa = radius * cos(theta); \
bb = radius * sin(theta); \
} \
if ((repeat == block->l_number) && (current_cc > r)) { \
cycle_traverse(block, plane, aa, bb, current_cc); \
cycle_traverse(block, plane, aa, bb, r); \
} else { \
\
cycle_traverse(block, plane, aa, bb, clear_cc); \
if (clear_cc > r) { \
cycle_traverse(block, plane, aa, bb, r); \
} \
} \
CHP(call); \
}
#endif