1 |
|
/******************************************************************** |
2 |
|
* Description: interp_convert.cc |
3 |
|
* |
4 |
|
* Derived from a work by Thomas Kramer |
5 |
|
* |
6 |
|
* Author: |
7 |
|
* License: GPL Version 2 |
8 |
|
* System: Linux |
9 |
|
* |
10 |
|
* Copyright (c) 2004 All rights reserved. |
11 |
|
* |
12 |
|
********************************************************************/ |
13 |
|
#ifndef _GNU_SOURCE |
14 |
|
#define _GNU_SOURCE |
15 |
|
#endif |
16 |
|
#include <unistd.h> |
17 |
|
#include <stdio.h> |
18 |
|
#include <stdlib.h> |
19 |
|
#include <math.h> |
20 |
|
#include <string.h> |
21 |
|
#include <ctype.h> |
22 |
|
#include <sys/types.h> |
23 |
|
#include <sys/stat.h> |
24 |
|
#include <string> |
25 |
|
#include "rtapi_math.h" |
26 |
|
#include "rs274ngc.hh" |
27 |
|
#include "rs274ngc_return.hh" |
28 |
|
#include "rs274ngc_interp.hh" |
29 |
|
#include "interp_internal.hh" |
30 |
|
#include "interp_queue.hh" |
31 |
|
|
32 |
|
#include "units.h" |
33 |
|
#define TOOL_INSIDE_ARC(side, turn) (((side)==LEFT&&(turn)>0)||((side)==RIGHT&&(turn)<0)) |
34 |
|
#define DEBUG_EMC |
35 |
|
|
36 |
|
|
37 |
|
// These four functions help make the rest of cutter comp |
38 |
|
// plane-agnostic in much the same way the ARC_FEED canon call is. |
39 |
|
// The programmer can gleefully think of only the XY plane when |
40 |
|
// reading convert_[straight|arc]_comp[1|2]. |
41 |
|
// |
42 |
|
// Because the STRAIGHT_[FEED|TRAVERSE] canon calls are not |
43 |
|
// plane-agnostic, the opposite plane conversion happens in |
44 |
|
// enqueue_STRAIGHT_[FEED|TRAVERSE] when adding to the interp queue. |
45 |
|
|
46 |
1096 |
int Interp::comp_get_current(setup_pointer settings, double *x, double *y, double *z) { |
47 |
1096 |
switch(settings->plane) { |
48 |
|
case CANON_PLANE_XY: |
49 |
979 |
*x = settings->current_x; |
50 |
979 |
*y = settings->current_y; |
51 |
979 |
*z = settings->current_z; |
52 |
979 |
break; |
53 |
|
case CANON_PLANE_XZ: |
54 |
114 |
*x = settings->current_z; |
55 |
114 |
*y = settings->current_x; |
56 |
114 |
*z = settings->current_y; |
57 |
114 |
break; |
58 |
|
default: |
59 |
3 |
ERS("BUG: Invalid plane in comp_get_current"); |
60 |
|
} |
61 |
|
return INTERP_OK; |
62 |
|
} |
63 |
|
|
64 |
743 |
int Interp::comp_set_current(setup_pointer settings, double x, double y, double z) { |
65 |
743 |
switch(settings->plane) { |
66 |
|
case CANON_PLANE_XY: |
67 |
665 |
settings->current_x = x; |
68 |
665 |
settings->current_y = y; |
69 |
665 |
settings->current_z = z; |
70 |
665 |
break; |
71 |
|
case CANON_PLANE_XZ: |
72 |
78 |
settings->current_x = y; |
73 |
78 |
settings->current_y = z; |
74 |
78 |
settings->current_z = x; |
75 |
78 |
break; |
76 |
|
default: |
77 |
|
ERS("BUG: Invalid plane in comp_set_current"); |
78 |
|
} |
79 |
|
return INTERP_OK; |
80 |
|
} |
81 |
|
|
82 |
685 |
int Interp::comp_get_programmed(setup_pointer settings, double *x, double *y, double *z) { |
83 |
685 |
switch(settings->plane) { |
84 |
|
case CANON_PLANE_XY: |
85 |
609 |
*x = settings->program_x; |
86 |
609 |
*y = settings->program_y; |
87 |
609 |
*z = settings->program_z; |
88 |
609 |
break; |
89 |
|
case CANON_PLANE_XZ: |
90 |
76 |
*x = settings->program_z; |
91 |
76 |
*y = settings->program_x; |
92 |
76 |
*z = settings->program_y; |
93 |
76 |
break; |
94 |
|
default: |
95 |
|
ERS("BUG: Invalid plane in comp_get_programmed"); |
96 |
|
} |
97 |
|
return INTERP_OK; |
98 |
|
} |
99 |
|
|
100 |
743 |
int Interp::comp_set_programmed(setup_pointer settings, double x, double y, double z) { |
101 |
743 |
switch(settings->plane) { |
102 |
|
case CANON_PLANE_XY: |
103 |
665 |
settings->program_x = x; |
104 |
665 |
settings->program_y = y; |
105 |
665 |
settings->program_z = z; |
106 |
665 |
break; |
107 |
|
case CANON_PLANE_XZ: |
108 |
78 |
settings->program_x = y; |
109 |
78 |
settings->program_y = z; |
110 |
78 |
settings->program_z = x; |
111 |
78 |
break; |
112 |
|
default: |
113 |
|
ERS("BUG: Invalid plane in comp_set_programmed"); |
114 |
|
} |
115 |
|
return INTERP_OK; |
116 |
|
} |
117 |
|
|
118 |
|
/****************************************************************************/ |
119 |
|
|
120 |
|
/*! convert_nurbs |
121 |
|
* |
122 |
|
* Returned value: int |
123 |
|
* Returns a rs274ngc error code, or INTERP_OK if everything is OK. |
124 |
|
* |
125 |
|
* Side effects: Generates a nurbs move and updates the position of the tool |
126 |
|
*/ |
127 |
|
|
128 |
|
static unsigned int nurbs_order; |
129 |
69 |
static std::vector<CONTROL_POINT> nurbs_control_points; |
130 |
|
|
131 |
5 |
int Interp::convert_nurbs(int mode, |
132 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
133 |
|
setup_pointer settings) //!< pointer to machine settings |
134 |
|
{ |
135 |
|
double end_z, AA_end, BB_end, CC_end, u_end, v_end, w_end; |
136 |
|
CONTROL_POINT CP; |
137 |
|
|
138 |
5 |
if (mode == G_5_2) { |
139 |
4 |
CHKS((((block->x_flag) && !(block->y_flag)) || (!(block->x_flag) && (block->y_flag))), ( |
140 |
|
_("You must specify both X and Y coordinates for Control Points"))); |
141 |
4 |
CHKS((!(block->x_flag) && !(block->y_flag) && (block->p_number > 0) && |
142 |
|
(!nurbs_control_points.empty())), ( |
143 |
|
_("Can specify P without X and Y only for the first control point"))); |
144 |
|
|
145 |
4 |
CHKS(((block->p_number <= 0) && (!nurbs_control_points.empty())), ( |
146 |
|
_("Must specify positive weight P for every Control Point"))); |
147 |
4 |
if (settings->feed_mode == UNITS_PER_MINUTE) { |
148 |
4 |
CHKS((settings->feed_rate == 0.0), ( |
149 |
|
_("Cannot make a NURBS with 0 feedrate"))); |
150 |
|
} |
151 |
4 |
if (settings->motion_mode != mode) nurbs_control_points.clear(); |
152 |
|
|
153 |
4 |
if (nurbs_control_points.empty()) { |
154 |
1 |
CP.X = settings->current_x; |
155 |
1 |
CP.Y = settings->current_y; |
156 |
1 |
if (!(block->x_flag) && !(block->y_flag) && (block->p_number > 0)) { |
157 |
|
CP.W = block->p_number; |
158 |
|
} else { |
159 |
1 |
CP.W = 1; |
160 |
|
} |
161 |
1 |
nurbs_order = 3; |
162 |
1 |
nurbs_control_points.push_back(CP); |
163 |
|
} |
164 |
4 |
if (block->l_number != -1 && block->l_number > 3) { |
165 |
|
nurbs_order = block->l_number; |
166 |
|
} |
167 |
4 |
if ((block->x_flag) && (block->y_flag)) { |
168 |
4 |
CHP(find_ends(block, settings, &CP.X, &CP.Y, &end_z, &AA_end, &BB_end, &CC_end, |
169 |
|
&u_end, &v_end, &w_end)); |
170 |
4 |
CP.W = block->p_number; |
171 |
4 |
nurbs_control_points.push_back(CP); |
172 |
|
} |
173 |
|
|
174 |
|
//for (i=0;i<nurbs_control_points.size();i++){ |
175 |
|
// printf( "X %8.4f, Y %8.4f, W %8.4f\n", |
176 |
|
// nurbs_control_points[i].X, |
177 |
|
// nurbs_control_points[i].Y, |
178 |
|
// nurbs_control_points[i].W); |
179 |
|
// } |
180 |
|
// printf("*-----------------------------------------*\n"); |
181 |
4 |
settings->motion_mode = mode; |
182 |
|
} |
183 |
|
|
184 |
1 |
else if (mode == G_5_3){ |
185 |
1 |
CHKS((settings->motion_mode != G_5_2), ( |
186 |
|
_("Cannot use G5.3 without G5.2 first"))); |
187 |
1 |
CHKS((nurbs_control_points.size()<nurbs_order), _("You must specify a number of control points at least equal to the order L = %d"), nurbs_order); |
188 |
2 |
settings->current_x = nurbs_control_points[nurbs_control_points.size()-1].X; |
189 |
1 |
settings->current_y = nurbs_control_points[nurbs_control_points.size()-1].Y; |
190 |
2 |
NURBS_FEED(block->line_number, nurbs_control_points, nurbs_order); |
191 |
|
//printf("hello\n"); |
192 |
|
nurbs_control_points.clear(); |
193 |
|
//printf("%d\n", nurbs_control_points.size()); |
194 |
1 |
settings->motion_mode = -1; |
195 |
|
} |
196 |
|
return INTERP_OK; |
197 |
|
} |
198 |
|
|
199 |
|
/****************************************************************************/ |
200 |
|
|
201 |
|
/*! convert_spline |
202 |
|
* |
203 |
|
* Returned value: int |
204 |
|
* Returns a rs274ngc error code, or INTERP_OK if everything is OK. |
205 |
|
* |
206 |
|
* Side effects: Generates a spline move and updates the position of the tool |
207 |
|
*/ |
208 |
|
int Interp::convert_spline(int mode, |
209 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
210 |
|
setup_pointer settings) //!< pointer to machine settings |
211 |
|
{ |
212 |
|
double x1, y1, x2, y2, x3, y3; |
213 |
|
double end_z, AA_end, BB_end, CC_end, u_end, v_end, w_end; |
214 |
|
CONTROL_POINT cp; |
215 |
|
|
216 |
|
CHKS((settings->cutter_comp_side), _("Cannot convert spline with cutter radius compensation")); // XXX |
217 |
|
|
218 |
|
if (settings->feed_mode == UNITS_PER_MINUTE) { |
219 |
|
CHKS((settings->feed_rate == 0.0), |
220 |
|
NCE_CANNOT_MAKE_ARC_WITH_ZERO_FEED_RATE); |
221 |
|
} else if (settings->feed_mode == INVERSE_TIME) { |
222 |
|
CHKS((!block->f_flag), |
223 |
|
NCE_F_WORD_MISSING_WITH_INVERSE_TIME_ARC_MOVE); |
224 |
|
} |
225 |
|
|
226 |
|
CHKS((settings->plane != CANON_PLANE_XY), _("Splines must be in the XY plane")); // XXX |
227 |
|
//Error (for now): Splines must be in XY plane |
228 |
|
|
229 |
|
CHKS((block->z_flag || block->a_flag || block->b_flag |
230 |
|
|| block->c_flag), |
231 |
|
_("Splines may not have motion in Z, A, B, or C")); |
232 |
|
|
233 |
|
if(mode == G_5_1) { |
234 |
|
CHKS(!block->i_flag || !block->j_flag, |
235 |
|
_("Must specify both I and J with G5.1")); |
236 |
|
x1 = settings->current_x + block->i_number; |
237 |
|
y1 = settings->current_y + block->j_number; |
238 |
|
CHP(find_ends(block, settings, &x2, &y2, &end_z, &AA_end, &BB_end, &CC_end, |
239 |
|
&u_end, &v_end, &w_end)); |
240 |
|
cp.W = 1; |
241 |
|
cp.X = settings->current_x, cp.Y = settings->current_y; |
242 |
|
nurbs_control_points.push_back(cp); |
243 |
|
cp.X = x1, cp.Y = y1; |
244 |
|
nurbs_control_points.push_back(cp); |
245 |
|
cp.X = x2, cp.Y = y2; |
246 |
|
nurbs_control_points.push_back(cp); |
247 |
|
NURBS_FEED(block->line_number, nurbs_control_points, 3); |
248 |
|
nurbs_control_points.clear(); |
249 |
|
settings->current_x = x2; |
250 |
|
settings->current_y = y2; |
251 |
|
} else { |
252 |
|
if(!block->i_flag || !block->j_flag) { |
253 |
|
CHKS(block->i_flag || block->j_flag, |
254 |
|
_("Must specify both I and J, or neither")); |
255 |
|
x1 = settings->current_x + settings->cycle_i; |
256 |
|
y1 = settings->current_y + settings->cycle_j; |
257 |
|
} else { |
258 |
|
x1 = settings->current_x + block->i_number; |
259 |
|
y1 = settings->current_y + block->j_number; |
260 |
|
} |
261 |
|
CHP(find_ends(block, settings, &x3, &y3, &end_z, &AA_end, &BB_end, &CC_end, |
262 |
|
&u_end, &v_end, &w_end)); |
263 |
|
|
264 |
|
CHKS(!block->p_flag || !block->q_flag, |
265 |
|
_("Must specify both P and Q with G5")); |
266 |
|
x2 = x3 + block->p_number; |
267 |
|
y2 = y3 + block->q_number; |
268 |
|
|
269 |
|
cp.W = 1; |
270 |
|
cp.X = settings->current_x, cp.Y = settings->current_y; |
271 |
|
nurbs_control_points.push_back(cp); |
272 |
|
cp.X = x1, cp.Y = y1; |
273 |
|
nurbs_control_points.push_back(cp); |
274 |
|
cp.X = x2, cp.Y = y2; |
275 |
|
nurbs_control_points.push_back(cp); |
276 |
|
cp.X = x3, cp.Y = y3; |
277 |
|
nurbs_control_points.push_back(cp); |
278 |
|
NURBS_FEED(block->line_number, nurbs_control_points, 4); |
279 |
|
nurbs_control_points.clear(); |
280 |
|
|
281 |
|
settings->cycle_i = -block->p_number; |
282 |
|
settings->cycle_j = -block->q_number; |
283 |
|
settings->current_x = x3; |
284 |
|
settings->current_y = y3; |
285 |
|
} |
286 |
|
return INTERP_OK; |
287 |
|
} |
288 |
|
|
289 |
|
/****************************************************************************/ |
290 |
|
|
291 |
|
/*! convert_arc |
292 |
|
|
293 |
|
Returned Value: int |
294 |
|
If one of the following functions returns an error code, |
295 |
|
this returns that error code. |
296 |
|
convert_arc_comp1 |
297 |
|
convert_arc_comp2 |
298 |
|
convert_arc2 |
299 |
|
If any of the following errors occur, this returns the error code shown. |
300 |
|
Otherwise, this returns INTERP_OK. |
301 |
|
1. The block has neither an r value nor any i,j,k values: |
302 |
|
NCE_R_I_J_K_WORDS_ALL_MISSING_FOR_ARC |
303 |
|
2. The block has both an r value and one or more i,j,k values: |
304 |
|
NCE_MIXED_RADIUS_IJK_FORMAT_FOR_ARC |
305 |
|
3. In the ijk format the XY-plane is selected and |
306 |
|
the block has a k value: NCE_K_WORD_GIVEN_FOR_ARC_IN_XY_PLANE |
307 |
|
4. In the ijk format the YZ-plane is selected and |
308 |
|
the block has an i value: NCE_I_WORD_GIVEN_FOR_ARC_IN_YZ_PLANE |
309 |
|
5. In the ijk format the XZ-plane is selected and |
310 |
|
the block has a j value: NCE_J_WORD_GIVEN_FOR_ARC_IN_XZ_PLANE |
311 |
|
6. In either format any of the following occurs. |
312 |
|
a. The XY-plane is selected and the block has no x or y value: |
313 |
|
NCE_X_AND_Y_WORDS_MISSING_FOR_ARC_IN_XY_PLANE |
314 |
|
b. The YZ-plane is selected and the block has no y or z value: |
315 |
|
NCE_Y_AND_Z_WORDS_MISSING_FOR_ARC_IN_YZ_PLANE |
316 |
|
c. The ZX-plane is selected and the block has no z or x value: |
317 |
|
NCE_X_AND_Z_WORDS_MISSING_FOR_ARC_IN_XZ_PLANE |
318 |
|
7. The selected plane is an unknown plane: |
319 |
|
NCE_BUG_PLANE_NOT_XY_YZ__OR_XZ |
320 |
|
8. The feed rate mode is UNITS_PER_MINUTE and feed rate is zero: |
321 |
|
NCE_CANNOT_MAKE_ARC_WITH_ZERO_FEED_RATE |
322 |
|
9. The feed rate mode is INVERSE_TIME and the block has no f word: |
323 |
|
NCE_F_WORD_MISSING_WITH_INVERSE_TIME_ARC_MOVE |
324 |
|
|
325 |
|
Side effects: |
326 |
|
This generates and executes an arc command at feed rate |
327 |
|
(and, possibly a second arc command). It also updates the setting |
328 |
|
of the position of the tool point to the end point of the move. |
329 |
|
|
330 |
|
Called by: convert_motion. |
331 |
|
|
332 |
|
This converts a helical or circular arc. The function calls: |
333 |
|
convert_arc2 (when cutter radius compensation is off) or |
334 |
|
convert_arc_comp1 (when cutter comp is on and this is the first move) or |
335 |
|
convert_arc_comp2 (when cutter comp is on and this is not the first move). |
336 |
|
|
337 |
|
If the ijk format is used, at least one of the offsets in the current |
338 |
|
plane must be given in the block; it is common but not required to |
339 |
|
give both offsets. The offsets are always incremental [NCMS, page 21]. |
340 |
|
|
341 |
|
If cutter compensation is in use, the path's length may increase or |
342 |
|
decrease. Also an arc may be added, to go around a corner, before the |
343 |
|
original arc move. For the purpose of calculating the feed rate when in |
344 |
|
inverse time mode, this length increase or decrease is ignored. The |
345 |
|
feed is still set to the original programmed arc length divided by the F |
346 |
|
number (with the above lower bound). The new arc (if needed) and the |
347 |
|
new longer or shorter original arc are taken at this feed. |
348 |
|
|
349 |
|
*/ |
350 |
|
|
351 |
537 |
int Interp::convert_arc(int move, //!< either G_2 (cw arc) or G_3 (ccw arc) |
352 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
353 |
|
setup_pointer settings) //!< pointer to machine settings |
354 |
|
{ |
355 |
|
int status; |
356 |
|
int first; /* flag set true if this is first move after comp true */ |
357 |
|
int ijk_flag; /* flag set true if any of i,j,k present in NC code */ |
358 |
|
double end_x; |
359 |
|
double end_y; |
360 |
|
double end_z; |
361 |
|
double AA_end; |
362 |
|
double BB_end; |
363 |
|
double CC_end; |
364 |
|
double u_end, v_end, w_end; |
365 |
|
|
366 |
537 |
CHKS((settings->arc_not_allowed), (_("The move just after exiting cutter compensation mode must be straight, not an arc"))); |
367 |
|
|
368 |
536 |
ijk_flag = block->i_flag || block->j_flag || block->k_flag; |
369 |
536 |
first = settings->cutter_comp_firstmove; |
370 |
|
|
371 |
536 |
CHKS((settings->plane == CANON_PLANE_UV |
372 |
|
|| settings->plane == CANON_PLANE_VW |
373 |
|
|| settings->plane == CANON_PLANE_UW), |
374 |
|
_("Cannot do an arc in planes G17.1, G18.1, or G19.1")); |
375 |
536 |
CHKS(((!block->r_flag) && (!ijk_flag)), |
376 |
|
NCE_R_I_J_K_WORDS_ALL_MISSING_FOR_ARC); |
377 |
535 |
CHKS(((block->r_flag) && (ijk_flag)), |
378 |
|
NCE_MIXED_RADIUS_IJK_FORMAT_FOR_ARC); |
379 |
535 |
if (settings->feed_mode == UNITS_PER_MINUTE) { |
380 |
532 |
CHKS((settings->feed_rate == 0.0), |
381 |
|
NCE_CANNOT_MAKE_ARC_WITH_ZERO_FEED_RATE); |
382 |
3 |
} else if(settings->feed_mode == UNITS_PER_REVOLUTION) { |
383 |
|
CHKS((settings->feed_rate == 0.0), |
384 |
|
NCE_CANNOT_MAKE_ARC_WITH_ZERO_FEED_RATE); |
385 |
|
CHKS((settings->speed == 0.0), |
386 |
|
_("Cannot feed with zero spindle speed in feed per rev mode")); |
387 |
3 |
} else if (settings->feed_mode == INVERSE_TIME) { |
388 |
3 |
CHKS((!block->f_flag), |
389 |
|
NCE_F_WORD_MISSING_WITH_INVERSE_TIME_ARC_MOVE); |
390 |
|
} |
391 |
|
|
392 |
535 |
if (ijk_flag) { |
393 |
535 |
if (settings->plane == CANON_PLANE_XY) { |
394 |
466 |
CHKS((block->k_flag), NCE_K_WORD_GIVEN_FOR_ARC_IN_XY_PLANE); |
395 |
466 |
if (!block->i_flag) { /* i or j flag on to get here */ |
396 |
138 |
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
397 |
|
ERS(_("%c word missing in absolute center arc"), 'I'); |
398 |
|
} else { |
399 |
138 |
block->i_number = 0.0; |
400 |
|
} |
401 |
328 |
} else if (!block->j_flag) { |
402 |
12 |
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
403 |
|
ERS(_("%c word missing in absolute center arc"), 'J'); |
404 |
|
} else { |
405 |
12 |
block->j_number = 0.0; |
406 |
|
} |
407 |
|
} |
408 |
69 |
} else if (settings->plane == CANON_PLANE_YZ) { |
409 |
|
CHKS((block->i_flag), NCE_I_WORD_GIVEN_FOR_ARC_IN_YZ_PLANE); |
410 |
|
if (!block->j_flag) { /* j or k flag on to get here */ |
411 |
|
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
412 |
|
ERS(_("%c word missing in absolute center arc"), 'J'); |
413 |
|
} else { |
414 |
|
block->j_number = 0.0; |
415 |
|
} |
416 |
|
} else if (!block->k_flag) { |
417 |
|
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
418 |
|
ERS(_("%c word missing in absolute center arc"), 'K'); |
419 |
|
} else { |
420 |
|
block->k_number = 0.0; |
421 |
|
} |
422 |
|
} |
423 |
69 |
} else if (settings->plane == CANON_PLANE_XZ) { |
424 |
69 |
CHKS((block->j_flag), NCE_J_WORD_GIVEN_FOR_ARC_IN_XZ_PLANE); |
425 |
69 |
if (!block->i_flag) { /* i or k flag on to get here */ |
426 |
|
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
427 |
|
ERS(_("%c word missing in absolute center arc"), 'I'); |
428 |
|
} else { |
429 |
|
block->i_number = 0.0; |
430 |
|
} |
431 |
69 |
} else if (!block->k_flag) { |
432 |
|
if (settings->ijk_distance_mode == MODE_ABSOLUTE) { |
433 |
|
ERS(_("%c word missing in absolute center arc"), 'K'); |
434 |
|
} else { |
435 |
|
block->k_number = 0.0; |
436 |
|
} |
437 |
|
} |
438 |
|
} else { |
439 |
|
ERS(NCE_BUG_PLANE_NOT_XY_YZ_OR_XZ); |
440 |
|
} |
441 |
|
} else { |
442 |
|
// in R format, we need some XYZ words specified because a full circle is not allowed. |
443 |
|
if (settings->plane == CANON_PLANE_XY) { |
444 |
|
CHKS(((!block->x_flag) && (!block->y_flag) && (!block->radius_flag) && (!block->theta_flag)), |
445 |
|
NCE_X_AND_Y_WORDS_MISSING_FOR_ARC_IN_XY_PLANE); |
446 |
|
} else if (settings->plane == CANON_PLANE_YZ) { |
447 |
|
CHKS(((!block->y_flag) && (!block->z_flag)), |
448 |
|
NCE_Y_AND_Z_WORDS_MISSING_FOR_ARC_IN_YZ_PLANE); |
449 |
|
} else if (settings->plane == CANON_PLANE_XZ) { |
450 |
|
CHKS(((!block->x_flag) && (!block->z_flag)), |
451 |
|
NCE_X_AND_Z_WORDS_MISSING_FOR_ARC_IN_XZ_PLANE); |
452 |
|
} |
453 |
|
} |
454 |
|
|
455 |
|
|
456 |
535 |
CHP(find_ends(block, settings, &end_x, &end_y, &end_z, |
457 |
|
&AA_end, &BB_end, &CC_end, |
458 |
|
&u_end, &v_end, &w_end)); |
459 |
|
|
460 |
535 |
settings->motion_mode = move; |
461 |
|
|
462 |
|
|
463 |
535 |
if (settings->plane == CANON_PLANE_XY) { |
464 |
878 |
if ((!settings->cutter_comp_side) || |
465 |
412 |
(settings->cutter_comp_radius == 0.0)) { |
466 |
|
status = |
467 |
|
convert_arc2(move, block, settings, |
468 |
|
&(settings->current_x), &(settings->current_y), |
469 |
|
&(settings->current_z), end_x, end_y, end_z, |
470 |
|
AA_end, BB_end, CC_end, |
471 |
|
u_end, v_end, w_end, |
472 |
78 |
block->i_number, block->j_number); |
473 |
78 |
CHP(status); |
474 |
388 |
} else if (first) { |
475 |
|
status = convert_arc_comp1(move, block, settings, end_x, end_y, end_z, |
476 |
|
block->i_number, block->j_number, |
477 |
|
AA_end, BB_end, CC_end, |
478 |
|
u_end, v_end, w_end); |
479 |
|
CHP(status); |
480 |
|
} else { |
481 |
|
status = convert_arc_comp2(move, block, settings, end_x, end_y, end_z, |
482 |
|
block->i_number, block->j_number, |
483 |
|
AA_end, BB_end, CC_end, |
484 |
388 |
u_end, v_end, w_end); |
485 |
388 |
CHP(status); |
486 |
|
} |
487 |
69 |
} else if (settings->plane == CANON_PLANE_XZ) { |
488 |
138 |
if ((!settings->cutter_comp_side) || |
489 |
69 |
(settings->cutter_comp_radius == 0.0)) { |
490 |
|
status = |
491 |
|
convert_arc2(move, block, settings, |
492 |
|
&(settings->current_z), &(settings->current_x), |
493 |
|
&(settings->current_y), end_z, end_x, end_y, |
494 |
|
AA_end, BB_end, CC_end, |
495 |
|
u_end, v_end, w_end, |
496 |
23 |
block->k_number, block->i_number); |
497 |
23 |
CHP(status); |
498 |
46 |
} else if (first) { |
499 |
|
status = convert_arc_comp1(move, block, settings, end_z, end_x, end_y, |
500 |
|
block->k_number, block->i_number, |
501 |
|
AA_end, BB_end, CC_end, |
502 |
|
u_end, v_end, w_end); |
503 |
|
CHP(status); |
504 |
|
} else { |
505 |
|
status = convert_arc_comp2(move, block, settings, end_z, end_x, end_y, |
506 |
|
block->k_number, block->i_number, |
507 |
|
AA_end, BB_end, CC_end, |
508 |
46 |
u_end, v_end, w_end); |
509 |
|
|
510 |
46 |
CHP(status); |
511 |
|
} |
512 |
|
} else if (settings->plane == CANON_PLANE_YZ) { |
513 |
|
status = |
514 |
|
convert_arc2(move, block, settings, |
515 |
|
&(settings->current_y), &(settings->current_z), |
516 |
|
&(settings->current_x), end_y, end_z, end_x, |
517 |
|
AA_end, BB_end, CC_end, |
518 |
|
u_end, v_end, w_end, |
519 |
|
block->j_number, block->k_number); |
520 |
|
CHP(status); |
521 |
|
} else |
522 |
|
ERS(NCE_BUG_PLANE_NOT_XY_YZ_OR_XZ); |
523 |
|
return INTERP_OK; |
524 |
|
} |
525 |
|
|
526 |
|
/****************************************************************************/ |
527 |
|
|
528 |
|
/*! convert_arc2 |
529 |
|
|
530 |
|
Returned Value: int |
531 |
|
If arc_data_ijk or arc_data_r returns an error code, |
532 |
|
this returns that code. |
533 |
|
Otherwise, it returns INTERP_OK. |
534 |
|
|
535 |
|
Side effects: |
536 |
|
This executes an arc command at feed rate. It also updates the |
537 |
|
setting of the position of the tool point to the end point of the move. |
538 |
|
|
539 |
|
Called by: convert_arc. |
540 |
|
|
541 |
|
This converts a helical or circular arc. |
542 |
|
|
543 |
|
*/ |
544 |
|
|
545 |
101 |
int Interp::convert_arc2(int move, //!< either G_2 (cw arc) or G_3 (ccw arc) |
546 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
547 |
|
setup_pointer settings, //!< pointer to machine settings |
548 |
|
double *current1, //!< pointer to current value of coordinate 1 |
549 |
|
double *current2, //!< pointer to current value of coordinate 2 |
550 |
|
double *current3, //!< pointer to current value of coordinate 3 |
551 |
|
double end1, //!< coordinate 1 value at end of arc |
552 |
|
double end2, //!< coordinate 2 value at end of arc |
553 |
|
double end3, //!< coordinate 3 value at end of arc |
554 |
|
double AA_end, //!< a-value at end of arc |
555 |
|
double BB_end, //!< b-value at end of arc |
556 |
|
double CC_end, //!< c-value at end of arc |
557 |
|
double u, double v, double w, //!< values at end of arc |
558 |
|
double offset1, //!< center, either abs or offset from current |
559 |
|
double offset2) |
560 |
|
{ |
561 |
|
double center1; |
562 |
|
double center2; |
563 |
|
int turn; /* number of full or partial turns CCW in arc */ |
564 |
101 |
int plane = settings->plane; |
565 |
|
|
566 |
|
// Spiral tolerance is the amount of "spiral" allowed in a given arc segment, or (r2-r1)/theta |
567 |
101 |
double spiral_abs_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? |
568 |
101 |
settings->center_arc_radius_tolerance_inch : settings->center_arc_radius_tolerance_mm; |
569 |
|
|
570 |
|
// Radius tolerance allows a bit of leeway on the minimum radius for a radius defined arc. |
571 |
|
double radius_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? |
572 |
101 |
RADIUS_TOLERANCE_INCH : RADIUS_TOLERANCE_MM; |
573 |
|
|
574 |
101 |
if (block->r_flag) { |
575 |
|
CHP(arc_data_r(move, plane, *current1, *current2, end1, end2, |
576 |
|
block->r_number, block->p_flag? round_to_int(block->p_number) : 1, |
577 |
|
¢er1, ¢er2, &turn, radius_tolerance)); |
578 |
|
} else { |
579 |
101 |
CHP(arc_data_ijk(move, plane, *current1, *current2, end1, end2, |
580 |
|
(settings->ijk_distance_mode == MODE_ABSOLUTE), |
581 |
|
offset1, offset2, block->p_flag? round_to_int(block->p_number) : 1, |
582 |
|
¢er1, ¢er2, &turn, radius_tolerance, spiral_abs_tolerance, SPIRAL_RELATIVE_TOLERANCE)); |
583 |
|
} |
584 |
|
inverse_time_rate_arc(*current1, *current2, *current3, center1, center2, |
585 |
95 |
turn, end1, end2, end3, block, settings); |
586 |
|
|
587 |
|
ARC_FEED(block->line_number, end1, end2, center1, center2, turn, end3, |
588 |
95 |
AA_end, BB_end, CC_end, u, v, w); |
589 |
95 |
*current1 = end1; |
590 |
95 |
*current2 = end2; |
591 |
95 |
*current3 = end3; |
592 |
95 |
settings->AA_current = AA_end; |
593 |
95 |
settings->BB_current = BB_end; |
594 |
95 |
settings->CC_current = CC_end; |
595 |
95 |
settings->u_current = u; |
596 |
95 |
settings->v_current = v; |
597 |
95 |
settings->w_current = w; |
598 |
|
|
599 |
95 |
return INTERP_OK; |
600 |
|
} |
601 |
|
|
602 |
|
/****************************************************************************/ |
603 |
|
|
604 |
|
/*! convert_arc_comp1 |
605 |
|
|
606 |
|
Returned Value: int |
607 |
|
If arc_data_comp_ijk or arc_data_comp_r returns an error code, |
608 |
|
this returns that code. |
609 |
|
Otherwise, it returns INTERP_OK. |
610 |
|
|
611 |
|
Side effects: |
612 |
|
This executes an arc command at |
613 |
|
feed rate. It also updates the setting of the position of |
614 |
|
the tool point to the end point of the move. |
615 |
|
|
616 |
|
Called by: convert_arc. |
617 |
|
|
618 |
|
This function converts a helical or circular arc, generating only one |
619 |
|
arc. This is called when cutter radius compensation is on and this is |
620 |
|
the first cut after the turning on. |
621 |
|
|
622 |
|
The arc which is generated is derived from a second arc which passes |
623 |
|
through the programmed end point and is tangent to the cutter at its |
624 |
|
current location. The generated arc moves the tool so that it stays |
625 |
|
tangent to the second arc throughout the move. |
626 |
|
|
627 |
|
*/ |
628 |
|
|
629 |
|
int Interp::convert_arc_comp1(int move, //!< either G_2 (cw arc) or G_3 (ccw arc) |
630 |
|
block_pointer block, //!< pointer to a block of RS274/NGC instructions |
631 |
|
setup_pointer settings, //!< pointer to machine settings |
632 |
|
double end_x, //!< x-value at end of programmed (then actual) arc |
633 |
|
double end_y, //!< y-value at end of programmed (then actual) arc |
634 |
|
double end_z, //!< z-value at end of arc |
635 |
|
double offset_x, double offset_y, |
636 |
|
double AA_end, //!< a-value at end of arc |
637 |
|
double BB_end, //!< b-value at end of arc |
638 |
|
double CC_end, //!< c-value at end of arc |
639 |
|
double u_end, double v_end, double w_end) //!< uvw at end of arc |
640 |
|
{ |
641 |
|
double center_x, center_y; |
642 |
|
double gamma; /* direction of perpendicular to arc at end */ |
643 |
|
int side; /* offset side - right or left */ |
644 |
|
double tool_radius; |
645 |
|
int turn; /* 1 for counterclockwise, -1 for clockwise */ |
646 |
|
double cx, cy, cz; // current |
647 |
|
int plane = settings->plane; |
648 |
|
|
649 |
|
side = settings->cutter_comp_side; |
650 |
|
tool_radius = settings->cutter_comp_radius; /* always is positive */ |
651 |
|
|
652 |
|
double spiral_abs_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? settings->center_arc_radius_tolerance_inch : settings->center_arc_radius_tolerance_mm; |
653 |
|
double radius_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? RADIUS_TOLERANCE_INCH : RADIUS_TOLERANCE_MM; |
654 |
|
|
655 |
|
comp_get_current(settings, &cx, &cy, &cz); |
656 |
|
|
657 |
|
CHKS((hypot((end_x - cx), (end_y - cy)) <= tool_radius), |
658 |
|
_("Radius of cutter compensation entry arc is not greater than the tool radius")); |
659 |
|
|
660 |
|
if (block->r_flag) { |
661 |
|
CHP(arc_data_comp_r(move, plane, side, tool_radius, cx, cy, end_x, end_y, |
662 |
|
block->r_number, block->p_flag? round_to_int(block->p_number): 1, |
663 |
|
¢er_x, ¢er_y, &turn, radius_tolerance)); |
664 |
|
} else { |
665 |
|
CHP(arc_data_comp_ijk(move, plane, side, tool_radius, cx, cy, end_x, end_y, |
666 |
|
(settings->ijk_distance_mode == MODE_ABSOLUTE), |
667 |
|
offset_x, offset_y, block->p_flag? round_to_int(block->p_number): 1, |
668 |
|
¢er_x, ¢er_y, &turn, radius_tolerance, spiral_abs_tolerance, SPIRAL_RELATIVE_TOLERANCE)); |
669 |
|
} |
670 |
|
|
671 |
|
inverse_time_rate_arc(cx, cy, cz, center_x, center_y, |
672 |
|
turn, end_x, end_y, end_z, block, settings); |
673 |
|
|
674 |
|
|
675 |
|
// the tool will end up in gamma direction from the programmed arc endpoint |
676 |
|
if TOOL_INSIDE_ARC(side, turn) { |
677 |
|
// tool inside the arc: ends up toward the center |
678 |
|
gamma = atan2((center_y - end_y), (center_x - end_x)); |
679 |
|
} else { |
680 |
|
// outside: away from the center |
681 |
|
gamma = atan2((end_y - center_y), (end_x - center_x)); |
682 |
|
} |
683 |
|
|
684 |
|
settings->cutter_comp_firstmove = false; |
685 |
|
|
686 |
|
comp_set_programmed(settings, end_x, end_y, end_z); |
687 |
|
|
688 |
|
// move endpoint to the compensated position. This changes the radius and center. |
689 |
|
end_x += tool_radius * cos(gamma); |
690 |
|
end_y += tool_radius * sin(gamma); |
691 |
|
|
692 |
|
/* To find the new center: |
693 |
|
imagine a right triangle ABC with A being the endpoint of the |
694 |
|
compensated arc, B being the center of the compensated arc, C being |
695 |
|
the midpoint between start and end of the compensated arc. AB_ang |
696 |
|
is the direction of A->B. A_ang is the angle of the triangle |
697 |
|
itself. We need to find a new center for the compensated arc |
698 |
|
(point B). */ |
699 |
|
|
700 |
|
double b_len = hypot(cy - end_y, cx - end_x) / 2.0; |
701 |
|
double AB_ang = atan2(center_y - end_y, center_x - end_x); |
702 |
|
double A_ang = atan2(cy - end_y, cx - end_x) - AB_ang; |
703 |
|
|
704 |
|
CHKS((fabs(cos(A_ang)) < TOLERANCE_EQUAL), NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP); |
705 |
|
|
706 |
|
double c_len = b_len/cos(A_ang); |
707 |
|
|
708 |
|
// center of the arc is c_len from end in direction AB |
709 |
|
center_x = end_x + c_len * cos(AB_ang); |
710 |
|
center_y = end_y + c_len * sin(AB_ang); |
711 |
|
|
712 |
|
/* center to endpoint distances matched before - they still should. */ |
713 |
|
CHKS((fabs(hypot(center_x-end_x,center_y-end_y) - |
714 |
|
hypot(center_x-cx,center_y-cy)) > spiral_abs_tolerance), |
715 |
|
NCE_BUG_IN_TOOL_RADIUS_COMP); |
716 |
|
|
717 |
|
// need this move for lathes to move the tool origin first. otherwise, the arc isn't an arc. |
718 |
|
if (settings->cutter_comp_orientation != 0 && settings->cutter_comp_orientation != 9) { |
719 |
|
enqueue_STRAIGHT_FEED(settings, block->line_number, |
720 |
|
0, 0, 0, |
721 |
|
cx, cy, cz, |
722 |
|
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
723 |
|
set_endpoint(cx, cy); |
724 |
|
} |
725 |
|
|
726 |
|
enqueue_ARC_FEED(settings, block->line_number, |
727 |
|
find_turn(cx, cy, center_x, center_y, turn, end_x, end_y), |
728 |
|
end_x, end_y, center_x, center_y, turn, end_z, |
729 |
|
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
730 |
|
|
731 |
|
comp_set_current(settings, end_x, end_y, end_z); |
732 |
|
settings->AA_current = AA_end; |
733 |
|
settings->BB_current = BB_end; |
734 |
|
settings->CC_current = CC_end; |
735 |
|
settings->u_current = u_end; |
736 |
|
settings->v_current = v_end; |
737 |
|
settings->w_current = w_end; |
738 |
|
|
739 |
|
return INTERP_OK; |
740 |
|
} |
741 |
|
|
742 |
|
/****************************************************************************/ |
743 |
|
|
744 |
|
/*! convert_arc_comp2 |
745 |
|
|
746 |
|
Returned Value: int |
747 |
|
If arc_data_ijk or arc_data_r returns an error code, |
748 |
|
this returns that code. |
749 |
|
If any of the following errors occurs, this returns the error code shown. |
750 |
|
Otherwise, it returns INTERP_OK. |
751 |
|
1. A concave corner is found: NCE_CONCAVE_CORNER_WITH_CUTTER_RADIUS_COMP |
752 |
|
2. The tool will not fit inside an arc: |
753 |
|
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP |
754 |
|
|
755 |
|
Side effects: |
756 |
|
This executes an arc command feed rate. If needed, at also generates |
757 |
|
an arc to go around a convex corner. It also updates the setting of |
758 |
|
the position of the tool point to the end point of the move. |
759 |
|
Called by: convert_arc. |
760 |
|
|
761 |
|
This function converts a helical or circular arc. The axis must be |
762 |
|
parallel to the z-axis. This is called when cutter radius compensation |
763 |
|
is on and this is not the first cut after the turning on. |
764 |
|
|
765 |
|
If one or more rotary axes is moved in this block and an extra arc is |
766 |
|
required to go around a sharp corner, all the rotary axis motion |
767 |
|
occurs on the main arc and none on the extra arc. An alternative |
768 |
|
might be to distribute the rotary axis motion over the extra arc and |
769 |
|
the programmed arc in proportion to their lengths. |
770 |
|
|
771 |
|
If the Z-axis is moved in this block and an extra arc is required to |
772 |
|
go around a sharp corner, all the Z-axis motion occurs on the main arc |
773 |
|
and none on the extra arc. An alternative might be to distribute the |
774 |
|
Z-axis motion over the extra arc and the main arc in proportion to |
775 |
|
their lengths. |
776 |
|
|
777 |
|
*/ |
778 |
|
|
779 |
434 |
int Interp::convert_arc_comp2(int move, //!< either G_2 (cw arc) or G_3 (ccw arc) |
780 |
|
block_pointer block, //!< pointer to a block of RS274/NGC instructions |
781 |
|
setup_pointer settings, //!< pointer to machine settings |
782 |
|
double end_x, //!< x-value at end of programmed (then actual) arc |
783 |
|
double end_y, //!< y-value at end of programmed (then actual) arc |
784 |
|
double end_z, //!< z-value at end of arc |
785 |
|
double offset_x, double offset_y, |
786 |
|
double AA_end, //!< a-value at end of arc |
787 |
|
double BB_end, //!< b-value at end of arc |
788 |
|
double CC_end, //!< c-value at end of arc |
789 |
|
double u, double v, double w) //!< uvw at end of arc |
790 |
|
{ |
791 |
|
double alpha; /* direction of tangent to start of arc */ |
792 |
|
double arc_radius; |
793 |
|
double beta; /* angle between two tangents above */ |
794 |
|
double centerx, centery; /* center of arc */ |
795 |
|
double delta; /* direction of radius from start of arc to center of arc */ |
796 |
|
double gamma; /* direction of perpendicular to arc at end */ |
797 |
|
double midx, midy; |
798 |
|
int side; |
799 |
434 |
double small = TOLERANCE_CONCAVE_CORNER; /* angle for testing corners */ |
800 |
|
double opx, opy, opz; |
801 |
|
double theta; /* direction of tangent to last cut */ |
802 |
|
double tool_radius; |
803 |
|
int turn; /* number of full or partial circles CCW */ |
804 |
434 |
int plane = settings->plane; |
805 |
|
double cx, cy, cz; |
806 |
|
double new_end_x, new_end_y; |
807 |
|
|
808 |
434 |
double spiral_abs_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? settings->center_arc_radius_tolerance_inch : settings->center_arc_radius_tolerance_mm; |
809 |
434 |
double radius_tolerance = (settings->length_units == CANON_UNITS_INCHES) ? RADIUS_TOLERANCE_INCH : RADIUS_TOLERANCE_MM; |
810 |
|
|
811 |
|
/* find basic arc data: center_x, center_y, and turn */ |
812 |
|
|
813 |
434 |
comp_get_programmed(settings, &opx, &opy, &opz); |
814 |
434 |
comp_get_current(settings, &cx, &cy, &cz); |
815 |
|
|
816 |
|
|
817 |
434 |
if (block->r_flag) { |
818 |
|
CHP(arc_data_r(move, plane, opx, opy, end_x, end_y, |
819 |
|
block->r_number, block->p_flag? round_to_int(block->p_number): 1, |
820 |
|
¢erx, ¢ery, &turn, radius_tolerance)); |
821 |
|
} else { |
822 |
434 |
CHP(arc_data_ijk(move, plane, |
823 |
|
opx, opy, end_x, end_y, |
824 |
|
(settings->ijk_distance_mode == MODE_ABSOLUTE), |
825 |
|
offset_x, offset_y, block->p_flag? round_to_int(block->p_number): 1, |
826 |
|
¢erx, ¢ery, &turn, radius_tolerance, spiral_abs_tolerance, SPIRAL_RELATIVE_TOLERANCE)); |
827 |
|
} |
828 |
|
|
829 |
|
inverse_time_rate_arc(opx, opy, opz, centerx, centery, |
830 |
434 |
turn, end_x, end_y, end_z, block, settings); |
831 |
|
|
832 |
434 |
side = settings->cutter_comp_side; |
833 |
434 |
tool_radius = settings->cutter_comp_radius; /* always is positive */ |
834 |
434 |
arc_radius = hypot((centerx - end_x), (centery - end_y)); |
835 |
434 |
theta = atan2(cy - opy, cx - opx); |
836 |
434 |
theta = (side == LEFT) ? (theta - M_PI_2l) : (theta + M_PI_2l); |
837 |
434 |
delta = atan2(centery - opy, centerx - opx); |
838 |
434 |
alpha = (move == G_3) ? (delta - M_PI_2l) : (delta + M_PI_2l); |
839 |
434 |
beta = (side == LEFT) ? (theta - alpha) : (alpha - theta); |
840 |
|
|
841 |
|
// normalize beta -90 to +270? |
842 |
434 |
beta = (beta > (1.5 * M_PIl)) ? (beta - (2 * M_PIl)) : (beta < -M_PI_2l) ? (beta + (2 * M_PIl)) : beta; |
843 |
|
|
844 |
434 |
if (((side == LEFT) && (move == G_3)) || ((side == RIGHT) && (move == G_2))) { |
845 |
|
// we are cutting inside the arc |
846 |
287 |
gamma = atan2((centery - end_y), (centerx - end_x)); |
847 |
287 |
CHKS((arc_radius <= tool_radius), |
848 |
|
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP); |
849 |
|
} else { |
850 |
147 |
gamma = atan2((end_y - centery), (end_x - centerx)); |
851 |
147 |
delta = (delta + M_PIl); |
852 |
|
} |
853 |
|
|
854 |
|
// move arc endpoint to the compensated position |
855 |
434 |
new_end_x = end_x + tool_radius * cos(gamma); |
856 |
434 |
new_end_y = end_y + tool_radius * sin(gamma); |
857 |
|
|
858 |
841 |
if (beta < -small || |
859 |
787 |
beta > M_PIl + small || |
860 |
|
// special detection for convex corner on tangent arc->arc (like atop the middle of "m" shape) |
861 |
|
// or tangent line->arc (atop "h" shape) |
862 |
392 |
(fabs(beta - M_PIl) < small && !TOOL_INSIDE_ARC(side, turn)) |
863 |
|
) { |
864 |
|
// concave |
865 |
120 |
if (qc().front().type != QARC_FEED) { |
866 |
|
// line->arc |
867 |
34 |
double cy = arc_radius * sin(beta - M_PI_2l); |
868 |
|
double toward_nominal; |
869 |
|
double dist_from_center; |
870 |
|
double angle_from_center; |
871 |
|
|
872 |
34 |
if TOOL_INSIDE_ARC(side, turn) { |
873 |
|
// tool is inside the arc |
874 |
8 |
dist_from_center = arc_radius - tool_radius; |
875 |
8 |
toward_nominal = cy + tool_radius; |
876 |
8 |
double l = toward_nominal / dist_from_center; |
877 |
8 |
CHKS((l > 1.0 || l < -1.0), _("Arc move in concave corner cannot be reached by the tool without gouging")); |
878 |
8 |
if(turn > 0) { |
879 |
4 |
angle_from_center = theta + asin(l); |
880 |
|
} else { |
881 |
4 |
angle_from_center = theta - asin(l); |
882 |
|
} |
883 |
|
} else { |
884 |
26 |
dist_from_center = arc_radius + tool_radius; |
885 |
26 |
toward_nominal = cy - tool_radius; |
886 |
26 |
double l = toward_nominal / dist_from_center; |
887 |
26 |
CHKS((l > 1.0 || l < -1.0), _("Arc move in concave corner cannot be reached by the tool without gouging")); |
888 |
26 |
if(turn > 0) { |
889 |
10 |
angle_from_center = theta + M_PIl - asin(l); |
890 |
|
} else { |
891 |
16 |
angle_from_center = theta + M_PIl + asin(l); |
892 |
|
} |
893 |
|
} |
894 |
|
|
895 |
34 |
midx = centerx + dist_from_center * cos(angle_from_center); |
896 |
34 |
midy = centery + dist_from_center * sin(angle_from_center); |
897 |
|
|
898 |
34 |
CHP(move_endpoint_and_flush(settings, midx, midy)); |
899 |
|
} else { |
900 |
|
// arc->arc |
901 |
52 |
struct arc_feed &prev = qc().front().data.arc_feed; |
902 |
26 |
double oldrad = hypot(prev.center2 - prev.end2, prev.center1 - prev.end1); |
903 |
|
double newrad; |
904 |
26 |
if TOOL_INSIDE_ARC(side, turn) { |
905 |
5 |
newrad = arc_radius - tool_radius; |
906 |
|
} else { |
907 |
21 |
newrad = arc_radius + tool_radius; |
908 |
|
} |
909 |
|
|
910 |
|
double arc_cc, pullback, cc_dir, a; |
911 |
26 |
arc_cc = hypot(prev.center2 - centery, prev.center1 - centerx); |
912 |
|
|
913 |
26 |
CHKS((oldrad == 0 || arc_cc == 0), _("Arc to arc motion is invalid because the arcs have the same center")); |
914 |
78 |
a = (SQ(oldrad) + SQ(arc_cc) - SQ(newrad)) / (2 * oldrad * arc_cc); |
915 |
|
|
916 |
26 |
CHKS((a > 1.0 || a < -1.0), (_("Arc to arc motion makes a corner the compensated tool can't fit in without gouging"))); |
917 |
26 |
pullback = acos(a); |
918 |
26 |
cc_dir = atan2(centery - prev.center2, centerx - prev.center1); |
919 |
|
|
920 |
|
double dir; |
921 |
26 |
if TOOL_INSIDE_ARC(side, prev.turn) { |
922 |
10 |
if(turn > 0) |
923 |
5 |
dir = cc_dir + pullback; |
924 |
|
else |
925 |
5 |
dir = cc_dir - pullback; |
926 |
|
} else { |
927 |
16 |
if(turn > 0) |
928 |
9 |
dir = cc_dir - pullback; |
929 |
|
else |
930 |
7 |
dir = cc_dir + pullback; |
931 |
|
} |
932 |
|
|
933 |
26 |
midx = prev.center1 + oldrad * cos(dir); |
934 |
26 |
midy = prev.center2 + oldrad * sin(dir); |
935 |
|
|
936 |
26 |
CHP(move_endpoint_and_flush(settings, midx, midy)); |
937 |
|
} |
938 |
|
enqueue_ARC_FEED(settings, block->line_number, |
939 |
|
find_turn(opx, opy, centerx, centery, turn, end_x, end_y), |
940 |
|
new_end_x, new_end_y, centerx, centery, turn, end_z, |
941 |
60 |
AA_end, BB_end, CC_end, u, v, w); |
942 |
374 |
} else if (beta > small) { /* convex, two arcs needed */ |
943 |
60 |
midx = opx + tool_radius * cos(delta); |
944 |
60 |
midy = opy + tool_radius * sin(delta); |
945 |
60 |
dequeue_canons(settings); |
946 |
|
enqueue_ARC_FEED(settings, block->line_number, |
947 |
|
0.0, // doesn't matter since we won't move this arc's endpoint |
948 |
|
midx, midy, opx, opy, ((side == LEFT) ? -1 : 1), |
949 |
|
cz, |
950 |
60 |
AA_end, BB_end, CC_end, u, v, w); |
951 |
60 |
dequeue_canons(settings); |
952 |
60 |
set_endpoint(midx, midy); |
953 |
|
enqueue_ARC_FEED(settings, block->line_number, |
954 |
|
find_turn(opx, opy, centerx, centery, turn, end_x, end_y), |
955 |
|
new_end_x, new_end_y, centerx, centery, turn, end_z, |
956 |
60 |
AA_end, BB_end, CC_end, u, v, w); |
957 |
|
} else { /* convex, one arc needed */ |
958 |
314 |
dequeue_canons(settings); |
959 |
314 |
set_endpoint(cx, cy); |
960 |
|
enqueue_ARC_FEED(settings, block->line_number, |
961 |
|
find_turn(opx, opy, centerx, centery, turn, end_x, end_y), |
962 |
|
new_end_x, new_end_y, centerx, centery, turn, end_z, |
963 |
314 |
AA_end, BB_end, CC_end, u, v, w); |
964 |
|
} |
965 |
|
|
966 |
434 |
comp_set_programmed(settings, end_x, end_y, end_z); |
967 |
434 |
comp_set_current(settings, new_end_x, new_end_y, end_z); |
968 |
434 |
settings->AA_current = AA_end; |
969 |
434 |
settings->BB_current = BB_end; |
970 |
434 |
settings->CC_current = CC_end; |
971 |
434 |
settings->u_current = u; |
972 |
434 |
settings->v_current = v; |
973 |
434 |
settings->w_current = w; |
974 |
|
|
975 |
434 |
return INTERP_OK; |
976 |
|
} |
977 |
|
|
978 |
|
/****************************************************************************/ |
979 |
|
|
980 |
|
/*! convert_axis_offsets |
981 |
|
|
982 |
|
Returned Value: int |
983 |
|
If any of the following errors occur, this returns the error code shown. |
984 |
|
Otherwise, it returns INTERP_OK. |
985 |
|
1. The function is called when cutter radius compensation is on: |
986 |
|
NCE_CANNOT_CHANGE_AXIS_OFFSETS_WITH_CUTTER_RADIUS_COMP |
987 |
|
2. The g_code argument is not G_52, G_92, G_92_1, G_92_2, or G_92_3 |
988 |
|
NCE_BUG_CODE_NOT_IN_G52_G92_SERIES |
989 |
|
|
990 |
|
Side effects: |
991 |
|
SET_G92_OFFSET is called, and the coordinate |
992 |
|
values for the axis offsets are reset. The coordinates of the |
993 |
|
current point are reset. Parameters may be set. |
994 |
|
|
995 |
|
Called by: convert_modal_0. |
996 |
|
|
997 |
|
The action of G92 is described in [NCMS, pages 10 - 11] and {Fanuc, |
998 |
|
pages 61 - 63]. [NCMS] is ambiguous about the intent, but [Fanuc] |
999 |
|
is clear. When G92 is executed, an offset of the origin is calculated |
1000 |
|
so that the coordinates of the current point with respect to the moved |
1001 |
|
origin are as specified on the line containing the G92. If an axis |
1002 |
|
is not mentioned on the line, the coordinates of the current point |
1003 |
|
are not changed. The execution of G92 results in an axis offset being |
1004 |
|
calculated and saved for each of the six axes, and the axis offsets |
1005 |
|
are always used when motion is specified with respect to absolute |
1006 |
|
distance mode using any of the nine coordinate systems (those designated |
1007 |
|
by G54 - G59.3). Thus all nine coordinate systems are affected by G92. |
1008 |
|
|
1009 |
|
Being in incremental distance mode has no effect on the action of G92 |
1010 |
|
in this implementation. [NCMS] is not explicit about this, but it is |
1011 |
|
implicit in the second sentence of [Fanuc, page 61]. |
1012 |
|
|
1013 |
|
The offset is the amount the origin must be moved so that the |
1014 |
|
coordinate of the controlled point has the specified value. For |
1015 |
|
example, if the current point is at X=4 in the currently specified |
1016 |
|
coordinate system and the current X-axis offset is zero, then "G92 x7" |
1017 |
|
causes the X-axis offset to be reset to -3. |
1018 |
|
|
1019 |
|
Since a non-zero offset may be already be in effect when the G92 is |
1020 |
|
called, that must be taken into account. |
1021 |
|
|
1022 |
|
In addition to causing the axis offset values in the _setup model to be |
1023 |
|
set, G52 and G92 set parameters 5211 to 5216 to the x,y,z,a,b,c axis |
1024 |
|
offsets. |
1025 |
|
|
1026 |
|
The action of G92.2 is described in [NCMS, page 12]. There is no |
1027 |
|
equivalent command in [Fanuc]. G92.2 resets axis offsets to zero. |
1028 |
|
G92.1, also included in [NCMS, page 12] (but the usage here differs |
1029 |
|
slightly from the spec), is like G92.2, except that it also causes |
1030 |
|
the axis offset parameters to be set to zero, whereas G92.2 does not |
1031 |
|
zero out the parameters. |
1032 |
|
|
1033 |
|
G92.3 is not in [NCMS]. It sets the axis offset values to the values |
1034 |
|
given in the parameters. |
1035 |
|
|
1036 |
|
*/ |
1037 |
|
|
1038 |
12 |
int Interp::convert_axis_offsets(int g_code, //!< g_code being executed (must be in G_92 series) |
1039 |
|
block_pointer block, //!< pointer to a block of RS274/NGC instructions |
1040 |
|
setup_pointer settings) //!< pointer to machine settings |
1041 |
|
{ |
1042 |
|
double *pars; /* short name for settings->parameters */ |
1043 |
|
|
1044 |
12 |
CHKS((settings->cutter_comp_side), /* not "== true" */ |
1045 |
|
NCE_CANNOT_CHANGE_AXIS_OFFSETS_WITH_CUTTER_RADIUS_COMP); |
1046 |
12 |
CHKS((block->a_flag && settings->a_axis_wrapped && |
1047 |
|
(block->a_number <= -360.0 || block->a_number >= 360.0)), |
1048 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), |
1049 |
|
block->a_number, 'A'); |
1050 |
12 |
CHKS((block->b_flag && settings->b_axis_wrapped && |
1051 |
|
(block->b_number <= -360.0 || block->b_number >= 360.0)), |
1052 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), |
1053 |
|
block->b_number, 'B'); |
1054 |
12 |
CHKS((block->c_flag && settings->c_axis_wrapped && |
1055 |
|
(block->c_number <= -360.0 || block->c_number >= 360.0)), |
1056 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), |
1057 |
|
block->c_number, 'C'); |
1058 |
12 |
pars = settings->parameters; |
1059 |
12 |
if ((g_code == G_52) || (g_code == G_92)) { |
1060 |
5 |
pars[5210] = 1.0; |
1061 |
|
|
1062 |
5 |
if (g_code == G_52) { |
1063 |
2 |
if (block->x_flag) { |
1064 |
2 |
settings->current_x += settings->axis_offset_x - block->x_number; |
1065 |
2 |
settings->axis_offset_x = block->x_number; |
1066 |
|
} |
1067 |
|
|
1068 |
2 |
if (block->y_flag) { |
1069 |
2 |
settings->current_y += settings->axis_offset_y - block->y_number; |
1070 |
2 |
settings->axis_offset_y = block->y_number; |
1071 |
|
} |
1072 |
|
|
1073 |
2 |
if (block->z_flag) { |
1074 |
|
settings->current_z += settings->axis_offset_z - block->z_number; |
1075 |
|
settings->axis_offset_z = block->z_number; |
1076 |
|
} |
1077 |
2 |
if (block->a_flag) { |
1078 |
|
settings->AA_current += settings->AA_axis_offset - block->a_number; |
1079 |
|
settings->AA_axis_offset = block->a_number; |
1080 |
|
} |
1081 |
2 |
if (block->b_flag) { |
1082 |
|
settings->BB_current += settings->BB_axis_offset - block->b_number; |
1083 |
|
settings->BB_axis_offset = block->b_number; |
1084 |
|
} |
1085 |
2 |
if (block->c_flag) { |
1086 |
|
settings->CC_current += settings->CC_axis_offset - block->c_number; |
1087 |
|
settings->CC_axis_offset = block->c_number; |
1088 |
|
} |
1089 |
2 |
if (block->u_flag) { |
1090 |
|
settings->u_current += settings->u_axis_offset - block->u_number; |
1091 |
|
settings->u_axis_offset = block->u_number; |
1092 |
|
} |
1093 |
2 |
if (block->v_flag) { |
1094 |
|
settings->v_current += settings->v_axis_offset - block->v_number; |
1095 |
|
settings->v_axis_offset = block->v_number; |
1096 |
|
} |
1097 |
2 |
if (block->w_flag) { |
1098 |
|
settings->w_current += settings->w_axis_offset - block->w_number; |
1099 |
|
settings->w_axis_offset = block->w_number; |
1100 |
|
} |
1101 |
|
|
1102 |
|
} else { |
1103 |
3 |
if (block->x_flag) { |
1104 |
|
settings->axis_offset_x = |
1105 |
3 |
(settings->current_x + settings->axis_offset_x - block->x_number); |
1106 |
3 |
settings->current_x = block->x_number; |
1107 |
|
} |
1108 |
|
|
1109 |
3 |
if (block->y_flag) { |
1110 |
|
settings->axis_offset_y = |
1111 |
3 |
(settings->current_y + settings->axis_offset_y - block->y_number); |
1112 |
3 |
settings->current_y = block->y_number; |
1113 |
|
} |
1114 |
|
|
1115 |
3 |
if (block->z_flag) { |
1116 |
|
settings->axis_offset_z = |
1117 |
2 |
(settings->current_z + settings->axis_offset_z - block->z_number); |
1118 |
2 |
settings->current_z = block->z_number; |
1119 |
|
} |
1120 |
3 |
if (block->a_flag) { |
1121 |
|
settings->AA_axis_offset = (settings->AA_current + |
1122 |
|
settings->AA_axis_offset - block->a_number); |
1123 |
|
settings->AA_current = block->a_number; |
1124 |
|
} |
1125 |
3 |
if (block->b_flag) { |
1126 |
|
settings->BB_axis_offset = (settings->BB_current + |
1127 |
|
settings->BB_axis_offset - block->b_number); |
1128 |
|
settings->BB_current = block->b_number; |
1129 |
|
} |
1130 |
3 |
if (block->c_flag) { |
1131 |
|
settings->CC_axis_offset = (settings->CC_current + |
1132 |
|
settings->CC_axis_offset - block->c_number); |
1133 |
|
settings->CC_current = block->c_number; |
1134 |
|
} |
1135 |
3 |
if (block->u_flag) { |
1136 |
|
settings->u_axis_offset = (settings->u_current + |
1137 |
|
settings->u_axis_offset - block->u_number); |
1138 |
|
settings->u_current = block->u_number; |
1139 |
|
} |
1140 |
3 |
if (block->v_flag) { |
1141 |
|
settings->v_axis_offset = (settings->v_current + |
1142 |
|
settings->v_axis_offset - block->v_number); |
1143 |
|
settings->v_current = block->v_number; |
1144 |
|
} |
1145 |
3 |
if (block->w_flag) { |
1146 |
|
settings->w_axis_offset = (settings->w_current + |
1147 |
|
settings->w_axis_offset - block->w_number); |
1148 |
|
settings->w_current = block->w_number; |
1149 |
|
} |
1150 |
|
} |
1151 |
|
|
1152 |
|
SET_G92_OFFSET(settings->axis_offset_x, |
1153 |
|
settings->axis_offset_y, |
1154 |
|
settings->axis_offset_z, |
1155 |
|
settings->AA_axis_offset, |
1156 |
|
settings->BB_axis_offset, |
1157 |
|
settings->CC_axis_offset, |
1158 |
|
settings->u_axis_offset, |
1159 |
|
settings->v_axis_offset, |
1160 |
5 |
settings->w_axis_offset); |
1161 |
|
|
1162 |
5 |
pars[5211] = PROGRAM_TO_USER_LEN(settings->axis_offset_x); |
1163 |
5 |
pars[5212] = PROGRAM_TO_USER_LEN(settings->axis_offset_y); |
1164 |
5 |
pars[5213] = PROGRAM_TO_USER_LEN(settings->axis_offset_z); |
1165 |
5 |
pars[5214] = PROGRAM_TO_USER_ANG(settings->AA_axis_offset); |
1166 |
5 |
pars[5215] = PROGRAM_TO_USER_ANG(settings->BB_axis_offset); |
1167 |
5 |
pars[5216] = PROGRAM_TO_USER_ANG(settings->CC_axis_offset); |
1168 |
5 |
pars[5217] = PROGRAM_TO_USER_LEN(settings->u_axis_offset); |
1169 |
5 |
pars[5218] = PROGRAM_TO_USER_LEN(settings->v_axis_offset); |
1170 |
5 |
pars[5219] = PROGRAM_TO_USER_LEN(settings->w_axis_offset); |
1171 |
|
|
1172 |
7 |
} else if ((g_code == G_92_1) || (g_code == G_92_2)) { |
1173 |
5 |
pars[5210] = 0.0; |
1174 |
5 |
settings->current_x = settings->current_x + settings->axis_offset_x; |
1175 |
5 |
settings->current_y = settings->current_y + settings->axis_offset_y; |
1176 |
5 |
settings->current_z = settings->current_z + settings->axis_offset_z; |
1177 |
5 |
settings->AA_current = (settings->AA_current + settings->AA_axis_offset); |
1178 |
5 |
settings->BB_current = (settings->BB_current + settings->BB_axis_offset); |
1179 |
5 |
settings->CC_current = (settings->CC_current + settings->CC_axis_offset); |
1180 |
5 |
settings->u_current = (settings->u_current + settings->u_axis_offset); |
1181 |
5 |
settings->v_current = (settings->v_current + settings->v_axis_offset); |
1182 |
5 |
settings->w_current = (settings->w_current + settings->w_axis_offset); |
1183 |
|
|
1184 |
5 |
SET_G92_OFFSET(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
1185 |
|
|
1186 |
5 |
settings->axis_offset_x = 0.0; |
1187 |
5 |
settings->axis_offset_y = 0.0; |
1188 |
5 |
settings->axis_offset_z = 0.0; |
1189 |
5 |
settings->AA_axis_offset = 0.0; |
1190 |
5 |
settings->BB_axis_offset = 0.0; |
1191 |
5 |
settings->CC_axis_offset = 0.0; |
1192 |
5 |
settings->u_axis_offset = 0.0; |
1193 |
5 |
settings->v_axis_offset = 0.0; |
1194 |
5 |
settings->w_axis_offset = 0.0; |
1195 |
5 |
if (g_code == G_92_1) { |
1196 |
3 |
pars[5211] = 0.0; |
1197 |
3 |
pars[5212] = 0.0; |
1198 |
3 |
pars[5213] = 0.0; |
1199 |
3 |
pars[5214] = 0.0; |
1200 |
3 |
pars[5215] = 0.0; |
1201 |
3 |
pars[5216] = 0.0; |
1202 |
3 |
pars[5217] = 0.0; |
1203 |
3 |
pars[5218] = 0.0; |
1204 |
3 |
pars[5219] = 0.0; |
1205 |
|
} |
1206 |
2 |
} else if (g_code == G_92_3) { |
1207 |
2 |
pars[5210] = 1.0; |
1208 |
|
settings->current_x = |
1209 |
2 |
settings->current_x + settings->axis_offset_x - USER_TO_PROGRAM_LEN(pars[5211]); |
1210 |
|
settings->current_y = |
1211 |
2 |
settings->current_y + settings->axis_offset_y - USER_TO_PROGRAM_LEN(pars[5212]); |
1212 |
|
settings->current_z = |
1213 |
2 |
settings->current_z + settings->axis_offset_z - USER_TO_PROGRAM_LEN(pars[5213]); |
1214 |
|
settings->AA_current = |
1215 |
2 |
settings->AA_current + settings->AA_axis_offset - USER_TO_PROGRAM_ANG(pars[5214]); |
1216 |
|
settings->BB_current = |
1217 |
2 |
settings->BB_current + settings->BB_axis_offset - USER_TO_PROGRAM_ANG(pars[5215]); |
1218 |
|
settings->CC_current = |
1219 |
2 |
settings->CC_current + settings->CC_axis_offset - USER_TO_PROGRAM_ANG(pars[5216]); |
1220 |
|
settings->u_current = |
1221 |
2 |
settings->u_current + settings->u_axis_offset - USER_TO_PROGRAM_LEN(pars[5217]); |
1222 |
|
settings->v_current = |
1223 |
2 |
settings->v_current + settings->v_axis_offset - USER_TO_PROGRAM_LEN(pars[5218]); |
1224 |
|
settings->w_current = |
1225 |
2 |
settings->w_current + settings->w_axis_offset - USER_TO_PROGRAM_LEN(pars[5219]); |
1226 |
|
|
1227 |
2 |
settings->axis_offset_x = USER_TO_PROGRAM_LEN(pars[5211]); |
1228 |
2 |
settings->axis_offset_y = USER_TO_PROGRAM_LEN(pars[5212]); |
1229 |
2 |
settings->axis_offset_z = USER_TO_PROGRAM_LEN(pars[5213]); |
1230 |
2 |
settings->AA_axis_offset = USER_TO_PROGRAM_ANG(pars[5214]); |
1231 |
2 |
settings->BB_axis_offset = USER_TO_PROGRAM_ANG(pars[5215]); |
1232 |
2 |
settings->CC_axis_offset = USER_TO_PROGRAM_ANG(pars[5216]); |
1233 |
2 |
settings->u_axis_offset = USER_TO_PROGRAM_LEN(pars[5217]); |
1234 |
2 |
settings->v_axis_offset = USER_TO_PROGRAM_LEN(pars[5218]); |
1235 |
2 |
settings->w_axis_offset = USER_TO_PROGRAM_LEN(pars[5219]); |
1236 |
|
|
1237 |
|
SET_G92_OFFSET(settings->axis_offset_x, |
1238 |
|
settings->axis_offset_y, |
1239 |
|
settings->axis_offset_z, |
1240 |
|
settings->AA_axis_offset, |
1241 |
|
settings->BB_axis_offset, |
1242 |
|
settings->CC_axis_offset, |
1243 |
|
settings->u_axis_offset, |
1244 |
|
settings->v_axis_offset, |
1245 |
2 |
settings->w_axis_offset); |
1246 |
|
} else |
1247 |
|
ERS(NCE_BUG_CODE_NOT_IN_G52_G92_SERIES); |
1248 |
|
|
1249 |
|
return INTERP_OK; |
1250 |
|
} |
1251 |
|
|
1252 |
|
#define VAL_LEN 30 |
1253 |
|
|
1254 |
123 |
int Interp::convert_param_comment(char *comment, char *expanded, int len) |
1255 |
|
{ |
1256 |
|
int i; |
1257 |
|
char param[LINELEN+1]; |
1258 |
|
int paramNumber; |
1259 |
|
int stat; |
1260 |
|
double value; |
1261 |
|
char valbuf[VAL_LEN]; // max double length + room |
1262 |
|
char *v; |
1263 |
|
int found; |
1264 |
|
|
1265 |
2887 |
while(*comment) |
1266 |
|
{ |
1267 |
2641 |
if(*comment == '#') |
1268 |
|
{ |
1269 |
315 |
found = 0; |
1270 |
315 |
logDebug("a parameter"); |
1271 |
|
|
1272 |
|
// skip over the '#' |
1273 |
315 |
comment++; |
1274 |
315 |
CHKS((0 == *comment), NCE_NAMED_PARAMETER_NOT_TERMINATED); |
1275 |
|
|
1276 |
315 |
if(isdigit(*comment)) // is this numeric param? |
1277 |
|
{ |
1278 |
288 |
logDebug("numeric parameter"); |
1279 |
1150 |
for(i=0; isdigit(*comment)&& (i<LINELEN); i++) |
1280 |
|
{ |
1281 |
1150 |
param[i] = *comment++; |
1282 |
|
} |
1283 |
288 |
param[i] = 0; |
1284 |
288 |
paramNumber = atoi(param); |
1285 |
288 |
if((paramNumber >= 0) && |
1286 |
|
(paramNumber < RS274NGC_MAX_PARAMETERS)) |
1287 |
|
{ |
1288 |
288 |
value = _setup.parameters[paramNumber]; |
1289 |
288 |
found = 1; |
1290 |
|
} |
1291 |
|
} |
1292 |
27 |
else if(*comment == '<') |
1293 |
|
{ |
1294 |
27 |
logDebug("name parameter"); |
1295 |
|
// this is a name parameter |
1296 |
|
// skip over the '<' |
1297 |
27 |
comment++; |
1298 |
27 |
CHKS((0 == *comment), NCE_NAMED_PARAMETER_NOT_TERMINATED); |
1299 |
|
|
1300 |
188 |
for(i=0; (')' != *comment) && |
1301 |
188 |
(i<LINELEN) && (0 != *comment);) |
1302 |
|
{ |
1303 |
188 |
if('>' == *comment) |
1304 |
|
{ |
1305 |
|
break; // done |
1306 |
|
} |
1307 |
161 |
if(isspace(*comment)) // skip space inside the param |
1308 |
|
{ |
1309 |
|
comment++; |
1310 |
|
continue; |
1311 |
|
} |
1312 |
|
else |
1313 |
|
{ |
1314 |
|
// if tolower is a macro, may need this int |
1315 |
161 |
int c = *comment++; |
1316 |
161 |
if (FEATURE(NO_DOWNCASE_OWORD)) |
1317 |
35 |
param[i] = c; |
1318 |
|
else |
1319 |
126 |
param[i] = tolower(c); |
1320 |
161 |
i++; |
1321 |
|
} |
1322 |
|
} |
1323 |
27 |
if('>' != *comment) |
1324 |
|
{ |
1325 |
|
ERS(NCE_NAMED_PARAMETER_NOT_TERMINATED); |
1326 |
|
} |
1327 |
|
else |
1328 |
|
{ |
1329 |
27 |
comment++; |
1330 |
|
} |
1331 |
|
|
1332 |
|
// terminate the name |
1333 |
27 |
param[i] = 0; |
1334 |
|
|
1335 |
|
// now lookup the name |
1336 |
27 |
find_named_param(param, &stat, &value); |
1337 |
27 |
if(stat) |
1338 |
|
{ |
1339 |
26 |
found = 1; |
1340 |
|
} |
1341 |
|
} |
1342 |
|
else |
1343 |
|
{ |
1344 |
|
// neither numeric or name |
1345 |
|
logDebug("neither numeric nor name"); |
1346 |
|
// just store the '#' |
1347 |
|
*expanded++ = '#'; |
1348 |
|
|
1349 |
|
CHKS((*comment == 0), NCE_NAMED_PARAMETER_NOT_TERMINATED); |
1350 |
|
continue; |
1351 |
|
} |
1352 |
|
|
1353 |
|
// we have a parameter -- now insert it |
1354 |
|
// we have the value |
1355 |
315 |
if(found) |
1356 |
|
{ |
1357 |
|
// avoid -0.0/0.0 issues |
1358 |
628 |
double pvalue = equal(value, 0.0) ? 0.0 : value; |
1359 |
314 |
int n = snprintf(valbuf, VAL_LEN, "%lf", pvalue); |
1360 |
314 |
bool fail = (n >= VAL_LEN || n < 0); |
1361 |
314 |
if(fail) |
1362 |
|
strcpy(valbuf, "######"); |
1363 |
|
|
1364 |
|
} |
1365 |
|
else |
1366 |
|
{ |
1367 |
1 |
strcpy(valbuf, "######"); |
1368 |
|
} |
1369 |
315 |
logDebug("found:%d value:|%s|", found, valbuf); |
1370 |
|
|
1371 |
|
v = valbuf; |
1372 |
2963 |
while(*v) |
1373 |
|
{ |
1374 |
2648 |
*expanded++ = *v++; |
1375 |
|
} |
1376 |
|
} |
1377 |
|
else // not a '#' |
1378 |
|
{ |
1379 |
2326 |
*expanded++ = *comment++; |
1380 |
|
} |
1381 |
|
} |
1382 |
123 |
*expanded = 0; // the final nul |
1383 |
|
|
1384 |
123 |
return INTERP_OK; |
1385 |
|
} |
1386 |
|
|
1387 |
|
/****************************************************************************/ |
1388 |
|
|
1389 |
|
/*! convert_comment |
1390 |
|
|
1391 |
|
Returned Value: int (INTERP_OK) |
1392 |
|
|
1393 |
|
Side effects: |
1394 |
|
The message function is called if the string starts with "MSG,". |
1395 |
|
Otherwise, the comment function is called. |
1396 |
|
|
1397 |
|
Called by: execute_block |
1398 |
|
|
1399 |
|
To be a message, the first four characters of the comment after the |
1400 |
|
opening left parenthesis must be "MSG,", ignoring the case of the |
1401 |
|
letters and allowing spaces or tabs anywhere before the comma (to make |
1402 |
|
the treatment of case and white space consistent with how it is |
1403 |
|
handled elsewhere). |
1404 |
|
|
1405 |
|
Messages are not provided for in [NCMS]. They are implemented here as a |
1406 |
|
subtype of comment. This is an extension to the rs274NGC language. |
1407 |
|
|
1408 |
|
*/ |
1409 |
|
|
1410 |
1030 |
static int streq(char *s1, char *s2) { |
1411 |
1030 |
return !strcmp(s1, s2); |
1412 |
|
} |
1413 |
|
|
1414 |
10715 |
static int startswith(char *haystack, char *needle) { |
1415 |
10715 |
return !strncmp(haystack, needle, strlen(needle)); |
1416 |
|
} |
1417 |
|
|
1418 |
1175 |
int Interp::convert_comment(char *comment, bool enqueue) //!< string with comment |
1419 |
|
{ |
1420 |
|
enum |
1421 |
|
{ LC_SIZE = 256, EX_SIZE = 2*LC_SIZE}; // 256 from comment[256] in rs274ngc.hh |
1422 |
|
char lc[LC_SIZE+1]; |
1423 |
|
char expanded[EX_SIZE+1]; |
1424 |
1175 |
char MSG_STR[] = "msg,"; |
1425 |
|
|
1426 |
|
//!!!KL add two -- debug => same as msg |
1427 |
|
//!!!KL -- print => goes to stderr |
1428 |
1175 |
char DEBUG_STR[] = "debug,"; |
1429 |
1175 |
char PRINT_STR[] = "print,"; |
1430 |
1175 |
char LOG_STR[] = "log,"; |
1431 |
1175 |
char LOGOPEN_STR[] = "logopen,"; |
1432 |
1175 |
char LOGAPPEND_STR[] = "logappend,"; |
1433 |
1175 |
char LOGCLOSE_STR[] = "logclose"; |
1434 |
1175 |
char PY_STR[] = "py,"; |
1435 |
1175 |
char PYRUN_STR[] = "pyrun,"; |
1436 |
1175 |
char PYRELOAD_STR[] = "pyreload"; |
1437 |
1175 |
char ABORT_STR[] = "abort,"; |
1438 |
|
int m, n, start; |
1439 |
|
|
1440 |
|
// step over leading white space in comment |
1441 |
1175 |
m = 0; |
1442 |
2468 |
while (isspace(comment[m])) |
1443 |
118 |
m++; |
1444 |
|
start = m; |
1445 |
|
// copy lowercase comment to lc[] |
1446 |
32625 |
for (n = 0; n < LC_SIZE && comment[m] != 0; m++, n++) { |
1447 |
32625 |
lc[n] = tolower(comment[m]); |
1448 |
|
} |
1449 |
1175 |
lc[n] = 0; // null terminate |
1450 |
|
|
1451 |
|
// compare with MSG, SYSTEM, DEBUG, PRINT |
1452 |
1175 |
if (startswith(lc, MSG_STR)) { |
1453 |
3 |
MESSAGE(comment + start + strlen(MSG_STR)); |
1454 |
|
return INTERP_OK; |
1455 |
|
} |
1456 |
1172 |
else if (startswith(lc, DEBUG_STR)) |
1457 |
|
{ |
1458 |
97 |
convert_param_comment(comment+start+strlen(DEBUG_STR), expanded, |
1459 |
97 |
EX_SIZE); |
1460 |
97 |
if (_setup.parameters[5599] > 0.0) |
1461 |
97 |
MESSAGE(expanded); |
1462 |
|
return INTERP_OK; |
1463 |
|
} |
1464 |
1075 |
else if (startswith(lc, PRINT_STR)) |
1465 |
|
{ |
1466 |
25 |
convert_param_comment(comment+start+strlen(PRINT_STR), expanded, |
1467 |
25 |
EX_SIZE); |
1468 |
25 |
fprintf(stdout, "%s\n", expanded); |
1469 |
25 |
fflush(stdout); |
1470 |
|
return INTERP_OK; |
1471 |
|
} |
1472 |
1050 |
else if (startswith(lc, LOG_STR)) |
1473 |
|
{ |
1474 |
|
convert_param_comment(comment+start+strlen(LOG_STR), expanded, |
1475 |
|
EX_SIZE); |
1476 |
|
LOG(expanded); |
1477 |
|
return INTERP_OK; |
1478 |
|
} |
1479 |
1050 |
else if (startswith(lc, LOGOPEN_STR)) |
1480 |
|
{ |
1481 |
|
LOGOPEN(comment + start + strlen(LOGOPEN_STR)); |
1482 |
|
return INTERP_OK; |
1483 |
|
} |
1484 |
1050 |
else if (startswith(lc, LOGAPPEND_STR)) |
1485 |
|
{ |
1486 |
|
LOGAPPEND(comment + start + strlen(LOGAPPEND_STR)); |
1487 |
|
return INTERP_OK; |
1488 |
|
} |
1489 |
1050 |
else if (startswith(lc, PY_STR)) |
1490 |
|
{ |
1491 |
19 |
return py_execute(comment + start + strlen(PY_STR), false); |
1492 |
|
} |
1493 |
1031 |
else if (startswith(lc, PYRUN_STR)) |
1494 |
|
{ |
1495 |
|
return py_execute(comment + start + strlen(PYRUN_STR), true); |
1496 |
|
} |
1497 |
1031 |
else if (startswith(lc, PYRELOAD_STR)) |
1498 |
|
{ |
1499 |
|
return py_reload(); |
1500 |
|
} |
1501 |
1031 |
else if (startswith(lc, ABORT_STR)) |
1502 |
|
{ |
1503 |
1 |
convert_param_comment(comment+start+strlen(ABORT_STR), expanded, |
1504 |
1 |
EX_SIZE); |
1505 |
1 |
setSavedError(expanded); // avoid printf interpretation |
1506 |
|
return INTERP_ERROR; |
1507 |
|
} |
1508 |
1030 |
else if (streq(lc, LOGCLOSE_STR)) |
1509 |
|
{ |
1510 |
|
LOGCLOSE(); |
1511 |
|
return INTERP_OK; |
1512 |
|
} |
1513 |
|
// else it's a real comment |
1514 |
1030 |
if (enqueue) |
1515 |
886 |
enqueue_COMMENT(comment + start); |
1516 |
|
return INTERP_OK; |
1517 |
|
} |
1518 |
|
|
1519 |
|
/****************************************************************************/ |
1520 |
|
|
1521 |
|
/*! convert_control_mode |
1522 |
|
|
1523 |
|
Returned Value: int |
1524 |
|
If any of the following errors occur, this returns the error code shown. |
1525 |
|
Otherwise, it returns INTERP_OK. |
1526 |
|
1. g_code isn't G_61, G_61_1, G_64 : NCE_BUG_CODE_NOT_G61_G61_1_OR_G64 |
1527 |
|
|
1528 |
|
Side effects: See below |
1529 |
|
|
1530 |
|
Called by: convert_g. |
1531 |
|
|
1532 |
|
The interpreter switches the machine settings to indicate the |
1533 |
|
control mode (CANON_EXACT_STOP, CANON_EXACT_PATH or CANON_CONTINUOUS) |
1534 |
|
|
1535 |
|
A call is made to SET_MOTION_CONTROL_MODE(CANON_XXX), where CANON_XXX is |
1536 |
|
CANON_EXACT_PATH if g_code is G_61, CANON_EXACT_STOP if g_code is G_61_1, |
1537 |
|
and CANON_CONTINUOUS if g_code is G_64. |
1538 |
|
|
1539 |
|
Setting the control mode to CANON_EXACT_STOP on G_61 would correspond |
1540 |
|
more closely to the meaning of G_61 as given in [NCMS, page 40], but |
1541 |
|
CANON_EXACT_PATH has the advantage that the tool does not stop if it |
1542 |
|
does not have to, and no evident disadvantage compared to |
1543 |
|
CANON_EXACT_STOP, so it is being used for G_61. G_61_1 is not defined |
1544 |
|
in [NCMS], so it is available and is used here for setting the control |
1545 |
|
mode to CANON_EXACT_STOP. |
1546 |
|
|
1547 |
|
It is OK to call SET_MOTION_CONTROL_MODE(CANON_XXX) when CANON_XXX is |
1548 |
|
already in force. |
1549 |
|
|
1550 |
|
*/ |
1551 |
|
|
1552 |
7 |
int Interp::convert_control_mode(int g_code, //!< g_code being executed (G_61, G61_1, || G_64) |
1553 |
|
double tolerance, //tolerance for the path following in G64 |
1554 |
|
double naivecam_tolerance, //tolerance for the naivecam |
1555 |
|
setup_pointer settings) //!< pointer to machine settings |
1556 |
|
{ |
1557 |
7 |
CHKS((settings->cutter_comp_side), |
1558 |
|
(_("Cannot change control mode with cutter radius compensation on"))); |
1559 |
7 |
if (g_code == G_61) { |
1560 |
1 |
SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0); |
1561 |
1 |
settings->control_mode = CANON_EXACT_PATH; |
1562 |
6 |
} else if (g_code == G_61_1) { |
1563 |
1 |
SET_MOTION_CONTROL_MODE(CANON_EXACT_STOP, 0); |
1564 |
1 |
settings->control_mode = CANON_EXACT_STOP; |
1565 |
5 |
} else if (g_code == G_64) { |
1566 |
5 |
if (tolerance >= 0) { |
1567 |
2 |
SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, tolerance); |
1568 |
|
} else { |
1569 |
3 |
SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, 0); |
1570 |
|
} |
1571 |
5 |
if (naivecam_tolerance >= 0) { |
1572 |
1 |
SET_NAIVECAM_TOLERANCE(naivecam_tolerance); |
1573 |
4 |
} else if (tolerance >= 0) { |
1574 |
1 |
SET_NAIVECAM_TOLERANCE(tolerance); // if no naivecam_tolerance specified use same for both |
1575 |
|
} else { |
1576 |
3 |
SET_NAIVECAM_TOLERANCE(0); |
1577 |
|
} |
1578 |
5 |
settings->control_mode = CANON_CONTINUOUS; |
1579 |
|
} else |
1580 |
|
ERS(NCE_BUG_CODE_NOT_G61_G61_1_OR_G64); |
1581 |
|
return INTERP_OK; |
1582 |
|
} |
1583 |
|
|
1584 |
|
/****************************************************************************/ |
1585 |
|
|
1586 |
|
/*! convert_coordinate_system |
1587 |
|
|
1588 |
|
Returned Value: int |
1589 |
|
If any of the following errors occur, this returns the error code shown. |
1590 |
|
Otherwise, it returns INTERP_OK. |
1591 |
|
1. The value of the g_code argument is not 540, 550, 560, 570, 580, 590 |
1592 |
|
591, 592, or 593: |
1593 |
|
NCE_BUG_CODE_NOT_IN_RANGE_G54_TO_G593 |
1594 |
|
|
1595 |
|
Side effects: |
1596 |
|
If the coordinate system selected by the g_code is not already in |
1597 |
|
use, the canonical program coordinate system axis offset values are |
1598 |
|
reset and the coordinate values of the current point are reset. |
1599 |
|
|
1600 |
|
Called by: convert_g. |
1601 |
|
|
1602 |
|
COORDINATE SYSTEMS (involves g10, g53, g54 - g59.3, g92) |
1603 |
|
|
1604 |
|
The canonical machining functions view of coordinate systems is: |
1605 |
|
1. There are two coordinate systems: absolute and program. |
1606 |
|
2. All coordinate values are given in terms of the program coordinate system. |
1607 |
|
3. The offsets of the program coordinate system may be reset. |
1608 |
|
|
1609 |
|
The RS274/NGC view of coordinate systems, as given in section 3.2 |
1610 |
|
of [NCMS] is: |
1611 |
|
1. there are ten coordinate systems: absolute and 9 program. The |
1612 |
|
program coordinate systems are numbered 1 to 9. |
1613 |
|
2. you can switch among the 9 but not to the absolute one. G54 |
1614 |
|
selects coordinate system 1, G55 selects 2, and so on through |
1615 |
|
G56, G57, G58, G59, G59.1, G59.2, and G59.3. |
1616 |
|
3. you can set the offsets of the 9 program coordinate systems |
1617 |
|
using G10 L2 Pn (n is the number of the coordinate system) with |
1618 |
|
values for the axes in terms of the absolute coordinate system. |
1619 |
|
4. the first one of the 9 program coordinate systems is the default. |
1620 |
|
5. data for coordinate systems is stored in parameters [NCMS, pages 59 - 60]. |
1621 |
|
6. g53 means to interpret coordinate values in terms of the absolute |
1622 |
|
coordinate system for the one block in which g53 appears. |
1623 |
|
7. You can offset the current coordinate system using g92. This offset |
1624 |
|
will then apply to all nine program coordinate systems. |
1625 |
|
|
1626 |
|
The approach used in the interpreter mates the canonical and NGC views |
1627 |
|
of coordinate systems as follows: |
1628 |
|
|
1629 |
|
During initialization, data from the parameters for the first NGC |
1630 |
|
coordinate system is used in a SET_ORIGIN_OFFSETS function call and |
1631 |
|
origin_index in the machine model is set to 1. |
1632 |
|
|
1633 |
|
If a g_code in the range g54 - g59.3 is encountered in an NC program, |
1634 |
|
the data from the appropriate NGC coordinate system is copied into the |
1635 |
|
origin offsets used by the interpreter, a SET_ORIGIN_OFFSETS function |
1636 |
|
call is made, and the current position is reset. |
1637 |
|
|
1638 |
|
If a g10 is encountered, the convert_setup function is called to reset |
1639 |
|
the offsets of the program coordinate system indicated by the P number |
1640 |
|
given in the same block. |
1641 |
|
|
1642 |
|
If a g53 is encountered, the axis values given in that block are used |
1643 |
|
to calculate what the coordinates are of that point in the current |
1644 |
|
coordinate system, and a STRAIGHT_TRAVERSE or STRAIGHT_FEED function |
1645 |
|
call to that point using the calculated values is made. No offset |
1646 |
|
values are changed. |
1647 |
|
|
1648 |
|
If a g92 is encountered, that is handled by the convert_axis_offsets |
1649 |
|
function. A g92 results in an axis offset for each axis being calculated |
1650 |
|
and stored in the machine model. The axis offsets are applied to all |
1651 |
|
nine coordinate systems. Axis offsets are initialized to zero. |
1652 |
|
|
1653 |
|
*/ |
1654 |
|
|
1655 |
351 |
void Interp::rotate(double *x, double *y, double theta) { |
1656 |
|
double xx, yy; |
1657 |
351 |
double t = D2R(theta); |
1658 |
351 |
xx = *x * cos(t) - *y * sin(t); |
1659 |
351 |
yy = *x * sin(t) + *y * cos(t); |
1660 |
351 |
*x = xx; |
1661 |
351 |
*y = yy; |
1662 |
351 |
} |
1663 |
|
|
1664 |
36 |
int Interp::convert_coordinate_system(int g_code, //!< g_code called (must be one listed above) |
1665 |
|
setup_pointer settings) //!< pointer to machine settings |
1666 |
|
{ |
1667 |
|
int origin; |
1668 |
|
double *parameters; |
1669 |
|
|
1670 |
36 |
CHKS((settings->cutter_comp_side), |
1671 |
|
(_("Cannot change coordinate systems with cutter radius compensation on"))); |
1672 |
36 |
parameters = settings->parameters; |
1673 |
36 |
switch (g_code) { |
1674 |
|
case G_54: |
1675 |
|
origin = 1; |
1676 |
|
break; |
1677 |
|
case G_55: |
1678 |
5 |
origin = 2; |
1679 |
5 |
break; |
1680 |
|
case G_56: |
1681 |
4 |
origin = 3; |
1682 |
4 |
break; |
1683 |
|
case G_57: |
1684 |
3 |
origin = 4; |
1685 |
3 |
break; |
1686 |
|
case G_58: |
1687 |
3 |
origin = 5; |
1688 |
3 |
break; |
1689 |
|
case G_59: |
1690 |
3 |
origin = 6; |
1691 |
3 |
break; |
1692 |
|
case G_59_1: |
1693 |
3 |
origin = 7; |
1694 |
3 |
break; |
1695 |
|
case G_59_2: |
1696 |
3 |
origin = 8; |
1697 |
3 |
break; |
1698 |
|
case G_59_3: |
1699 |
3 |
origin = 9; |
1700 |
3 |
break; |
1701 |
|
default: |
1702 |
|
ERS(NCE_BUG_CODE_NOT_IN_RANGE_G54_TO_G593); |
1703 |
|
} |
1704 |
|
|
1705 |
36 |
if (origin == settings->origin_index) { /* already using this origin */ |
1706 |
|
#ifdef DEBUG_EMC |
1707 |
6 |
enqueue_COMMENT("interpreter: continuing to use same coordinate system"); |
1708 |
|
#endif |
1709 |
6 |
return INTERP_OK; |
1710 |
|
} |
1711 |
|
|
1712 |
|
// move the current point into the new system |
1713 |
|
find_current_in_system(settings, origin, |
1714 |
|
&settings->current_x, &settings->current_y, &settings->current_z, |
1715 |
|
&settings->AA_current, &settings->BB_current, &settings->CC_current, |
1716 |
30 |
&settings->u_current, &settings->v_current, &settings->w_current); |
1717 |
|
|
1718 |
|
// remember that this is new system |
1719 |
30 |
settings->origin_index = origin; |
1720 |
30 |
parameters[5220] = (double) origin; |
1721 |
|
|
1722 |
|
// load the origin of the newly-selected system |
1723 |
30 |
settings->origin_offset_x = USER_TO_PROGRAM_LEN(parameters[5201 + (origin * 20)]); |
1724 |
30 |
settings->origin_offset_y = USER_TO_PROGRAM_LEN(parameters[5202 + (origin * 20)]); |
1725 |
30 |
settings->origin_offset_z = USER_TO_PROGRAM_LEN(parameters[5203 + (origin * 20)]); |
1726 |
30 |
settings->AA_origin_offset = USER_TO_PROGRAM_ANG(parameters[5204 + (origin * 20)]); |
1727 |
30 |
settings->BB_origin_offset = USER_TO_PROGRAM_ANG(parameters[5205 + (origin * 20)]); |
1728 |
30 |
settings->CC_origin_offset = USER_TO_PROGRAM_ANG(parameters[5206 + (origin * 20)]); |
1729 |
30 |
settings->u_origin_offset = USER_TO_PROGRAM_LEN(parameters[5207 + (origin * 20)]); |
1730 |
30 |
settings->v_origin_offset = USER_TO_PROGRAM_LEN(parameters[5208 + (origin * 20)]); |
1731 |
30 |
settings->w_origin_offset = USER_TO_PROGRAM_LEN(parameters[5209 + (origin * 20)]); |
1732 |
30 |
settings->rotation_xy = parameters[5210 + (origin * 20)]; |
1733 |
|
|
1734 |
|
SET_G5X_OFFSET(origin, |
1735 |
|
settings->origin_offset_x, |
1736 |
|
settings->origin_offset_y, |
1737 |
|
settings->origin_offset_z, |
1738 |
|
settings->AA_origin_offset, |
1739 |
|
settings->BB_origin_offset, |
1740 |
|
settings->CC_origin_offset, |
1741 |
|
settings->u_origin_offset, |
1742 |
|
settings->v_origin_offset, |
1743 |
30 |
settings->w_origin_offset); |
1744 |
|
|
1745 |
|
SET_G92_OFFSET(settings->axis_offset_x, |
1746 |
|
settings->axis_offset_y, |
1747 |
|
settings->axis_offset_z, |
1748 |
|
settings->AA_axis_offset, |
1749 |
|
settings->BB_axis_offset, |
1750 |
|
settings->CC_axis_offset, |
1751 |
|
settings->u_axis_offset, |
1752 |
|
settings->v_axis_offset, |
1753 |
30 |
settings->w_axis_offset); |
1754 |
|
|
1755 |
30 |
SET_XY_ROTATION(settings->rotation_xy); |
1756 |
30 |
return INTERP_OK; |
1757 |
|
} |
1758 |
|
|
1759 |
|
/****************************************************************************/ |
1760 |
|
|
1761 |
|
/*! convert_cutter_compensation |
1762 |
|
|
1763 |
|
Returned Value: int |
1764 |
|
If convert_cutter_compensation_on or convert_cutter_compensation_off |
1765 |
|
is called and returns an error code, this returns that code. |
1766 |
|
If any of the following errors occur, this returns the error shown. |
1767 |
|
Otherwise, it returns INTERP_OK. |
1768 |
|
1. g_code is not G_40, G_41, or G_42: |
1769 |
|
NCE_BUG_CODE_NOT_G40_G41_OR_G42 |
1770 |
|
|
1771 |
|
Side effects: |
1772 |
|
The value of cutter_comp_side in the machine model mode is |
1773 |
|
set to RIGHT, LEFT, or false. The currently active tool table index in |
1774 |
|
the machine model (which is the index of the slot whose diameter |
1775 |
|
value is used in cutter radius compensation) is updated. |
1776 |
|
|
1777 |
|
Since cutter radius compensation is performed in the interpreter, no |
1778 |
|
call is made to any canonical function regarding cutter radius compensation. |
1779 |
|
|
1780 |
|
Called by: convert_g |
1781 |
|
|
1782 |
|
*/ |
1783 |
|
|
1784 |
149 |
int Interp::convert_cutter_compensation(int g_code, //!< must be G_40, G_41, or G_42 |
1785 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
1786 |
|
setup_pointer settings) //!< pointer to machine settings |
1787 |
|
{ |
1788 |
|
|
1789 |
149 |
if (g_code == G_40) { |
1790 |
87 |
CHP(convert_cutter_compensation_off(settings)); |
1791 |
62 |
} else if (g_code == G_41) { |
1792 |
|
CHP(convert_cutter_compensation_on(LEFT, block, settings)); |
1793 |
62 |
} else if (g_code == G_42) { |
1794 |
1 |
CHP(convert_cutter_compensation_on(RIGHT, block, settings)); |
1795 |
61 |
} else if (g_code == G_41_1) { |
1796 |
58 |
CHP(convert_cutter_compensation_on(LEFT, block, settings)); |
1797 |
3 |
} else if (g_code == G_42_1) { |
1798 |
3 |
CHP(convert_cutter_compensation_on(RIGHT, block, settings)); |
1799 |
|
} else |
1800 |
|
ERS("BUG: Code not G40, G41, G41.1, G42, G42.2"); |
1801 |
|
|
1802 |
|
return INTERP_OK; |
1803 |
|
} |
1804 |
|
|
1805 |
|
/****************************************************************************/ |
1806 |
|
|
1807 |
|
/*! convert_cutter_compensation_off |
1808 |
|
|
1809 |
|
Returned Value: int (INTERP_OK) |
1810 |
|
|
1811 |
|
Side effects: |
1812 |
|
A comment is made that cutter radius compensation is turned off. |
1813 |
|
The machine model of the cutter radius compensation mode is set to false. |
1814 |
|
The value of cutter_comp_firstmove in the machine model is set to true. |
1815 |
|
This serves as a flag when cutter radius compensation is |
1816 |
|
turned on again. |
1817 |
|
|
1818 |
|
Called by: convert_cutter_compensation |
1819 |
|
|
1820 |
|
*/ |
1821 |
|
|
1822 |
87 |
int Interp::convert_cutter_compensation_off(setup_pointer settings) //!< pointer to machine settings |
1823 |
|
{ |
1824 |
|
#ifdef DEBUG_EMC |
1825 |
87 |
enqueue_COMMENT("interpreter: cutter radius compensation off"); |
1826 |
|
#endif |
1827 |
87 |
if(settings->cutter_comp_side && settings->cutter_comp_radius > 0.0) { |
1828 |
|
double cx, cy, cz; |
1829 |
58 |
comp_get_current(settings, &cx, &cy, &cz); |
1830 |
58 |
CHP(move_endpoint_and_flush(settings, cx, cy)); |
1831 |
58 |
dequeue_canons(settings); |
1832 |
58 |
settings->current_x = settings->program_x; |
1833 |
58 |
settings->current_y = settings->program_y; |
1834 |
58 |
settings->current_z = settings->program_z; |
1835 |
58 |
settings->arc_not_allowed = true; |
1836 |
|
} |
1837 |
87 |
settings->cutter_comp_side = false; |
1838 |
87 |
settings->cutter_comp_firstmove = true; |
1839 |
87 |
return INTERP_OK; |
1840 |
|
} |
1841 |
|
|
1842 |
|
/****************************************************************************/ |
1843 |
|
|
1844 |
|
/*! convert_cutter_compensation_on |
1845 |
|
|
1846 |
|
Returned Value: int |
1847 |
|
If any of the following errors occur, this returns the error code shown. |
1848 |
|
Otherwise, it returns INTERP_OK. |
1849 |
|
1. The selected plane is not the XY plane: |
1850 |
|
NCE_CANNOT_TURN_CUTTER_RADIUS_COMP_ON_OUT_OF_XY_PLANE |
1851 |
|
2. Cutter radius compensation is already on: |
1852 |
|
NCE_CANNOT_TURN_CUTTER_RADIUS_COMP_ON_WHEN_ON |
1853 |
|
|
1854 |
|
Side effects: |
1855 |
|
A COMMENT function call is made (conditionally) saying that the |
1856 |
|
interpreter is switching mode so that cutter radius compensation is on. |
1857 |
|
The value of cutter_comp_radius in the machine model mode is |
1858 |
|
set to the absolute value of the radius given in the tool table. |
1859 |
|
The value of cutter_comp_side in the machine model mode is |
1860 |
|
set to RIGHT or LEFT. The currently active tool table index in |
1861 |
|
the machine model is updated. |
1862 |
|
|
1863 |
|
Called by: convert_cutter_compensation |
1864 |
|
|
1865 |
|
check_other_codes checks that a d word occurs only in a block with g41 |
1866 |
|
or g42. |
1867 |
|
|
1868 |
|
Cutter radius compensation is carried out in the interpreter, so no |
1869 |
|
call is made to a canonical function (although there is a canonical |
1870 |
|
function, START_CUTTER_RADIUS_COMPENSATION, that could be called if |
1871 |
|
the primitive level could execute it). |
1872 |
|
|
1873 |
|
This version uses a D word if there is one in the block, but it does |
1874 |
|
not require a D word, since the sample programs which the interpreter |
1875 |
|
is supposed to handle do not have them. Logically, the D word is |
1876 |
|
optional, since the D word is always (except in cases we have never |
1877 |
|
heard of) the slot number of the tool in the spindle. Not requiring a |
1878 |
|
D word is contrary to [Fanuc, page 116] and [NCMS, page 79], however. |
1879 |
|
Both manuals require the use of the D-word with G41 and G42. |
1880 |
|
|
1881 |
|
This version handles a negative offset radius, which may be |
1882 |
|
encountered if the programmed tool path is a center line path for |
1883 |
|
cutting a profile and the path was constructed using a nominal tool |
1884 |
|
diameter. Then the value in the tool table for the diameter is set to |
1885 |
|
be the difference between the actual diameter and the nominal |
1886 |
|
diameter. If the actual diameter is less than the nominal, the value |
1887 |
|
in the table is negative. The method of handling a negative radius is |
1888 |
|
to switch the side of the offset and use a positive radius. This |
1889 |
|
requires that the profile use arcs (not straight lines) to go around |
1890 |
|
convex corners. |
1891 |
|
|
1892 |
|
*/ |
1893 |
|
|
1894 |
|
/* Set *result to the integer nearest to value; return TRUE if value is |
1895 |
|
* within .0001 of an integer |
1896 |
|
*/ |
1897 |
27 |
static int is_near_int(int *result, double value) { |
1898 |
27 |
*result = (int)(value + .5); |
1899 |
27 |
return fabs(*result - value) < .0001; |
1900 |
|
} |
1901 |
|
|
1902 |
62 |
int Interp::convert_cutter_compensation_on(int side, //!< side of path cutter is on (LEFT or RIGHT) |
1903 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
1904 |
|
setup_pointer settings) //!< pointer to machine settings |
1905 |
|
{ |
1906 |
|
double radius; |
1907 |
|
int pocket_number, orientation; |
1908 |
|
|
1909 |
62 |
CHKS((settings->plane != CANON_PLANE_XY && settings->plane != CANON_PLANE_XZ), |
1910 |
|
NCE_RADIUS_COMP_ONLY_IN_XY_OR_XZ); |
1911 |
62 |
CHKS((settings->cutter_comp_side), |
1912 |
|
NCE_CANNOT_TURN_CUTTER_RADIUS_COMP_ON_WHEN_ON); |
1913 |
62 |
if(block->g_modes[7] == G_41_1 || block->g_modes[7] == G_42_1) { |
1914 |
61 |
CHKS((!block->d_flag), |
1915 |
|
_("G%d.1 with no D word"), block->g_modes[7]/10 ); |
1916 |
61 |
radius = block->d_number_float / 2; |
1917 |
61 |
if(block->l_number != -1) { |
1918 |
|
CHKS((settings->plane != CANON_PLANE_XZ), _("G%d.1 with L word, but plane is not G18"), block->g_modes[7]/10); |
1919 |
|
orientation = block->l_number; |
1920 |
|
} else { |
1921 |
|
orientation = 0; |
1922 |
|
} |
1923 |
|
} else { |
1924 |
1 |
if(!block->d_flag) { |
1925 |
|
pocket_number = 0; |
1926 |
|
} else { |
1927 |
|
int tool; |
1928 |
1 |
CHKS(!is_near_int(&tool, block->d_number_float), |
1929 |
|
_("G%d requires D word to be a whole number"), |
1930 |
|
block->g_modes[7]/10); |
1931 |
1 |
CHKS((tool < 0), NCE_NEGATIVE_D_WORD_TOOL_RADIUS_INDEX_USED); |
1932 |
1 |
CHP((find_tool_pocket(settings, tool, &pocket_number))); |
1933 |
|
} |
1934 |
1 |
radius = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].diameter) / 2.0; |
1935 |
1 |
orientation = settings->tool_table[pocket_number].orientation; |
1936 |
1 |
CHKS((settings->plane != CANON_PLANE_XZ && orientation != 0 && orientation != 9), _("G%d with lathe tool, but plane is not G18"), block->g_modes[7]/10); |
1937 |
|
} |
1938 |
62 |
if (radius < 0.0) { /* switch side & make radius positive if radius negative */ |
1939 |
28 |
radius = -radius; |
1940 |
28 |
if (side == RIGHT) |
1941 |
|
side = LEFT; |
1942 |
|
else |
1943 |
27 |
side = RIGHT; |
1944 |
|
} |
1945 |
|
#ifdef DEBUG_EMC |
1946 |
62 |
if (side == RIGHT) |
1947 |
30 |
enqueue_COMMENT("interpreter: cutter radius compensation on right"); |
1948 |
|
else |
1949 |
32 |
enqueue_COMMENT("interpreter: cutter radius compensation on left"); |
1950 |
|
#endif |
1951 |
|
|
1952 |
62 |
settings->cutter_comp_radius = radius; |
1953 |
62 |
settings->cutter_comp_orientation = orientation; |
1954 |
62 |
settings->cutter_comp_side = side; |
1955 |
62 |
return INTERP_OK; |
1956 |
|
} |
1957 |
|
|
1958 |
|
/****************************************************************************/ |
1959 |
|
|
1960 |
|
/*! convert_distance_mode |
1961 |
|
|
1962 |
|
Returned Value: int |
1963 |
|
If any of the following errors occur, this returns the error shown. |
1964 |
|
Otherwise, it returns INTERP_OK. |
1965 |
|
1. g_code isn't G_90 or G_91: NCE_BUG_CODE_NOT_G90_OR_G91 |
1966 |
|
|
1967 |
|
Side effects: |
1968 |
|
The interpreter switches the machine settings to indicate the current |
1969 |
|
distance mode (absolute or incremental). |
1970 |
|
|
1971 |
|
The canonical machine to which commands are being sent does not have |
1972 |
|
an incremental mode, so no command setting the distance mode is |
1973 |
|
generated in this function. A comment function call explaining the |
1974 |
|
change of mode is made (conditionally), however, if there is a change. |
1975 |
|
|
1976 |
|
Called by: convert_g. |
1977 |
|
|
1978 |
|
*/ |
1979 |
|
|
1980 |
|
// OK to call this in a concave corner with a deferred move, since it |
1981 |
|
// doesn't issue any CANONs |
1982 |
|
|
1983 |
176 |
int Interp::convert_distance_mode(int g_code, //!< g_code being executed (must be G_90 or G_91) |
1984 |
|
setup_pointer settings) //!< pointer to machine settings |
1985 |
|
{ |
1986 |
176 |
if (g_code == G_90) { |
1987 |
129 |
if (settings->distance_mode != MODE_ABSOLUTE) { |
1988 |
|
#ifdef DEBUG_EMC |
1989 |
40 |
enqueue_COMMENT("interpreter: distance mode changed to absolute"); |
1990 |
|
#endif |
1991 |
40 |
settings->distance_mode = MODE_ABSOLUTE; |
1992 |
|
} |
1993 |
47 |
} else if (g_code == G_91) { |
1994 |
47 |
if (settings->distance_mode != MODE_INCREMENTAL) { |
1995 |
|
#ifdef DEBUG_EMC |
1996 |
47 |
enqueue_COMMENT("interpreter: distance mode changed to incremental"); |
1997 |
|
#endif |
1998 |
47 |
settings->distance_mode = MODE_INCREMENTAL; |
1999 |
|
} |
2000 |
|
} else |
2001 |
|
ERS(NCE_BUG_CODE_NOT_G90_OR_G91); |
2002 |
|
return INTERP_OK; |
2003 |
|
} |
2004 |
|
|
2005 |
|
/****************************************************************************/ |
2006 |
|
|
2007 |
|
/*! convert_ijk_distance_mode |
2008 |
|
|
2009 |
|
Returned Value: int |
2010 |
|
If any of the following errors occur, this returns the error shown. |
2011 |
|
Otherwise, it returns INTERP_OK. |
2012 |
|
1. g_code isn't G_90.1 or G_91.1: NCE_BUG_CODE_NOT_G90_OR_G91 |
2013 |
|
|
2014 |
|
Side effects: |
2015 |
|
The interpreter switches the machine settings to indicate the current |
2016 |
|
distance mode for arc centers (absolute or incremental). |
2017 |
|
|
2018 |
|
The canonical machine to which commands are being sent does not have |
2019 |
|
an incremental mode, so no command setting the distance mode is |
2020 |
|
generated in this function. A comment function call explaining the |
2021 |
|
change of mode is made (conditionally), however, if there is a change. |
2022 |
|
|
2023 |
|
Called by: convert_g. |
2024 |
|
|
2025 |
|
*/ |
2026 |
|
|
2027 |
|
// OK to call this in a concave corner with a deferred move, since it |
2028 |
|
// doesn't issue any CANONs except comments (and who cares where the comments are) |
2029 |
|
|
2030 |
|
int Interp::convert_ijk_distance_mode(int g_code, //!< g_code being executed (must be G_90_1 or G_91_1) |
2031 |
|
setup_pointer settings) //!< pointer to machine settings |
2032 |
|
{ |
2033 |
|
if (g_code == G_90_1) { |
2034 |
|
if (settings->ijk_distance_mode != MODE_ABSOLUTE) { |
2035 |
|
#ifdef DEBUG_EMC |
2036 |
|
enqueue_COMMENT("interpreter: IJK distance mode changed to absolute"); |
2037 |
|
#endif |
2038 |
|
settings->ijk_distance_mode = MODE_ABSOLUTE; |
2039 |
|
} |
2040 |
|
} else if (g_code == G_91_1) { |
2041 |
|
if (settings->ijk_distance_mode != MODE_INCREMENTAL) { |
2042 |
|
#ifdef DEBUG_EMC |
2043 |
|
enqueue_COMMENT("interpreter: IJK distance mode changed to incremental"); |
2044 |
|
#endif |
2045 |
|
settings->ijk_distance_mode = MODE_INCREMENTAL; |
2046 |
|
} |
2047 |
|
} else |
2048 |
|
ERS(NCE_BUG_CODE_NOT_G90_OR_G91); |
2049 |
|
return INTERP_OK; |
2050 |
|
} |
2051 |
|
|
2052 |
|
/****************************************************************************/ |
2053 |
|
|
2054 |
|
/*! convert_lathe_diameter_mode |
2055 |
|
|
2056 |
|
Returned Value: int |
2057 |
|
If any of the following errors occur, this returns the error shown. |
2058 |
|
Otherwise, it returns INTERP_OK. |
2059 |
|
1. g_code isn't G_07 or G_08: NCE_BUG_CODE_NOT_G07_OR_G08 |
2060 |
|
|
2061 |
|
Side effects: |
2062 |
|
The interpreter switches the machine settings to indicate the current |
2063 |
|
distance mode for arc centers (absolute or incremental). |
2064 |
|
|
2065 |
|
The canonical machine to which commands are being sent does not have |
2066 |
|
an incremental mode, so no command setting the distance mode is |
2067 |
|
generated in this function. A comment function call explaining the |
2068 |
|
change of mode is made (conditionally), however, if there is a change. |
2069 |
|
|
2070 |
|
Called by: convert_g. |
2071 |
|
|
2072 |
|
*/ |
2073 |
|
|
2074 |
|
int Interp::convert_lathe_diameter_mode(int g_code, //!< g_code being executed (must be G_90_1 or G_91_1) |
2075 |
|
block_pointer block, //!< pointer to current block |
2076 |
|
setup_pointer settings) //!< pointer to machine settings |
2077 |
|
{ |
2078 |
|
if (g_code == G_7) { |
2079 |
|
if (!settings->lathe_diameter_mode) { |
2080 |
|
if(block->x_flag) |
2081 |
|
{ |
2082 |
|
block->x_number /= 2; //Apply scaling now |
2083 |
|
} |
2084 |
|
if(block->motion_to_be == G_76) { |
2085 |
|
block->i_number /= 2; |
2086 |
|
block->j_number /= 2; |
2087 |
|
block->k_number /= 2; |
2088 |
|
} |
2089 |
|
#ifdef DEBUG_EMC |
2090 |
|
COMMENT("interpreter: Lathe diameter mode changed to diameter"); |
2091 |
|
#endif |
2092 |
|
settings->lathe_diameter_mode = true; |
2093 |
|
} |
2094 |
|
} else if (g_code == G_8) { |
2095 |
|
if (settings->lathe_diameter_mode) { |
2096 |
|
if(block->x_flag) |
2097 |
|
{ |
2098 |
|
block->x_number *= 2; //Remove any existing scaling |
2099 |
|
} |
2100 |
|
if(block->motion_to_be == G_76) { |
2101 |
|
block->i_number *= 2; |
2102 |
|
block->j_number *= 2; |
2103 |
|
block->k_number *= 2; |
2104 |
|
} |
2105 |
|
#ifdef DEBUG_EMC |
2106 |
|
COMMENT("interpreter: Lathe diameter mode changed to radius"); |
2107 |
|
#endif |
2108 |
|
settings->lathe_diameter_mode = false; |
2109 |
|
} |
2110 |
|
} else |
2111 |
|
ERS("BUG: Code not G7 or G8"); |
2112 |
|
return INTERP_OK; |
2113 |
|
} |
2114 |
|
|
2115 |
|
|
2116 |
|
/****************************************************************************/ |
2117 |
|
|
2118 |
|
/*! convert_dwell |
2119 |
|
|
2120 |
|
Returned Value: int (INTERP_OK) |
2121 |
|
|
2122 |
|
Side effects: |
2123 |
|
A dwell command is executed. |
2124 |
|
|
2125 |
|
Called by: convert_g. |
2126 |
|
|
2127 |
|
*/ |
2128 |
|
|
2129 |
3 |
int Interp::convert_dwell(setup_pointer settings, double time) //!< time in seconds to dwell */ |
2130 |
|
{ |
2131 |
3 |
enqueue_DWELL(time); |
2132 |
3 |
return INTERP_OK; |
2133 |
|
} |
2134 |
|
|
2135 |
|
/****************************************************************************/ |
2136 |
|
|
2137 |
|
/*! convert_feed_mode |
2138 |
|
|
2139 |
|
Returned Value: int |
2140 |
|
If any of the following errors occur, this returns an error code. |
2141 |
|
Otherwise, it returns INTERP_OK. |
2142 |
|
1. g_code isn't G_93, G_94 or G_95 |
2143 |
|
|
2144 |
|
Side effects: |
2145 |
|
The interpreter switches the machine settings to indicate the current |
2146 |
|
feed mode (UNITS_PER_MINUTE or INVERSE_TIME). |
2147 |
|
|
2148 |
|
The canonical machine to which commands are being sent does not have |
2149 |
|
a feed mode, so no command setting the distance mode is generated in |
2150 |
|
this function. A comment function call is made (conditionally) |
2151 |
|
explaining the change in mode, however. |
2152 |
|
|
2153 |
|
Called by: execute_block. |
2154 |
|
|
2155 |
|
*/ |
2156 |
|
|
2157 |
13 |
int Interp::convert_feed_mode(int g_code, //!< g_code being executed (must be G_93, G_94 or G_95) |
2158 |
|
setup_pointer settings) //!< pointer to machine settings |
2159 |
|
{ |
2160 |
13 |
if (g_code == G_93) { |
2161 |
|
#ifdef DEBUG_EMC |
2162 |
6 |
enqueue_COMMENT("interpreter: feed mode set to inverse time"); |
2163 |
|
#endif |
2164 |
6 |
settings->feed_mode = INVERSE_TIME; |
2165 |
6 |
enqueue_SET_FEED_MODE(0); |
2166 |
7 |
} else if (g_code == G_94) { |
2167 |
|
#ifdef DEBUG_EMC |
2168 |
7 |
enqueue_COMMENT("interpreter: feed mode set to units per minute"); |
2169 |
|
#endif |
2170 |
7 |
settings->feed_mode = UNITS_PER_MINUTE; |
2171 |
7 |
enqueue_SET_FEED_MODE(0); |
2172 |
7 |
settings->feed_rate = 0.0; |
2173 |
7 |
enqueue_SET_FEED_RATE(0); |
2174 |
|
} else if(g_code == G_95) { |
2175 |
|
#ifdef DEBUG_EMC |
2176 |
|
enqueue_COMMENT("interpreter: feed mode set to units per revolution"); |
2177 |
|
#endif |
2178 |
|
settings->feed_mode = UNITS_PER_REVOLUTION; |
2179 |
|
enqueue_SET_FEED_MODE(1); |
2180 |
|
settings->feed_rate = 0.0; |
2181 |
|
enqueue_SET_FEED_RATE(0); |
2182 |
|
} else |
2183 |
|
ERS("BUG: Code not G93, G94, or G95"); |
2184 |
|
return INTERP_OK; |
2185 |
|
} |
2186 |
|
|
2187 |
|
/****************************************************************************/ |
2188 |
|
|
2189 |
|
/*! convert_feed_rate |
2190 |
|
|
2191 |
|
Returned Value: int (INTERP_OK) |
2192 |
|
|
2193 |
|
Side effects: |
2194 |
|
The machine feed_rate is set to the value of f_number in the |
2195 |
|
block by function call. |
2196 |
|
The machine model feed_rate is set to that value. |
2197 |
|
|
2198 |
|
Called by: execute_block |
2199 |
|
|
2200 |
|
This is called only if the feed mode is UNITS_PER_MINUTE or UNITS_PER_REVOLUTION. |
2201 |
|
|
2202 |
|
*/ |
2203 |
|
|
2204 |
569 |
int Interp::convert_feed_rate(block_pointer block, //!< pointer to a block of RS274 instructions |
2205 |
|
setup_pointer settings) //!< pointer to machine settings |
2206 |
|
{ |
2207 |
569 |
settings->feed_rate = block->f_number; |
2208 |
569 |
enqueue_SET_FEED_RATE(block->f_number); |
2209 |
569 |
return INTERP_OK; |
2210 |
|
} |
2211 |
|
|
2212 |
|
/****************************************************************************/ |
2213 |
|
|
2214 |
|
/*! convert_g |
2215 |
|
|
2216 |
|
Returned Value: int |
2217 |
|
If one of the following functions is called and returns an error code, |
2218 |
|
this returns that code. |
2219 |
|
convert_control_mode |
2220 |
|
convert_coordinate_system |
2221 |
|
convert_cutter_compensation |
2222 |
|
convert_distance_mode |
2223 |
|
convert_ijk_distance_mode |
2224 |
|
convert_lathe_diameter_mode |
2225 |
|
convert_dwell |
2226 |
|
convert_length_units |
2227 |
|
convert_modal_0 |
2228 |
|
convert_motion |
2229 |
|
convert_retract_mode |
2230 |
|
convert_set_plane |
2231 |
|
convert_tool_length_offset |
2232 |
|
Otherwise, it returns INTERP_OK. |
2233 |
|
|
2234 |
|
Side effects: |
2235 |
|
Any g_codes in the block (excluding g93 and 94) and any implicit |
2236 |
|
motion g_code are executed. |
2237 |
|
|
2238 |
|
Called by: execute_block. |
2239 |
|
|
2240 |
|
This takes a pointer to a block of RS274/NGC instructions (already |
2241 |
|
read in) and creates the appropriate output commands corresponding to |
2242 |
|
any "g" codes in the block. |
2243 |
|
|
2244 |
|
Codes g93 and g94, which set the feed mode, are executed earlier by |
2245 |
|
execute_block before reading the feed rate. |
2246 |
|
|
2247 |
|
G codes are are executed in the following order. |
2248 |
|
1. mode 0, G4 only - dwell. Left here from earlier versions. |
2249 |
|
2. mode 2, one of (G17, G18, G19) - plane selection. |
2250 |
|
3. mode 6, one of (G20, G21) - length units. |
2251 |
|
4. mode 15 one of (G07,G08) - lathe diameter mode |
2252 |
|
5. mode 7, one of (G40, G41, G42) - cutter radius compensation. |
2253 |
|
6. mode 8, one of (G43, G49) - tool length offset |
2254 |
|
7. mode 12, one of (G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3) |
2255 |
|
- coordinate system selection. |
2256 |
|
8. mode 13, one of (G61, G61.1, G64, G50, G51) - control mode |
2257 |
|
9. mode 3, one of (G90, G91) - distance mode. |
2258 |
|
10. mode 4, one of (G90.1, G91.1) - arc i,j,k mode. |
2259 |
|
11. mode 10, one of (G98, G99) - retract mode. |
2260 |
|
12. mode 0, one of (G10, G28, G30, G92, G92.1, G92.2, G92.3) - |
2261 |
|
13. mode 1, one of (G0, G1, G2, G3, G38.2, G80, G81 to G89, G33, G33.1, G76) - motion or cancel. |
2262 |
|
G53 from mode 0 is also handled here, if present. |
2263 |
|
|
2264 |
|
Some mode 0 and most mode 1 G codes must be executed after the length units |
2265 |
|
are set, since they use coordinate values. Mode 1 codes also must wait |
2266 |
|
until most of the other modes are set. |
2267 |
|
|
2268 |
|
*/ |
2269 |
|
|
2270 |
4509 |
int Interp::convert_g(block_pointer block, //!< pointer to a block of RS274/NGC instructions |
2271 |
|
setup_pointer settings) //!< pointer to machine settings |
2272 |
|
{ |
2273 |
|
int status; |
2274 |
|
|
2275 |
4521 |
if ((block->g_modes[GM_MODAL_0] == G_4) && ONCE(STEP_DWELL)) { |
2276 |
3 |
status = convert_dwell(settings, block->p_number); |
2277 |
3 |
CHP(status); |
2278 |
|
} |
2279 |
4553 |
if ((block->g_modes[GM_SET_PLANE] != -1) && ONCE(STEP_SET_PLANE)) { |
2280 |
11 |
status = convert_set_plane(block->g_modes[GM_SET_PLANE], settings); |
2281 |
11 |
CHP(status); |
2282 |
|
} |
2283 |
4725 |
if ((block->g_modes[GM_LENGTH_UNITS] != -1) && ONCE(STEP_LENGTH_UNITS)) { |
2284 |
54 |
status = convert_length_units(block->g_modes[GM_LENGTH_UNITS], settings); |
2285 |
54 |
CHP(status); |
2286 |
|
} |
2287 |
4509 |
if ((block->g_modes[GM_LATHE_DIAMETER_MODE] != -1) && ONCE(STEP_LATHE_DIAMETER_MODE)) { |
2288 |
|
status = convert_lathe_diameter_mode(block->g_modes[GM_LATHE_DIAMETER_MODE], block, settings); |
2289 |
|
CHP(status); |
2290 |
|
} |
2291 |
5105 |
if ((block->g_modes[GM_CUTTER_COMP] != -1) && ONCE(STEP_CUTTER_COMP)) { |
2292 |
149 |
status = convert_cutter_compensation(block->g_modes[GM_CUTTER_COMP], block, settings); |
2293 |
149 |
CHP(status); |
2294 |
|
} |
2295 |
4577 |
if ((block->g_modes[GM_TOOL_LENGTH_OFFSET] != -1) && ONCE(STEP_TOOL_LENGTH_OFFSET)){ |
2296 |
17 |
status = convert_tool_length_offset(block->g_modes[GM_TOOL_LENGTH_OFFSET], block, settings); |
2297 |
17 |
CHP(status); |
2298 |
|
} |
2299 |
4653 |
if ((block->g_modes[GM_COORD_SYSTEM] != -1) && ONCE(STEP_COORD_SYSTEM)){ |
2300 |
36 |
status = convert_coordinate_system(block->g_modes[GM_COORD_SYSTEM], settings); |
2301 |
36 |
CHP(status); |
2302 |
|
} |
2303 |
4537 |
if ((block->g_modes[GM_CONTROL_MODE] != -1) && ONCE(STEP_CONTROL_MODE)) { |
2304 |
|
status = convert_control_mode(block->g_modes[GM_CONTROL_MODE], |
2305 |
7 |
block->p_number, block->q_number, settings); |
2306 |
7 |
CHP(status); |
2307 |
|
} |
2308 |
5213 |
if ((block->g_modes[GM_DISTANCE_MODE] != -1) && ONCE(STEP_DISTANCE_MODE)) { |
2309 |
176 |
status = convert_distance_mode(block->g_modes[GM_DISTANCE_MODE], settings); |
2310 |
176 |
CHP(status); |
2311 |
|
} |
2312 |
4509 |
if ((block->g_modes[GM_IJK_DISTANCE_MODE] != -1) && ONCE(STEP_IJK_DISTANCE_MODE)){ |
2313 |
|
status = convert_ijk_distance_mode(block->g_modes[GM_IJK_DISTANCE_MODE], settings); |
2314 |
|
CHP(status); |
2315 |
|
} |
2316 |
4533 |
if ((block->g_modes[GM_RETRACT_MODE] != -1) && ONCE(STEP_RETRACT_MODE)){ |
2317 |
6 |
status = convert_retract_mode(block->g_modes[GM_RETRACT_MODE], settings); |
2318 |
6 |
CHP(status); |
2319 |
|
} |
2320 |
4837 |
if ((block->g_modes[GM_MODAL_0] != -1) && ONCE(STEP_MODAL_0)) { |
2321 |
82 |
status = convert_modal_0(block->g_modes[GM_MODAL_0], block, settings); |
2322 |
82 |
CHP(status); |
2323 |
|
} |
2324 |
10345 |
if ((block->motion_to_be != -1) && ONCE(STEP_MOTION)){ |
2325 |
1459 |
status = convert_motion(block->motion_to_be, block, settings); |
2326 |
1459 |
CHP(status); |
2327 |
|
} |
2328 |
|
return INTERP_OK; |
2329 |
|
} |
2330 |
|
|
2331 |
|
int Interp::convert_savehome(int code, block_pointer block, setup_pointer s) { |
2332 |
|
double *p = s->parameters; |
2333 |
|
|
2334 |
|
if(s->cutter_comp_side) { |
2335 |
|
ERS(_("Cannot set reference point with cutter compensation in effect")); |
2336 |
|
} |
2337 |
|
|
2338 |
|
double x = PROGRAM_TO_USER_LEN(s->current_x + s->tool_offset.tran.x + s->origin_offset_x + s->axis_offset_x); |
2339 |
|
double y = PROGRAM_TO_USER_LEN(s->current_y + s->tool_offset.tran.y + s->origin_offset_y + s->axis_offset_y); |
2340 |
|
double z = PROGRAM_TO_USER_LEN(s->current_z + s->tool_offset.tran.z + s->origin_offset_z + s->axis_offset_z); |
2341 |
|
double a = PROGRAM_TO_USER_ANG(s->AA_current + s->tool_offset.a + s->AA_origin_offset + s->AA_axis_offset); |
2342 |
|
double b = PROGRAM_TO_USER_ANG(s->BB_current + s->tool_offset.b + s->BB_origin_offset + s->BB_axis_offset); |
2343 |
|
double c = PROGRAM_TO_USER_ANG(s->CC_current + s->tool_offset.c + s->CC_origin_offset + s->CC_axis_offset); |
2344 |
|
double u = PROGRAM_TO_USER_LEN(s->u_current + s->tool_offset.u + s->u_origin_offset + s->u_axis_offset); |
2345 |
|
double v = PROGRAM_TO_USER_LEN(s->v_current + s->tool_offset.v + s->v_origin_offset + s->v_axis_offset); |
2346 |
|
double w = PROGRAM_TO_USER_LEN(s->w_current + s->tool_offset.w + s->w_origin_offset + s->w_axis_offset); |
2347 |
|
|
2348 |
|
if(s->a_axis_wrapped) { |
2349 |
|
a = fmod(a, 360.0); |
2350 |
|
if(a<0) a += 360.0; |
2351 |
|
} |
2352 |
|
|
2353 |
|
if(s->b_axis_wrapped) { |
2354 |
|
b = fmod(b, 360.0); |
2355 |
|
if(b<0) b += 360.0; |
2356 |
|
} |
2357 |
|
|
2358 |
|
if(s->c_axis_wrapped) { |
2359 |
|
c = fmod(c, 360.0); |
2360 |
|
if(c<0) c += 360.0; |
2361 |
|
} |
2362 |
|
|
2363 |
|
if(code == G_28_1) { |
2364 |
|
p[5161] = x; |
2365 |
|
p[5162] = y; |
2366 |
|
p[5163] = z; |
2367 |
|
p[5164] = a; |
2368 |
|
p[5165] = b; |
2369 |
|
p[5166] = c; |
2370 |
|
p[5167] = u; |
2371 |
|
p[5168] = v; |
2372 |
|
p[5169] = w; |
2373 |
|
} else if(code == G_30_1) { |
2374 |
|
p[5181] = x; |
2375 |
|
p[5182] = y; |
2376 |
|
p[5183] = z; |
2377 |
|
p[5184] = a; |
2378 |
|
p[5185] = b; |
2379 |
|
p[5186] = c; |
2380 |
|
p[5187] = u; |
2381 |
|
p[5188] = v; |
2382 |
|
p[5189] = w; |
2383 |
|
} else { |
2384 |
|
ERS("BUG: Code not G28.1 or G38.1"); |
2385 |
|
} |
2386 |
|
return INTERP_OK; |
2387 |
|
} |
2388 |
|
|
2389 |
|
|
2390 |
|
/****************************************************************************/ |
2391 |
|
|
2392 |
|
/*! convert_home |
2393 |
|
|
2394 |
|
Returned Value: int |
2395 |
|
If any of the following errors occur, this returns the error code shown. |
2396 |
|
Otherwise, it returns INTERP_OK. |
2397 |
|
1. cutter radius compensation is on: |
2398 |
|
NCE_CANNOT_USE_G28_OR_G30_WITH_CUTTER_RADIUS_COMP |
2399 |
|
2. The code is not G28 or G30: NCE_BUG_CODE_NOT_G28_OR_G30 |
2400 |
|
|
2401 |
|
Side effects: |
2402 |
|
This executes a straight traverse to the programmed point, using |
2403 |
|
the current coordinate system, tool length offset, and motion mode |
2404 |
|
to interpret the coordinate values. Then it executes a straight |
2405 |
|
traverse to move one or more axes to the location of reference |
2406 |
|
point 1 (if G28) or reference point 2 (if G30). If any axis words |
2407 |
|
are specified in this block, only those axes are moved to the |
2408 |
|
reference point. If none are specified, all axes are moved. It |
2409 |
|
also updates the setting of the position of the tool point to the |
2410 |
|
end point of the move. |
2411 |
|
|
2412 |
|
If either move would affect the position of one or more locking |
2413 |
|
rotaries, the rotaries are unlocked and indexed one at a time, |
2414 |
|
in the order A,B,C and then the other axes are moved. |
2415 |
|
|
2416 |
|
N.B. Many gcode programmers call the reference point a home |
2417 |
|
position, and that is exactly what it is if the parameters are |
2418 |
|
zero. Do not confuse this with homing the axis (searching for |
2419 |
|
a switch or index pulse). |
2420 |
|
|
2421 |
|
Called by: convert_modal_0. |
2422 |
|
|
2423 |
|
*/ |
2424 |
|
|
2425 |
|
int Interp::convert_home(int move, //!< G code, must be G_28 or G_30 |
2426 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
2427 |
|
setup_pointer settings) //!< pointer to machine settings |
2428 |
|
{ |
2429 |
|
double end_x; |
2430 |
|
double end_y; |
2431 |
|
double end_z; |
2432 |
|
double AA_end; |
2433 |
|
double BB_end; |
2434 |
|
double CC_end; |
2435 |
|
double u_end; |
2436 |
|
double v_end; |
2437 |
|
double w_end; |
2438 |
|
double end_x_home; |
2439 |
|
double end_y_home; |
2440 |
|
double end_z_home; |
2441 |
|
double AA_end_home; |
2442 |
|
double BB_end_home; |
2443 |
|
double CC_end_home; |
2444 |
|
double u_end_home; |
2445 |
|
double v_end_home; |
2446 |
|
double w_end_home; |
2447 |
|
double *parameters; |
2448 |
|
|
2449 |
|
parameters = settings->parameters; |
2450 |
|
CHP(find_ends(block, settings, &end_x, &end_y, &end_z, |
2451 |
|
&AA_end, &BB_end, &CC_end, |
2452 |
|
&u_end, &v_end, &w_end)); |
2453 |
|
|
2454 |
|
CHKS((settings->cutter_comp_side), |
2455 |
|
NCE_CANNOT_USE_G28_OR_G30_WITH_CUTTER_RADIUS_COMP); |
2456 |
|
|
2457 |
|
// waypoint is in currently active coordinate system |
2458 |
|
|
2459 |
|
// move indexers first, one at a time |
2460 |
|
// JOINTS_AXES settings->*_indexer_jnum == -1 means notused |
2461 |
|
if (AA_end != settings->AA_current && (-1 != settings->a_indexer_jnum) ) |
2462 |
|
issue_straight_index(3,settings->a_indexer_jnum, AA_end, block->line_number, settings); |
2463 |
|
if (BB_end != settings->BB_current && (-1 != settings->b_indexer_jnum) ) |
2464 |
|
issue_straight_index(4,settings->b_indexer_jnum, BB_end, block->line_number, settings); |
2465 |
|
if (CC_end != settings->CC_current && (-1 != settings->c_indexer_jnum) ) |
2466 |
|
issue_straight_index(5,settings->c_indexer_jnum, CC_end, block->line_number, settings); |
2467 |
|
|
2468 |
|
STRAIGHT_TRAVERSE(block->line_number, end_x, end_y, end_z, |
2469 |
|
AA_end, BB_end, CC_end, |
2470 |
|
u_end, v_end, w_end); |
2471 |
|
|
2472 |
|
settings->current_x = end_x; |
2473 |
|
settings->current_y = end_y; |
2474 |
|
settings->current_z = end_z; |
2475 |
|
settings->AA_current = AA_end; |
2476 |
|
settings->BB_current = BB_end; |
2477 |
|
settings->CC_current = CC_end; |
2478 |
|
settings->u_current = u_end; |
2479 |
|
settings->v_current = v_end; |
2480 |
|
settings->w_current = w_end; |
2481 |
|
|
2482 |
|
if (move == G_28) { |
2483 |
|
find_relative(USER_TO_PROGRAM_LEN(parameters[5161]), |
2484 |
|
USER_TO_PROGRAM_LEN(parameters[5162]), |
2485 |
|
USER_TO_PROGRAM_LEN(parameters[5163]), |
2486 |
|
USER_TO_PROGRAM_ANG(parameters[5164]), |
2487 |
|
USER_TO_PROGRAM_ANG(parameters[5165]), |
2488 |
|
USER_TO_PROGRAM_ANG(parameters[5166]), |
2489 |
|
USER_TO_PROGRAM_LEN(parameters[5167]), |
2490 |
|
USER_TO_PROGRAM_LEN(parameters[5168]), |
2491 |
|
USER_TO_PROGRAM_LEN(parameters[5169]), |
2492 |
|
&end_x_home, &end_y_home, &end_z_home, |
2493 |
|
&AA_end_home, &BB_end_home, &CC_end_home, |
2494 |
|
&u_end_home, &v_end_home, &w_end_home, settings); |
2495 |
|
} else if (move == G_30) { |
2496 |
|
find_relative(USER_TO_PROGRAM_LEN(parameters[5181]), |
2497 |
|
USER_TO_PROGRAM_LEN(parameters[5182]), |
2498 |
|
USER_TO_PROGRAM_LEN(parameters[5183]), |
2499 |
|
USER_TO_PROGRAM_ANG(parameters[5184]), |
2500 |
|
USER_TO_PROGRAM_ANG(parameters[5185]), |
2501 |
|
USER_TO_PROGRAM_ANG(parameters[5186]), |
2502 |
|
USER_TO_PROGRAM_LEN(parameters[5187]), |
2503 |
|
USER_TO_PROGRAM_LEN(parameters[5188]), |
2504 |
|
USER_TO_PROGRAM_LEN(parameters[5189]), |
2505 |
|
&end_x_home, &end_y_home, &end_z_home, |
2506 |
|
&AA_end_home, &BB_end_home, &CC_end_home, |
2507 |
|
&u_end_home, &v_end_home, &w_end_home, settings); |
2508 |
|
} else |
2509 |
|
ERS(NCE_BUG_CODE_NOT_G28_OR_G30); |
2510 |
|
|
2511 |
|
// if any axes are specified, home only those axes after the waypoint |
2512 |
|
// (both fanuc & haas, contrary to emc historical operation) |
2513 |
|
|
2514 |
|
if (block->x_flag) end_x = end_x_home; |
2515 |
|
if (block->y_flag) end_y = end_y_home; |
2516 |
|
if (block->z_flag) end_z = end_z_home; |
2517 |
|
if (block->a_flag) AA_end = AA_end_home; |
2518 |
|
if (block->b_flag) BB_end = BB_end_home; |
2519 |
|
if (block->c_flag) CC_end = CC_end_home; |
2520 |
|
if (block->u_flag) u_end = u_end_home; |
2521 |
|
if (block->v_flag) v_end = v_end_home; |
2522 |
|
if (block->w_flag) w_end = w_end_home; |
2523 |
|
|
2524 |
|
// but, if no axes are specified, home all of them |
2525 |
|
// (haas does this, emc historical did, throws an error in fanuc) |
2526 |
|
|
2527 |
|
if (!block->x_flag && !block->y_flag && !block->z_flag && |
2528 |
|
!block->a_flag && !block->b_flag && !block->c_flag && |
2529 |
|
!block->u_flag && !block->v_flag && !block->w_flag) { |
2530 |
|
end_x = end_x_home; |
2531 |
|
end_y = end_y_home; |
2532 |
|
end_z = end_z_home; |
2533 |
|
AA_end = AA_end_home; |
2534 |
|
BB_end = BB_end_home; |
2535 |
|
CC_end = CC_end_home; |
2536 |
|
u_end = u_end_home; |
2537 |
|
v_end = v_end_home; |
2538 |
|
w_end = w_end_home; |
2539 |
|
} |
2540 |
|
|
2541 |
|
// move indexers first, one at a time |
2542 |
|
// JOINTS_AXES settings->*_indexer_jnum == -1 means notused |
2543 |
|
if (AA_end != settings->AA_current && (-1 != settings->a_indexer_jnum) ) |
2544 |
|
issue_straight_index(3,settings->a_indexer_jnum, AA_end, block->line_number, settings); |
2545 |
|
if (BB_end != settings->BB_current && (-1 != settings->b_indexer_jnum) ) |
2546 |
|
issue_straight_index(4,settings->b_indexer_jnum, BB_end, block->line_number, settings); |
2547 |
|
if (CC_end != settings->CC_current && (-1 != settings->c_indexer_jnum) ) |
2548 |
|
issue_straight_index(5,settings->c_indexer_jnum, CC_end, block->line_number, settings); |
2549 |
|
|
2550 |
|
STRAIGHT_TRAVERSE(block->line_number, end_x, end_y, end_z, |
2551 |
|
AA_end, BB_end, CC_end, |
2552 |
|
u_end, v_end, w_end); |
2553 |
|
settings->current_x = end_x; |
2554 |
|
settings->current_y = end_y; |
2555 |
|
settings->current_z = end_z; |
2556 |
|
settings->AA_current = AA_end; |
2557 |
|
settings->BB_current = BB_end; |
2558 |
|
settings->CC_current = CC_end; |
2559 |
|
settings->u_current = u_end; |
2560 |
|
settings->v_current = v_end; |
2561 |
|
settings->w_current = w_end; |
2562 |
|
|
2563 |
|
return INTERP_OK; |
2564 |
|
} |
2565 |
|
|
2566 |
|
/****************************************************************************/ |
2567 |
|
|
2568 |
|
/*! convert_length_units |
2569 |
|
|
2570 |
|
Returned Value: int |
2571 |
|
If any of the following errors occur, this returns the error shown. |
2572 |
|
Otherwise, it returns INTERP_OK. |
2573 |
|
1. The g_code argument isnt G_20 or G_21: |
2574 |
|
NCE_BUG_CODE_NOT_G20_OR_G21 |
2575 |
|
2. Cutter radius compensation is on: |
2576 |
|
NCE_CANNOT_CHANGE_UNITS_WITH_CUTTER_RADIUS_COMP |
2577 |
|
|
2578 |
|
Side effects: |
2579 |
|
A command setting the length units is executed. The machine |
2580 |
|
settings are reset regarding length units and current position. |
2581 |
|
|
2582 |
|
Called by: convert_g. |
2583 |
|
|
2584 |
|
Tool length offset and diameter, work coordinate systems, feed rate, |
2585 |
|
g28/g30 home positions, and g53 motion in absolute coordinates all work |
2586 |
|
properly after switching units. Historically these had problems but the |
2587 |
|
intention is that they work properly now. |
2588 |
|
|
2589 |
|
The tool table in settings is not converted here; it is always in |
2590 |
|
inifile units and the conversion happens when reading an entry. Tool |
2591 |
|
offsets and feed rate that are in effect are converted by rereading them |
2592 |
|
from the canon level. |
2593 |
|
|
2594 |
|
Cutter diameter is not converted because radius comp is not in effect |
2595 |
|
when we are changing units. |
2596 |
|
|
2597 |
|
XXX Other distance items in the settings (such as the various parameters |
2598 |
|
for cycles) need testing. |
2599 |
|
|
2600 |
|
*/ |
2601 |
|
|
2602 |
54 |
int Interp::convert_length_units(int g_code, //!< g_code being executed (must be G_20 or G_21) |
2603 |
|
setup_pointer settings) //!< pointer to machine settings |
2604 |
|
{ |
2605 |
54 |
if (g_code == G_20) { |
2606 |
20 |
USE_LENGTH_UNITS(CANON_UNITS_INCHES); |
2607 |
20 |
if (settings->length_units != CANON_UNITS_INCHES) { |
2608 |
20 |
settings->length_units = CANON_UNITS_INCHES; |
2609 |
20 |
settings->current_x = (settings->current_x * INCH_PER_MM); |
2610 |
20 |
settings->current_y = (settings->current_y * INCH_PER_MM); |
2611 |
20 |
settings->current_z = (settings->current_z * INCH_PER_MM); |
2612 |
20 |
settings->program_x = (settings->program_x * INCH_PER_MM); |
2613 |
20 |
settings->program_y = (settings->program_y * INCH_PER_MM); |
2614 |
20 |
settings->program_z = (settings->program_z * INCH_PER_MM); |
2615 |
20 |
qc_scale(INCH_PER_MM); |
2616 |
20 |
settings->cutter_comp_radius *= INCH_PER_MM; |
2617 |
20 |
settings->axis_offset_x = (settings->axis_offset_x * INCH_PER_MM); |
2618 |
20 |
settings->axis_offset_y = (settings->axis_offset_y * INCH_PER_MM); |
2619 |
20 |
settings->axis_offset_z = (settings->axis_offset_z * INCH_PER_MM); |
2620 |
20 |
settings->origin_offset_x = (settings->origin_offset_x * INCH_PER_MM); |
2621 |
20 |
settings->origin_offset_y = (settings->origin_offset_y * INCH_PER_MM); |
2622 |
20 |
settings->origin_offset_z = (settings->origin_offset_z * INCH_PER_MM); |
2623 |
|
|
2624 |
20 |
settings->u_current = (settings->u_current * INCH_PER_MM); |
2625 |
20 |
settings->v_current = (settings->v_current * INCH_PER_MM); |
2626 |
20 |
settings->w_current = (settings->w_current * INCH_PER_MM); |
2627 |
20 |
settings->u_axis_offset = (settings->u_axis_offset * INCH_PER_MM); |
2628 |
20 |
settings->v_axis_offset = (settings->v_axis_offset * INCH_PER_MM); |
2629 |
20 |
settings->w_axis_offset = (settings->w_axis_offset * INCH_PER_MM); |
2630 |
20 |
settings->u_origin_offset = (settings->u_origin_offset * INCH_PER_MM); |
2631 |
20 |
settings->v_origin_offset = (settings->v_origin_offset * INCH_PER_MM); |
2632 |
20 |
settings->w_origin_offset = (settings->w_origin_offset * INCH_PER_MM); |
2633 |
|
|
2634 |
20 |
settings->tool_offset.tran.x = GET_EXTERNAL_TOOL_LENGTH_XOFFSET(); |
2635 |
20 |
settings->tool_offset.tran.y = GET_EXTERNAL_TOOL_LENGTH_YOFFSET(); |
2636 |
20 |
settings->tool_offset.tran.z = GET_EXTERNAL_TOOL_LENGTH_ZOFFSET(); |
2637 |
20 |
settings->tool_offset.a = GET_EXTERNAL_TOOL_LENGTH_AOFFSET(); |
2638 |
20 |
settings->tool_offset.b = GET_EXTERNAL_TOOL_LENGTH_BOFFSET(); |
2639 |
20 |
settings->tool_offset.c = GET_EXTERNAL_TOOL_LENGTH_COFFSET(); |
2640 |
20 |
settings->tool_offset.u = GET_EXTERNAL_TOOL_LENGTH_UOFFSET(); |
2641 |
20 |
settings->tool_offset.v = GET_EXTERNAL_TOOL_LENGTH_VOFFSET(); |
2642 |
20 |
settings->tool_offset.w = GET_EXTERNAL_TOOL_LENGTH_WOFFSET(); |
2643 |
20 |
settings->feed_rate = GET_EXTERNAL_FEED_RATE(); |
2644 |
|
} |
2645 |
34 |
} else if (g_code == G_21) { |
2646 |
34 |
USE_LENGTH_UNITS(CANON_UNITS_MM); |
2647 |
34 |
if (settings->length_units != CANON_UNITS_MM) { |
2648 |
|
settings->length_units = CANON_UNITS_MM; |
2649 |
|
settings->current_x = (settings->current_x * MM_PER_INCH); |
2650 |
|
settings->current_y = (settings->current_y * MM_PER_INCH); |
2651 |
|
settings->current_z = (settings->current_z * MM_PER_INCH); |
2652 |
|
settings->program_x = (settings->program_x * MM_PER_INCH); |
2653 |
|
settings->program_y = (settings->program_y * MM_PER_INCH); |
2654 |
|
settings->program_z = (settings->program_z * MM_PER_INCH); |
2655 |
|
qc_scale(MM_PER_INCH); |
2656 |
|
settings->cutter_comp_radius *= MM_PER_INCH; |
2657 |
|
settings->axis_offset_x = (settings->axis_offset_x * MM_PER_INCH); |
2658 |
|
settings->axis_offset_y = (settings->axis_offset_y * MM_PER_INCH); |
2659 |
|
settings->axis_offset_z = (settings->axis_offset_z * MM_PER_INCH); |
2660 |
|
settings->origin_offset_x = (settings->origin_offset_x * MM_PER_INCH); |
2661 |
|
settings->origin_offset_y = (settings->origin_offset_y * MM_PER_INCH); |
2662 |
|
settings->origin_offset_z = (settings->origin_offset_z * MM_PER_INCH); |
2663 |
|
|
2664 |
|
settings->u_current = (settings->u_current * MM_PER_INCH); |
2665 |
|
settings->v_current = (settings->v_current * MM_PER_INCH); |
2666 |
|
settings->w_current = (settings->w_current * MM_PER_INCH); |
2667 |
|
settings->u_axis_offset = (settings->u_axis_offset * MM_PER_INCH); |
2668 |
|
settings->v_axis_offset = (settings->v_axis_offset * MM_PER_INCH); |
2669 |
|
settings->w_axis_offset = (settings->w_axis_offset * MM_PER_INCH); |
2670 |
|
settings->u_origin_offset = (settings->u_origin_offset * MM_PER_INCH); |
2671 |
|
settings->v_origin_offset = (settings->v_origin_offset * MM_PER_INCH); |
2672 |
|
settings->w_origin_offset = (settings->w_origin_offset * MM_PER_INCH); |
2673 |
|
|
2674 |
|
settings->tool_offset.tran.x = GET_EXTERNAL_TOOL_LENGTH_XOFFSET(); |
2675 |
|
settings->tool_offset.tran.y = GET_EXTERNAL_TOOL_LENGTH_YOFFSET(); |
2676 |
|
settings->tool_offset.tran.z = GET_EXTERNAL_TOOL_LENGTH_ZOFFSET(); |
2677 |
|
settings->tool_offset.a = GET_EXTERNAL_TOOL_LENGTH_AOFFSET(); |
2678 |
|
settings->tool_offset.b = GET_EXTERNAL_TOOL_LENGTH_BOFFSET(); |
2679 |
|
settings->tool_offset.c = GET_EXTERNAL_TOOL_LENGTH_COFFSET(); |
2680 |
|
settings->tool_offset.u = GET_EXTERNAL_TOOL_LENGTH_UOFFSET(); |
2681 |
|
settings->tool_offset.v = GET_EXTERNAL_TOOL_LENGTH_VOFFSET(); |
2682 |
|
settings->tool_offset.w = GET_EXTERNAL_TOOL_LENGTH_WOFFSET(); |
2683 |
|
settings->feed_rate = GET_EXTERNAL_FEED_RATE(); |
2684 |
|
} |
2685 |
|
} else |
2686 |
|
ERS(NCE_BUG_CODE_NOT_G20_OR_G21); |
2687 |
|
return INTERP_OK; |
2688 |
|
} |
2689 |
|
|
2690 |
|
|
2691 |
|
/* |
2692 |
|
* given two double arrays representing interpreter settings as stored in |
2693 |
|
* _setup.active_settings, construct a G-code sequence to synchronize their state. |
2694 |
|
*/ |
2695 |
|
int Interp::gen_settings(double *current, double *saved, std::string &cmd) |
2696 |
|
{ |
2697 |
|
int i; |
2698 |
|
char buf[LINELEN]; |
2699 |
|
for (i = 0; i < ACTIVE_SETTINGS; i++) { |
2700 |
|
if (saved[i] != current[i]) { |
2701 |
|
switch (i) { |
2702 |
|
case 0: break; // sequence_number - no point in restoring |
2703 |
|
case 1: |
2704 |
|
snprintf(buf,sizeof(buf)," F%.1f", saved[i]); |
2705 |
|
cmd += buf; |
2706 |
|
break; |
2707 |
|
case 2: |
2708 |
|
snprintf(buf,sizeof(buf)," S%.0f", saved[i]); |
2709 |
|
cmd += buf; |
2710 |
|
break; |
2711 |
|
} |
2712 |
|
} |
2713 |
|
} |
2714 |
|
return INTERP_OK; |
2715 |
|
} |
2716 |
|
|
2717 |
|
|
2718 |
|
/* |
2719 |
|
* given two int arrays representing interpreter settings as stored in |
2720 |
|
* _setup.active_g_codes, construct a G-code sequence to synchronize their state. |
2721 |
|
*/ |
2722 |
|
int Interp::gen_g_codes(int *current, int *saved, std::string &cmd) |
2723 |
|
{ |
2724 |
|
int i, val; |
2725 |
|
char buf[LINELEN]; |
2726 |
|
for (i = 0; i < ACTIVE_G_CODES; i++) { |
2727 |
|
val = saved[i]; |
2728 |
|
if (val != current[i]) { |
2729 |
|
|
2730 |
|
switch (i) { |
2731 |
|
case 0: |
2732 |
|
// // sequence_number - no point in restoring |
2733 |
|
break; |
2734 |
|
case 2: // FIXME - I dont understand this: |
2735 |
|
// gez[2] = ((block == NULL) ? -1 : block->g_modes[0]); |
2736 |
|
break; |
2737 |
|
case 12: // mystery slot |
2738 |
|
break; |
2739 |
|
case 5: // - length units |
2740 |
|
// this is treated before all others - see convert_m() |
2741 |
|
break; |
2742 |
|
case 1: // - motion_mode |
2743 |
|
// restoring the motion mode is a real bad idea to start with |
2744 |
|
break; |
2745 |
|
case 3: // - plane |
2746 |
|
case 4: // - cutter compensation |
2747 |
|
case 6: // - distance mode |
2748 |
|
case 7: // - feed mode |
2749 |
|
case 8: // - coordinate system |
2750 |
|
case 9: // - tool offset (G43/G49) |
2751 |
|
case 10: // - retract mode |
2752 |
|
case 11: // - control mode |
2753 |
|
case 13: // - spindle mode |
2754 |
|
case 14: // - ijk distance mode |
2755 |
|
case 15: // - lathe diameter mode |
2756 |
|
|
2757 |
|
if (val != -1) { // FIXME not sure if this is correct! |
2758 |
|
// if this was set in sub, and unset in caller, it will |
2759 |
|
// not be reset |
2760 |
|
if (val % 10) { |
2761 |
|
snprintf(buf,sizeof(buf)," G%d.%d", val / 10, val % 10); |
2762 |
|
} else { |
2763 |
|
snprintf(buf,sizeof(buf)," G%d", val / 10); |
2764 |
|
} |
2765 |
|
cmd += buf; |
2766 |
|
} else { |
2767 |
|
// so complain rather loudly |
2768 |
|
MSG("------ gen_g_codes BUG: index %d = -1!!\n",i); |
2769 |
|
} |
2770 |
|
break; |
2771 |
|
} |
2772 |
|
} |
2773 |
|
} |
2774 |
|
return INTERP_OK; |
2775 |
|
} |
2776 |
|
|
2777 |
|
/* |
2778 |
|
* given two int arrays representing interpreter settings as stored in |
2779 |
|
* _setup.active_m_codes, construct a M-code sequence to synchronize their state. |
2780 |
|
* |
2781 |
|
* use multiple lines here because M7 and M8 may not be on the same line since |
2782 |
|
* they are in the same modal group. |
2783 |
|
*/ |
2784 |
|
int Interp::gen_m_codes(int *current, int *saved, std::string &cmd) |
2785 |
|
{ |
2786 |
|
int i,val; |
2787 |
|
char buf[LINELEN]; |
2788 |
|
for (i = 0; i < ACTIVE_M_CODES; i++) { |
2789 |
|
val = saved[i]; |
2790 |
|
if (val != current[i]) { |
2791 |
|
switch (i) { |
2792 |
|
case 0: /* 0 seq number */ |
2793 |
|
break; |
2794 |
|
case 1: /* 1 stopping */ |
2795 |
|
// FIXME - is the next line needed at all? |
2796 |
|
// emz[1] = (block == NULL) ? -1 : block->m_modes[4]; |
2797 |
|
break; |
2798 |
|
case 3: /* 3 tool change */ |
2799 |
|
// FIXME - dont know how to handle this. |
2800 |
|
// emz[3] = |
2801 |
|
// (block == NULL) ? -1 : block->m_modes[6]; |
2802 |
|
break; |
2803 |
|
case 2: // spindle |
2804 |
|
case 4: // mist |
2805 |
|
case 5: // flood |
2806 |
|
case 6: // speed/feed override |
2807 |
|
case 7: // adaptive feed |
2808 |
|
case 8: // feed hold |
2809 |
|
if (val != -1) { // unsure.. |
2810 |
|
snprintf(buf,sizeof(buf),"M%d\n", val); |
2811 |
|
cmd += buf; |
2812 |
|
} else { |
2813 |
|
MSG("------ gen_m_codes: index %d = -1!!\n",i); |
2814 |
|
} |
2815 |
|
break; |
2816 |
|
} |
2817 |
|
} |
2818 |
|
} |
2819 |
|
return INTERP_OK; |
2820 |
|
} |
2821 |
|
|
2822 |
|
int Interp::save_settings(setup_pointer settings) |
2823 |
|
{ |
2824 |
|
// the state is sprinkled all over _setup |
2825 |
|
// collate state in _setup.active_* arrays |
2826 |
|
write_g_codes((block_pointer) NULL, settings); |
2827 |
|
write_m_codes((block_pointer) NULL, settings); |
2828 |
|
write_settings(settings); |
2829 |
|
|
2830 |
|
// save in the current call frame |
2831 |
|
active_g_codes((int *)settings->sub_context[settings->call_level].saved_g_codes); |
2832 |
|
active_m_codes((int *)settings->sub_context[settings->call_level].saved_m_codes); |
2833 |
|
active_settings((double *)settings->sub_context[settings->call_level].saved_settings); |
2834 |
|
|
2835 |
|
// TBD: any other state deemed important to save/restore should be added here |
2836 |
|
// context_struct might need to be extended too. |
2837 |
|
|
2838 |
|
return INTERP_OK; |
2839 |
|
} |
2840 |
|
|
2841 |
|
/* restore global settings/gcodes/mcodes to current call level from a valid context |
2842 |
|
* used by: |
2843 |
|
* M72 - restores context from same level |
2844 |
|
* example: restore_settings(settings->call_level) |
2845 |
|
* |
2846 |
|
* an o-word return/endsub if auto-restore (M73) was issued |
2847 |
|
* issue this like so - after call_level has been decremented: |
2848 |
|
* restore_settings(settings->call_level + 1) |
2849 |
|
*/ |
2850 |
|
int Interp::restore_settings(setup_pointer settings, |
2851 |
|
int from_level) //!< call level of context to restore from |
2852 |
|
{ |
2853 |
|
|
2854 |
|
CHKS((from_level < settings->call_level), |
2855 |
|
(_("BUG: cannot restore from a lower call level (%d) to a higher call level (%d)")),from_level,settings->call_level); |
2856 |
|
CHKS((from_level < 0), (_("BUG: restore from level %d !?")),from_level); |
2857 |
|
CHKS((settings->call_level < 0), (_("BUG: restore to level %d !?")),settings->call_level); |
2858 |
|
|
2859 |
|
// linearize state |
2860 |
|
write_g_codes((block_pointer) NULL, settings); |
2861 |
|
write_m_codes((block_pointer) NULL, settings); |
2862 |
|
write_settings(settings); |
2863 |
|
|
2864 |
|
std::string cmd; |
2865 |
|
|
2866 |
|
// construct gcode from the state difference and execute |
2867 |
|
// this assures appropriate canon commands are generated if needed - |
2868 |
|
// just restoring interp variables is not enough |
2869 |
|
|
2870 |
|
// G20/G21 switching is special - it is executed beforehand |
2871 |
|
// so restoring feed lateron is interpreted in the correct context |
2872 |
|
|
2873 |
|
if (settings->active_g_codes[5] != settings->sub_context[from_level].saved_g_codes[5]) { |
2874 |
|
char buf[LINELEN]; |
2875 |
|
snprintf(buf,sizeof(buf), "G%d",settings->sub_context[from_level].saved_g_codes[5]/10); |
2876 |
|
CHKS(execute(buf) != INTERP_OK, _("M7x: restore_settings G20/G21 failed: '%s'"), cmd.c_str()); |
2877 |
|
} |
2878 |
|
gen_settings((double *)settings->active_settings, (double *)settings->sub_context[from_level].saved_settings,cmd); |
2879 |
|
gen_m_codes((int *) settings->active_m_codes, (int *)settings->sub_context[from_level].saved_m_codes,cmd); |
2880 |
|
gen_g_codes((int *)settings->active_g_codes, (int *)settings->sub_context[from_level].saved_g_codes,cmd); |
2881 |
|
|
2882 |
|
if (!cmd.empty()) { |
2883 |
|
// the sequence can be multiline, separated by nl |
2884 |
|
// so split and execute each line |
2885 |
|
char buf[cmd.size() + 1]; |
2886 |
|
strncpy(buf, cmd.c_str(), sizeof(buf)); |
2887 |
|
char *last = buf; |
2888 |
|
char *s; |
2889 |
|
while ((s = strtok_r(last, "\n", &last)) != NULL) { |
2890 |
|
int status = execute(s); |
2891 |
|
if (status != INTERP_OK) { |
2892 |
|
char currentError[LINELEN+1]; |
2893 |
|
strcpy(currentError,getSavedError()); |
2894 |
|
CHKS(status, _("M7x: restore_settings failed executing: '%s': %s"), s, currentError); |
2895 |
|
} |
2896 |
|
} |
2897 |
|
write_g_codes((block_pointer) NULL, settings); |
2898 |
|
write_m_codes((block_pointer) NULL, settings); |
2899 |
|
write_settings(settings); |
2900 |
|
} |
2901 |
|
|
2902 |
|
// TBD: any state deemed important to restore should be restored here |
2903 |
|
// NB: some state changes might generate canon commands so do that here |
2904 |
|
// if needed |
2905 |
|
|
2906 |
|
return INTERP_OK; |
2907 |
|
} |
2908 |
|
|
2909 |
|
|
2910 |
|
|
2911 |
|
/****************************************************************************/ |
2912 |
|
|
2913 |
|
/*! convert_m |
2914 |
|
|
2915 |
|
Returned Value: int |
2916 |
|
If convert_tool_change returns an error code, this returns that code. |
2917 |
|
If input-related stuff is needed, it sets the flag input_flag = true. |
2918 |
|
Otherwise, it returns INTERP_OK. |
2919 |
|
|
2920 |
|
Side effects: |
2921 |
|
m_codes in the block are executed. For each m_code |
2922 |
|
this consists of making a function call(s) to a canonical machining |
2923 |
|
function(s) and setting the machine model. |
2924 |
|
|
2925 |
|
Called by: execute_block. |
2926 |
|
|
2927 |
|
This handles four separate types of activity in order: |
2928 |
|
1. changing the tool (m6) - which also retracts and stops the spindle. |
2929 |
|
2. Turning the spindle on or off (m3, m4, and m5) |
2930 |
|
3. Turning coolant on and off (m7, m8, and m9) |
2931 |
|
4. turning a-axis clamping on and off (m26, m27) - commented out. |
2932 |
|
5. enabling or disabling feed and speed overrides (m49, m49). |
2933 |
|
6. changing the loaded toolnumber (m61). |
2934 |
|
Within each group, only the first code encountered will be executed. |
2935 |
|
|
2936 |
|
This does nothing with m0, m1, m2, m30, or m60 (which are handled in |
2937 |
|
convert_stop). |
2938 |
|
|
2939 |
|
*/ |
2940 |
|
|
2941 |
4509 |
int Interp::convert_m(block_pointer block, //!< pointer to a block of RS274/NGC instructions |
2942 |
|
setup_pointer settings) //!< pointer to machine settings |
2943 |
|
{ |
2944 |
|
int type; |
2945 |
|
double timeout; // timeout for M66 |
2946 |
|
|
2947 |
|
/* The M62-65 commands are used for DIO */ |
2948 |
|
/* M62 sets a DIO synched with motion |
2949 |
|
M63 clears a DIO synched with motion |
2950 |
|
M64 sets a DIO imediately |
2951 |
|
M65 clears a DIO imediately |
2952 |
|
M66 waits for an input |
2953 |
|
M67 reads a digital input |
2954 |
|
M68 reads an analog input*/ |
2955 |
|
|
2956 |
4509 |
if (IS_USER_MCODE(block,settings,5) && ONCE_M(5)) { |
2957 |
|
return convert_remapped_code(block, settings, STEP_M_5, 'm', |
2958 |
|
block->m_modes[5]); |
2959 |
4509 |
} else if ((block->m_modes[5] == 62) && ONCE_M(5)) { |
2960 |
|
CHKS((settings->cutter_comp_side), |
2961 |
|
(_("Cannot set motion output with cutter radius compensation on"))); // XXX |
2962 |
|
CHKS((!block->p_flag), _("No valid P word with M62")); |
2963 |
|
SET_MOTION_OUTPUT_BIT(round_to_int(block->p_number)); |
2964 |
4509 |
} else if ((block->m_modes[5] == 63) && ONCE_M(5)) { |
2965 |
|
CHKS((settings->cutter_comp_side), |
2966 |
|
(_("Cannot set motion digital output with cutter radius compensation on"))); // XXX |
2967 |
|
CHKS((!block->p_flag), _("No valid P word with M63")); |
2968 |
|
CLEAR_MOTION_OUTPUT_BIT(round_to_int(block->p_number)); |
2969 |
4509 |
} else if ((block->m_modes[5] == 64) && ONCE_M(5)){ |
2970 |
|
CHKS((settings->cutter_comp_side), |
2971 |
|
(_("Cannot set auxiliary digital output with cutter radius compensation on"))); // XXX |
2972 |
|
CHKS((!block->p_flag), _("No valid P word with M64")); |
2973 |
|
SET_AUX_OUTPUT_BIT(round_to_int(block->p_number)); |
2974 |
4509 |
} else if ((block->m_modes[5] == 65) && ONCE_M(5)) { |
2975 |
|
CHKS((settings->cutter_comp_side), |
2976 |
|
(_("Cannot set auxiliary digital output with cutter radius compensation on"))); // XXX |
2977 |
|
CHKS((!block->p_flag), _("No valid P word with M65")); |
2978 |
|
CLEAR_AUX_OUTPUT_BIT(round_to_int(block->p_number)); |
2979 |
4513 |
} else if ((block->m_modes[5] == 66) && ONCE_M(5)){ |
2980 |
|
|
2981 |
|
//P-word = digital channel |
2982 |
|
//E-word = analog channel |
2983 |
|
//L-word = wait type (immediate, rise, fall, high, low) |
2984 |
|
//Q-word = timeout |
2985 |
|
// it is an error if: |
2986 |
|
|
2987 |
|
// P and E word are specified together |
2988 |
1 |
CHKS(((block->p_flag) && (block->e_flag)), |
2989 |
|
NCE_BOTH_DIGITAL_AND_ANALOG_INPUT_SELECTED); |
2990 |
|
|
2991 |
|
// L-word not 0, and timeout <= 0 |
2992 |
1 |
CHKS(((block->q_number <= 0) && (block->l_flag) && (round_to_int(block->l_number) > 0)), |
2993 |
|
NCE_ZERO_TIMEOUT_WITH_WAIT_NOT_IMMEDIATE); |
2994 |
|
|
2995 |
|
// E-word specified (analog input) and wait type not immediate |
2996 |
1 |
CHKS(((block->e_flag) && (block->l_flag) && (round_to_int(block->l_number) != 0)), |
2997 |
|
NCE_ANALOG_INPUT_WITH_WAIT_NOT_IMMEDIATE); |
2998 |
|
|
2999 |
|
// missing P or E (or invalid = negative) |
3000 |
1 |
CHKS( ((block->p_flag) && (round_to_int(block->p_number) < 0)) || |
3001 |
|
((block->e_flag) && (round_to_int(block->e_number) < 0)) || |
3002 |
|
((!block->p_flag) && (!block->e_flag)) , |
3003 |
|
NCE_INVALID_OR_MISSING_P_AND_E_WORDS_FOR_WAIT_INPUT); |
3004 |
|
|
3005 |
1 |
if (block->p_flag) { // got a digital input |
3006 |
1 |
if (round_to_int(block->p_number) < 0) // safety check for negative words |
3007 |
|
ERS(_("invalid P-word with M66")); |
3008 |
|
|
3009 |
1 |
if (block->l_flag) { |
3010 |
1 |
type = round_to_int(block->l_number); |
3011 |
|
} else { |
3012 |
|
type = WAIT_MODE_IMMEDIATE; |
3013 |
|
} |
3014 |
|
|
3015 |
1 |
if (block->q_number > 0) { |
3016 |
|
timeout = block->q_number; |
3017 |
|
} else { |
3018 |
|
timeout = 0; |
3019 |
|
} |
3020 |
|
|
3021 |
1 |
CHKS((settings->cutter_comp_side), |
3022 |
|
(_("Cannot wait for digital input with cutter radius compensation on"))); |
3023 |
|
|
3024 |
1 |
int ret = WAIT(round_to_int(block->p_number), DIGITAL_INPUT, type, timeout); |
3025 |
|
//WAIT returns 0 on success, -1 for out of bounds |
3026 |
1 |
CHKS((ret == -1), NCE_DIGITAL_INPUT_INVALID_ON_M66); |
3027 |
1 |
if (ret == 0) { |
3028 |
1 |
settings->input_flag = true; |
3029 |
1 |
settings->input_index = round_to_int(block->p_number); |
3030 |
1 |
settings->input_digital = true; |
3031 |
|
} |
3032 |
|
} else if (round_to_int(block->e_number) >= 0) { // got an analog input |
3033 |
|
CHKS((settings->cutter_comp_side), |
3034 |
|
(_("Cannot wait for analog input with cutter radius compensation on"))); |
3035 |
|
|
3036 |
|
int ret = WAIT(round_to_int(block->e_number), ANALOG_INPUT, 0, 0); //WAIT returns 0 on success, -1 for out of bounds |
3037 |
|
CHKS((ret == -1), NCE_ANALOG_INPUT_INVALID_ON_M66); |
3038 |
|
if (ret == 0) { |
3039 |
|
settings->input_flag = true; |
3040 |
|
settings->input_index = round_to_int(block->e_number); |
3041 |
|
settings->input_digital = false; |
3042 |
|
} |
3043 |
|
} |
3044 |
4508 |
} else if ((block->m_modes[5] == 67) && ONCE_M(5)) { |
3045 |
|
|
3046 |
|
//E-word = analog channel |
3047 |
|
//Q-word = analog value |
3048 |
|
CHKS((settings->cutter_comp_side), |
3049 |
|
(_("Cannot set motion analog output with cutter radius compensation on"))); // XXX |
3050 |
|
CHKS((!block->e_flag) || (round_to_int(block->e_number) < 0), (_("Invalid analog index with M67"))); |
3051 |
|
SET_MOTION_OUTPUT_VALUE(round_to_int(block->e_number), block->q_number); |
3052 |
4508 |
} else if ((block->m_modes[5] == 68) && ONCE_M(5)) { |
3053 |
|
//E-word = analog channel |
3054 |
|
//Q-word = analog value |
3055 |
|
CHKS((settings->cutter_comp_side), |
3056 |
|
(_("Cannot set auxiliary analog output with cutter radius compensation on"))); // XXX |
3057 |
|
CHKS((!block->e_flag) || (round_to_int(block->e_number) < 0), (_("Invalid analog index with M68"))); |
3058 |
|
SET_AUX_OUTPUT_VALUE(round_to_int(block->e_number), block->q_number); |
3059 |
|
} |
3060 |
|
|
3061 |
4545 |
if ((block->m_modes[6] != -1) && ONCE_M(6)){ |
3062 |
|
int toolno; |
3063 |
27 |
bool remapped_in_block = STEP_REMAPPED_IN_BLOCK(block, STEP_M_6); |
3064 |
|
|
3065 |
9 |
switch (block->m_modes[6]) { |
3066 |
|
case 6: |
3067 |
9 |
if (IS_USER_MCODE(block,settings,6) && remapped_in_block) { |
3068 |
|
return convert_remapped_code(block,settings, |
3069 |
|
STEP_M_6, |
3070 |
|
'm', |
3071 |
|
block->m_modes[6]); |
3072 |
|
} else { |
3073 |
|
// the code was used in its very remap procedure - |
3074 |
|
// the 'recursion case'; record the fact |
3075 |
9 |
CONTROLLING_BLOCK(*settings).builtin_used = !remapped_in_block; |
3076 |
9 |
CHP(convert_tool_change(settings)); |
3077 |
|
} |
3078 |
|
break; |
3079 |
|
|
3080 |
|
case 61: |
3081 |
|
if (IS_USER_MCODE(block,settings,6) && remapped_in_block) { |
3082 |
|
return convert_remapped_code(block, settings, STEP_M_6,'m', |
3083 |
|
block->m_modes[6]); |
3084 |
|
} else { |
3085 |
|
CONTROLLING_BLOCK(*settings).builtin_used = !remapped_in_block; |
3086 |
|
toolno = round_to_int(block->q_number); |
3087 |
|
// now also accept M61 Q0 - unload tool |
3088 |
|
CHKS((toolno < 0), (_("Need non-negative Q-word to specify tool number with M61"))); |
3089 |
|
|
3090 |
|
int pocket; |
3091 |
|
|
3092 |
|
// make sure selected tool exists |
3093 |
|
CHP((find_tool_pocket(settings, toolno, &pocket))); |
3094 |
|
settings->current_pocket = pocket; |
3095 |
|
settings->toolchange_flag = true; |
3096 |
|
CHANGE_TOOL_NUMBER(settings->current_pocket); |
3097 |
|
set_tool_parameters(); |
3098 |
|
} |
3099 |
|
break; |
3100 |
|
|
3101 |
|
default: |
3102 |
|
if (IS_USER_MCODE(block,settings,6)) { |
3103 |
|
return convert_remapped_code(block, settings, STEP_M_6,'m', |
3104 |
|
block->m_modes[6]); |
3105 |
|
} |
3106 |
|
} |
3107 |
|
} |
3108 |
|
|
3109 |
|
// needs more testing.. once? test tool_change_flag! |
3110 |
|
//#ifdef DEBATABLE |
3111 |
4509 |
if (FEATURE(RETAIN_G43)) { |
3112 |
|
// I consider this useful, so make it configurable. |
3113 |
|
// Turn it on optionally . -mah |
3114 |
|
|
3115 |
|
// I would like this, but it's a big change. It changes the |
3116 |
|
// operation of legal ngc programs, but it could be argued that |
3117 |
|
// those programs are buggy or likely to be not what the author |
3118 |
|
// intended. |
3119 |
|
|
3120 |
|
// It would allow you to turn on G43 after loading the first tool, |
3121 |
|
// and then not worry about it through the program. When you |
3122 |
|
// finally unload the last tool, G43 mode is canceled. |
3123 |
|
|
3124 |
10 |
if ((settings->active_g_codes[9] == G_43) && ONCE(STEP_RETAIN_G43)) { |
3125 |
|
if(settings->selected_pocket > 0) { |
3126 |
|
struct block_struct g43; |
3127 |
|
init_block(&g43); |
3128 |
|
block->g_modes[_gees[G_43]] = G_43; |
3129 |
|
CHP(convert_tool_length_offset(G_43, &g43, settings)); |
3130 |
|
} else { |
3131 |
|
struct block_struct g49; |
3132 |
|
init_block(&g49); |
3133 |
|
block->g_modes[_gees[G_49]] = G_49; |
3134 |
|
CHP(convert_tool_length_offset(G_49, &g49, settings)); |
3135 |
|
} |
3136 |
|
} |
3137 |
|
} |
3138 |
|
//#endif |
3139 |
|
|
3140 |
4509 |
if (IS_USER_MCODE(block,settings,7) && ONCE_M(7)) { |
3141 |
|
return convert_remapped_code(block, settings, STEP_M_7, 'm', |
3142 |
|
block->m_modes[7]); |
3143 |
4525 |
} else if ((block->m_modes[7] == 3) && ONCE_M(7)) { |
3144 |
4 |
enqueue_START_SPINDLE_CLOCKWISE(); |
3145 |
4 |
settings->spindle_turning = CANON_CLOCKWISE; |
3146 |
4505 |
} else if ((block->m_modes[7] == 4) && ONCE_M(7)) { |
3147 |
|
enqueue_START_SPINDLE_COUNTERCLOCKWISE(); |
3148 |
|
settings->spindle_turning = CANON_COUNTERCLOCKWISE; |
3149 |
4521 |
} else if ((block->m_modes[7] == 5) && ONCE_M(7)){ |
3150 |
4 |
enqueue_STOP_SPINDLE_TURNING(); |
3151 |
4 |
settings->spindle_turning = CANON_STOPPED; |
3152 |
4525 |
} else if ((block->m_modes[7] == 19) && ONCE_M(7)) { |
3153 |
6 |
settings->spindle_turning = CANON_STOPPED; |
3154 |
6 |
if (block->r_flag || block->p_flag) |
3155 |
3 |
enqueue_ORIENT_SPINDLE(block->r_flag ? (block->r_number + settings->orient_offset) : settings->orient_offset, |
3156 |
7 |
block->p_flag ? block->p_number : 0); |
3157 |
6 |
if (block->q_flag) { |
3158 |
2 |
CHKS((block->q_number <= 0.0),(_("Q word with M19 requires a value > 0"))); |
3159 |
2 |
enqueue_WAIT_ORIENT_SPINDLE_COMPLETE(block->q_number); |
3160 |
|
} |
3161 |
4495 |
} else if ((block->m_modes[7] == 70) || (block->m_modes[7] == 73)) { |
3162 |
|
|
3163 |
|
// save state in current stack frame. We borrow the o-word call stack |
3164 |
|
// and extend it to hold modes & settings. |
3165 |
|
save_settings(&_setup); |
3166 |
|
|
3167 |
|
// flag this frame as containing a valid context |
3168 |
|
_setup.sub_context[_setup.call_level].context_status |= CONTEXT_VALID; |
3169 |
|
|
3170 |
|
// mark as auto-restore context |
3171 |
|
if (block->m_modes[7] == 73) { |
3172 |
|
if (_setup.call_level == 0) { |
3173 |
|
MSG("Warning - M73 at top level: nothing to return to; storing context anyway\n"); |
3174 |
|
} else { |
3175 |
|
_setup.sub_context[_setup.call_level].context_status |= CONTEXT_RESTORE_ON_RETURN; |
3176 |
|
} |
3177 |
|
} |
3178 |
4495 |
} else if ((block->m_modes[7] == 71) && ONCE_M(7)) { |
3179 |
|
// M72 - invalidate context at current level |
3180 |
|
_setup.sub_context[_setup.call_level].context_status &= ~CONTEXT_VALID; |
3181 |
|
|
3182 |
4495 |
} else if ((block->m_modes[7] == 72) && ONCE_M(7)) { |
3183 |
|
|
3184 |
|
// restore state from current stack frame. |
3185 |
|
CHKS((!(_setup.sub_context[_setup.call_level].context_status & CONTEXT_VALID)), |
3186 |
|
(_("Cannot restore context from invalid stack frame - missing M70/M73?"))); |
3187 |
|
CHP(restore_settings(&_setup, _setup.call_level)); |
3188 |
|
} |
3189 |
|
|
3190 |
4509 |
if (IS_USER_MCODE(block,settings,8) && ONCE_M(8)) { |
3191 |
|
return convert_remapped_code(block, settings, STEP_M_8, 'm', |
3192 |
|
block->m_modes[8]); |
3193 |
4509 |
} else if ((block->m_modes[8] == 7) && ONCE_M(8)){ |
3194 |
|
enqueue_MIST_ON(); |
3195 |
|
settings->mist = true; |
3196 |
4509 |
} else if ((block->m_modes[8] == 8) && ONCE_M(8)) { |
3197 |
|
enqueue_FLOOD_ON(); |
3198 |
|
settings->flood = true; |
3199 |
4509 |
} else if ((block->m_modes[8] == 9) && ONCE_M(8)) { |
3200 |
|
enqueue_MIST_OFF(); |
3201 |
|
settings->mist = false; |
3202 |
|
enqueue_FLOOD_OFF(); |
3203 |
|
settings->flood = false; |
3204 |
|
} |
3205 |
|
|
3206 |
|
/* No axis clamps in this version |
3207 |
|
if (block->m_modes[2] == 26) |
3208 |
|
{ |
3209 |
|
#ifdef DEBUG_EMC |
3210 |
|
COMMENT("interpreter: automatic A-axis clamping turned on"); |
3211 |
|
#endif |
3212 |
|
settings->a_axis_clamping = true; |
3213 |
|
} |
3214 |
|
else if (block->m_modes[2] == 27) |
3215 |
|
{ |
3216 |
|
#ifdef DEBUG_EMC |
3217 |
|
COMMENT("interpreter: automatic A-axis clamping turned off"); |
3218 |
|
#endif |
3219 |
|
settings->a_axis_clamping = false; |
3220 |
|
} |
3221 |
|
*/ |
3222 |
4509 |
if (IS_USER_MCODE(block,settings,9) && ONCE_M(9)) { |
3223 |
|
return convert_remapped_code(block, settings, STEP_M_9, 'm', |
3224 |
|
block->m_modes[9]); |
3225 |
4509 |
} else if ((block->m_modes[9] == 48) && ONCE_M(9)){ |
3226 |
|
CHKS((settings->cutter_comp_side), |
3227 |
|
(_("Cannot enable overrides with cutter radius compensation on"))); // XXX |
3228 |
|
ENABLE_FEED_OVERRIDE(); |
3229 |
|
ENABLE_SPEED_OVERRIDE(); |
3230 |
|
settings->feed_override = true; |
3231 |
|
settings->speed_override = true; |
3232 |
4509 |
} else if ((block->m_modes[9] == 49) && ONCE_M(9)){ |
3233 |
|
CHKS((settings->cutter_comp_side), |
3234 |
|
(_("Cannot disable overrides with cutter radius compensation on"))); // XXX |
3235 |
|
DISABLE_FEED_OVERRIDE(); |
3236 |
|
DISABLE_SPEED_OVERRIDE(); |
3237 |
|
settings->feed_override = false; |
3238 |
|
settings->speed_override = false; |
3239 |
|
} |
3240 |
|
|
3241 |
4509 |
if ((block->m_modes[9] == 50) && ONCE_M(9)){ |
3242 |
|
if (block->p_number != 0) { |
3243 |
|
CHKS((settings->cutter_comp_side), |
3244 |
|
(_("Cannot enable overrides with cutter radius compensation on"))); // XXX |
3245 |
|
ENABLE_FEED_OVERRIDE(); |
3246 |
|
settings->feed_override = true; |
3247 |
|
} else { |
3248 |
|
CHKS((settings->cutter_comp_side), |
3249 |
|
(_("Cannot disable overrides with cutter radius compensation on"))); // XXX |
3250 |
|
DISABLE_FEED_OVERRIDE(); |
3251 |
|
settings->feed_override = false; |
3252 |
|
} |
3253 |
|
} |
3254 |
|
|
3255 |
4509 |
if ((block->m_modes[9] == 51) && ONCE_M(9)){ |
3256 |
|
|
3257 |
|
if (block->p_number != 0) { |
3258 |
|
CHKS((settings->cutter_comp_side), |
3259 |
|
(_("Cannot enable overrides with cutter radius compensation on"))); // XXX |
3260 |
|
ENABLE_SPEED_OVERRIDE(); |
3261 |
|
settings->speed_override = true; |
3262 |
|
} else { |
3263 |
|
CHKS((settings->cutter_comp_side), |
3264 |
|
(_("Cannot disable overrides with cutter radius compensation on"))); // XXX |
3265 |
|
DISABLE_SPEED_OVERRIDE(); |
3266 |
|
settings->speed_override = false; |
3267 |
|
} |
3268 |
|
} |
3269 |
|
|
3270 |
4509 |
if ((block->m_modes[9] == 52) && ONCE_M(9)){ |
3271 |
|
if (block->p_number != 0) { |
3272 |
|
CHKS((settings->cutter_comp_side), |
3273 |
|
(_("Cannot enable overrides with cutter radius compensation on"))); // XXX |
3274 |
|
ENABLE_ADAPTIVE_FEED(); |
3275 |
|
settings->adaptive_feed = true; |
3276 |
|
} else { |
3277 |
|
CHKS((settings->cutter_comp_side), |
3278 |
|
(_("Cannot disable overrides with cutter radius compensation on"))); // XXX |
3279 |
|
DISABLE_ADAPTIVE_FEED(); |
3280 |
|
settings->adaptive_feed = false; |
3281 |
|
} |
3282 |
|
} |
3283 |
|
|
3284 |
4509 |
if ((block->m_modes[9] == 53) && ONCE_M(9)){ |
3285 |
|
if (block->p_number != 0) { |
3286 |
|
CHKS((settings->cutter_comp_side), |
3287 |
|
(_("Cannot enable overrides with cutter radius compensation on"))); // XXX |
3288 |
|
ENABLE_FEED_HOLD(); |
3289 |
|
settings->feed_hold = true; |
3290 |
|
} else { |
3291 |
|
CHKS((settings->cutter_comp_side), |
3292 |
|
(_("Cannot disable overrides with cutter radius compensation on"))); // XXX |
3293 |
|
DISABLE_FEED_HOLD(); |
3294 |
|
settings->feed_hold = false; |
3295 |
|
} |
3296 |
|
} |
3297 |
|
|
3298 |
4509 |
if (IS_USER_MCODE(block,settings,10) && ONCE_M(10)) { |
3299 |
|
return convert_remapped_code(block,settings,STEP_M_10,'m', |
3300 |
|
block->m_modes[10]); |
3301 |
|
|
3302 |
4509 |
} else if ((block->m_modes[10] != -1) && ONCE_M(10)){ |
3303 |
|
/* user-defined M codes */ |
3304 |
|
int index = block->m_modes[10]; |
3305 |
|
if (USER_DEFINED_FUNCTION[index - 100] == 0) { |
3306 |
|
CHKS(1, NCE_UNKNOWN_M_CODE_USED,index); |
3307 |
|
} |
3308 |
|
enqueue_M_USER_COMMAND(index,block->p_number,block->q_number); |
3309 |
|
} |
3310 |
|
return INTERP_OK; |
3311 |
|
} |
3312 |
|
|
3313 |
|
/****************************************************************************/ |
3314 |
|
|
3315 |
|
/*! convert_modal_0 |
3316 |
|
|
3317 |
|
Returned Value: int |
3318 |
|
If one of the following functions is called and returns an error code, |
3319 |
|
this returns that code. |
3320 |
|
convert_axis_offsets |
3321 |
|
convert_home |
3322 |
|
convert_setup |
3323 |
|
If any of the following errors occur, this returns the error code shown. |
3324 |
|
Otherwise, it returns INTERP_OK. |
3325 |
|
1. code is not G_4, G_10, G_28, G_30, G_52, G_53, G_92, G_92_1, G_92_2, |
3326 |
|
or G_92_3: |
3327 |
|
NCE_BUG_CODE_NOT_G4_G10_G28_G30_G52_G53_OR_G92_SERIES |
3328 |
|
|
3329 |
|
Side effects: See below |
3330 |
|
|
3331 |
|
Called by: convert_g |
3332 |
|
|
3333 |
|
If the g_code is g10, g28, g30, g52, g92, g92.1, g92.2, or g92.3 (all are in |
3334 |
|
modal group 0), it is executed. The other two in modal group 0 (G4 and |
3335 |
|
G53) are executed elsewhere. |
3336 |
|
|
3337 |
|
*/ |
3338 |
|
|
3339 |
82 |
int Interp::convert_modal_0(int code, //!< G code, must be from group 0 |
3340 |
|
block_pointer block, //!< pointer to a block of RS274/NGC instructions |
3341 |
|
setup_pointer settings) //!< pointer to machine settings |
3342 |
|
{ |
3343 |
|
|
3344 |
82 |
if (code == G_10) { |
3345 |
58 |
if(block->l_number == 1 || block->l_number == 10 || block->l_number == 11) |
3346 |
26 |
CHP(convert_setup_tool(block, settings)); |
3347 |
|
else |
3348 |
32 |
CHP(convert_setup(block, settings)); |
3349 |
24 |
} else if ((code == G_28) || (code == G_30)) { |
3350 |
|
CHP(convert_home(code, block, settings)); |
3351 |
24 |
} else if ((code == G_28_1) || (code == G_30_1)) { |
3352 |
|
CHP(convert_savehome(code, block, settings)); |
3353 |
48 |
} else if ((code == G_52) || |
3354 |
43 |
(code == G_92) || (code == G_92_1) || |
3355 |
14 |
(code == G_92_2) || (code == G_92_3)) { |
3356 |
12 |
CHP(convert_axis_offsets(code, block, settings)); |
3357 |
12 |
} else if (code == G_5_3) { |
3358 |
1 |
CHP(convert_nurbs(code, block, settings)); |
3359 |
11 |
} else if ((code == G_4) || (code == G_53)); /* handled elsewhere */ |
3360 |
|
else |
3361 |
|
ERS(NCE_BUG_CODE_NOT_G4_G10_G28_G30_G52_G53_OR_G92_SERIES); |
3362 |
|
return INTERP_OK; |
3363 |
|
} |
3364 |
|
|
3365 |
|
/****************************************************************************/ |
3366 |
|
|
3367 |
|
/*! convert_motion |
3368 |
|
|
3369 |
|
Returned Value: int |
3370 |
|
If one of the following functions is called and returns an error code, |
3371 |
|
this returns that code. |
3372 |
|
convert_arc |
3373 |
|
convert_cycle |
3374 |
|
convert_probe |
3375 |
|
convert_straight |
3376 |
|
If any of the following errors occur, this returns the error shown. |
3377 |
|
Otherwise, it returns INTERP_OK. |
3378 |
|
1. The motion code is not 0,1,2,3,38.2,80,81,82,83,84,85,86,87, 88, or 89: |
3379 |
|
NCE_BUG_UNKNOWN_MOTION_CODE |
3380 |
|
|
3381 |
|
Side effects: |
3382 |
|
A g_code from the group causing motion (mode 1) is executed. |
3383 |
|
|
3384 |
|
Called by: convert_g. |
3385 |
|
|
3386 |
|
*/ |
3387 |
|
|
3388 |
1459 |
int Interp::convert_motion(int motion, //!< g_code for a line, arc, canned cycle |
3389 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
3390 |
|
setup_pointer settings) //!< pointer to machine settings |
3391 |
|
{ |
3392 |
1459 |
int ai = block->a_flag && (-1 != settings->a_indexer_jnum); |
3393 |
1459 |
int bi = block->b_flag && (-1 != settings->b_indexer_jnum); |
3394 |
1459 |
int ci = block->c_flag && (-1 != settings->c_indexer_jnum); |
3395 |
|
|
3396 |
|
|
3397 |
1459 |
if (motion != G_0) { |
3398 |
1300 |
CHKS((ai), (_("Indexing axis %c can only be moved with G0")), 'A'); |
3399 |
1300 |
CHKS((bi), (_("Indexing axis %c can only be moved with G0")), 'B'); |
3400 |
1300 |
CHKS((ci), (_("Indexing axis %c can only be moved with G0")), 'C'); |
3401 |
|
} |
3402 |
|
|
3403 |
251 |
int xyzuvw_flag = (block->x_flag || block->y_flag || block->z_flag || |
3404 |
1461 |
block->u_flag || block->v_flag || block->w_flag); |
3405 |
|
|
3406 |
1459 |
CHKS((ai && (xyzuvw_flag || block->b_flag || block->c_flag)), |
3407 |
|
(_("Indexing axis %c can only be moved alone")), 'A'); |
3408 |
1459 |
CHKS((bi && (xyzuvw_flag || block->a_flag || block->c_flag)), |
3409 |
|
(_("Indexing axis %c can only be moved alone")), 'B'); |
3410 |
1459 |
CHKS((ci && (xyzuvw_flag || block->a_flag || block->b_flag)), |
3411 |
|
(_("Indexing axis %c can only be moved alone")), 'C'); |
3412 |
|
|
3413 |
1459 |
if (!is_a_cycle(motion)) |
3414 |
1422 |
settings->cycle_il_flag = false; |
3415 |
|
|
3416 |
1459 |
if (ai || bi || ci) { |
3417 |
|
int anum=-1,jnum=-1; |
3418 |
|
if ( ai) {anum = 3; jnum = settings->a_indexer_jnum;} |
3419 |
|
else if (bi) {anum = 4; jnum = settings->b_indexer_jnum;} |
3420 |
|
else if (ci) {anum = 5; jnum = settings->c_indexer_jnum;} |
3421 |
|
CHP(convert_straight_indexer(anum, jnum, block, settings)); |
3422 |
1459 |
} else if ((motion == G_0) || (motion == G_1) || (motion == G_33) || (motion == G_33_1) || (motion == G_76)) { |
3423 |
880 |
CHP(convert_straight(motion, block, settings)); |
3424 |
579 |
} else if ((motion == G_3) || (motion == G_2)) { |
3425 |
537 |
CHP(convert_arc(motion, block, settings)); |
3426 |
42 |
} else if (motion == G_38_2 || motion == G_38_3 || |
3427 |
42 |
motion == G_38_4 || motion == G_38_5) { |
3428 |
|
CHP(convert_probe(block, motion, settings)); |
3429 |
42 |
} else if (motion == G_80) { |
3430 |
|
#ifdef DEBUG_EMC |
3431 |
1 |
enqueue_COMMENT("interpreter: motion mode set to none"); |
3432 |
|
#endif |
3433 |
1 |
settings->motion_mode = G_80; |
3434 |
41 |
} else if (IS_USER_GCODE(motion)) { |
3435 |
|
CHP(convert_remapped_code(block, settings, STEP_MOTION, 'g', motion)); |
3436 |
41 |
} else if (is_a_cycle(motion)) { |
3437 |
37 |
CHP(convert_cycle(motion, block, settings)); |
3438 |
4 |
} else if ((motion == G_5) || (motion == G_5_1)) { |
3439 |
|
CHP(convert_spline(motion, block, settings)); |
3440 |
4 |
} else if (motion == G_5_2) { |
3441 |
4 |
CHP(convert_nurbs(motion, block, settings)); |
3442 |
|
} else { |
3443 |
|
ERS(NCE_BUG_UNKNOWN_MOTION_CODE); |
3444 |
|
} |
3445 |
|
|
3446 |
|
return INTERP_OK; |
3447 |
|
} |
3448 |
|
|
3449 |
|
/****************************************************************************/ |
3450 |
|
|
3451 |
|
/*! convert_probe |
3452 |
|
|
3453 |
|
Returned Value: int |
3454 |
|
If any of the following errors occur, this returns the error code shown. |
3455 |
|
Otherwise, it returns INTERP_OK. |
3456 |
|
1. No value is given in the block for any of X, Y, or Z: |
3457 |
|
NCE_X_Y_AND_Z_WORDS_ALL_MISSING_WITH_G38_2 |
3458 |
|
3. cutter radius comp is on: NCE_CANNOT_PROBE_WITH_CUTTER_RADIUS_COMP_ON |
3459 |
|
4. Feed rate is zero: NCE_CANNOT_PROBE_WITH_ZERO_FEED_RATE |
3460 |
|
5. The move is degenerate (already at the specified point) |
3461 |
|
NCE_START_POINT_TOO_CLOSE_TO_PROBE_POINT |
3462 |
|
|
3463 |
|
Side effects: |
3464 |
|
This executes a straight_probe command. |
3465 |
|
The probe_flag in the settings is set to true. |
3466 |
|
The motion mode in the settings is set to G_38_2. |
3467 |
|
|
3468 |
|
Called by: convert_motion. |
3469 |
|
|
3470 |
|
The approach to operating in incremental distance mode (g91) is to |
3471 |
|
put the the absolute position values into the block before using the |
3472 |
|
block to generate a move. |
3473 |
|
|
3474 |
|
After probing is performed, the location of the probe cannot be |
3475 |
|
predicted. This differs from every other command, all of which have |
3476 |
|
predictable results. The next call to the interpreter (with either |
3477 |
|
Interp::read or Interp::execute) will result in updating the |
3478 |
|
current position by calls to get_external_position_x, etc. |
3479 |
|
|
3480 |
|
*/ |
3481 |
|
|
3482 |
|
int Interp::convert_probe(block_pointer block, //!< pointer to a block of RS274 instructions |
3483 |
|
int g_code, |
3484 |
|
setup_pointer settings) //!< pointer to machine settings |
3485 |
|
{ |
3486 |
|
double end_x; |
3487 |
|
double end_y; |
3488 |
|
double end_z; |
3489 |
|
double AA_end; |
3490 |
|
double BB_end; |
3491 |
|
double CC_end; |
3492 |
|
double u_end; |
3493 |
|
double v_end; |
3494 |
|
double w_end; |
3495 |
|
|
3496 |
|
/* probe_type: |
3497 |
|
~1 = error if probe operation is unsuccessful (ngc default) |
3498 |
|
|1 = suppress error, report in # instead |
3499 |
|
~2 = move until probe trips (ngc default) |
3500 |
|
|2 = move until probe clears */ |
3501 |
|
|
3502 |
|
unsigned char probe_type = g_code - G_38_2; |
3503 |
|
|
3504 |
|
CHKS((settings->cutter_comp_side), |
3505 |
|
NCE_CANNOT_PROBE_WITH_CUTTER_RADIUS_COMP_ON); |
3506 |
|
CHKS((settings->feed_rate == 0.0), NCE_CANNOT_PROBE_WITH_ZERO_FEED_RATE); |
3507 |
|
CHKS(settings->feed_mode == UNITS_PER_REVOLUTION, |
3508 |
|
_("Cannot probe with feed per rev mode")); |
3509 |
|
CHP(find_ends(block, settings, &end_x, &end_y, &end_z, |
3510 |
|
&AA_end, &BB_end, &CC_end, |
3511 |
|
&u_end, &v_end, &w_end)); |
3512 |
|
CHKS(((!(probe_type & 1)) && |
3513 |
|
settings->current_x == end_x && settings->current_y == end_y && |
3514 |
|
settings->current_z == end_z && settings->AA_current == AA_end && |
3515 |
|
settings->BB_current == BB_end && settings->CC_current == CC_end && |
3516 |
|
settings->u_current == u_end && settings->v_current == v_end && |
3517 |
|
settings->w_current == w_end), |
3518 |
|
NCE_START_POINT_TOO_CLOSE_TO_PROBE_POINT); |
3519 |
|
|
3520 |
|
TURN_PROBE_ON(); |
3521 |
|
STRAIGHT_PROBE(block->line_number, end_x, end_y, end_z, |
3522 |
|
AA_end, BB_end, CC_end, |
3523 |
|
u_end, v_end, w_end, probe_type); |
3524 |
|
|
3525 |
|
TURN_PROBE_OFF(); |
3526 |
|
settings->motion_mode = g_code; |
3527 |
|
settings->probe_flag = true; |
3528 |
|
return INTERP_OK; |
3529 |
|
} |
3530 |
|
|
3531 |
|
/****************************************************************************/ |
3532 |
|
|
3533 |
|
/*! convert_retract_mode |
3534 |
|
|
3535 |
|
Returned Value: int |
3536 |
|
If any of the following errors occur, this returns the error code shown. |
3537 |
|
Otherwise, it returns INTERP_OK. |
3538 |
|
1. g_code isn't G_98 or G_99: NCE_BUG_CODE_NOT_G98_OR_G99 |
3539 |
|
|
3540 |
|
Side effects: |
3541 |
|
The interpreter switches the machine settings to indicate the current |
3542 |
|
retract mode for canned cycles (OLD_Z or R_PLANE). |
3543 |
|
|
3544 |
|
Called by: convert_g. |
3545 |
|
|
3546 |
|
The canonical machine to which commands are being sent does not have a |
3547 |
|
retract mode, so no command setting the retract mode is generated in |
3548 |
|
this function. |
3549 |
|
|
3550 |
|
*/ |
3551 |
|
|
3552 |
6 |
int Interp::convert_retract_mode(int g_code, //!< g_code being executed (must be G_98 or G_99) |
3553 |
|
setup_pointer settings) //!< pointer to machine settings |
3554 |
|
{ |
3555 |
6 |
CHKS((settings->cutter_comp_side), |
3556 |
|
(_("Cannot change retract mode with cutter radius compensation on"))); |
3557 |
6 |
if (g_code == G_98) { |
3558 |
|
#ifdef DEBUG_EMC |
3559 |
3 |
enqueue_COMMENT("interpreter: retract mode set to old_z"); |
3560 |
|
#endif |
3561 |
3 |
settings->retract_mode = OLD_Z; |
3562 |
3 |
} else if (g_code == G_99) { |
3563 |
|
#ifdef DEBUG_EMC |
3564 |
3 |
enqueue_COMMENT("interpreter: retract mode set to r_plane"); |
3565 |
|
#endif |
3566 |
3 |
settings->retract_mode = R_PLANE; |
3567 |
|
} else |
3568 |
|
ERS(NCE_BUG_CODE_NOT_G98_OR_G99); |
3569 |
|
return INTERP_OK; |
3570 |
|
} |
3571 |
|
|
3572 |
|
// G10 L1 P[tool number] R[radius] X[x offset] Z[z offset] Q[orientation] |
3573 |
|
// G10 L10 P[tool number] R[radius] X[x offset] Z[z offset] Q[orientation] |
3574 |
|
|
3575 |
26 |
int Interp::convert_setup_tool(block_pointer block, setup_pointer settings) { |
3576 |
26 |
int pocket = -1, toolno; |
3577 |
|
int q; |
3578 |
|
double tx, ty, tz, ta, tb, tc, tu, tv, tw; |
3579 |
26 |
int direct = block->l_number == 1; |
3580 |
|
|
3581 |
26 |
is_near_int(&toolno, block->p_number); |
3582 |
|
|
3583 |
26 |
CHP((find_tool_pocket(settings, toolno, &pocket))); |
3584 |
|
|
3585 |
26 |
CHKS(!(block->x_flag || block->y_flag || block->z_flag || |
3586 |
|
block->a_flag || block->b_flag || block->c_flag || |
3587 |
|
block->u_flag || block->v_flag || block->w_flag || |
3588 |
|
block->r_flag || block->q_flag || block->i_flag || |
3589 |
|
block->j_flag), |
3590 |
|
_("G10 L1 without offsets has no effect")); |
3591 |
|
|
3592 |
26 |
if(direct) { |
3593 |
9 |
if(block->x_flag) |
3594 |
5 |
settings->tool_table[pocket].offset.tran.x = PROGRAM_TO_USER_LEN(block->x_number); |
3595 |
9 |
if(block->y_flag) |
3596 |
5 |
settings->tool_table[pocket].offset.tran.y = PROGRAM_TO_USER_LEN(block->y_number); |
3597 |
9 |
if(block->z_flag) |
3598 |
5 |
settings->tool_table[pocket].offset.tran.z = PROGRAM_TO_USER_LEN(block->z_number); |
3599 |
9 |
if(block->a_flag) |
3600 |
|
settings->tool_table[pocket].offset.a = PROGRAM_TO_USER_ANG(block->a_number); |
3601 |
9 |
if(block->b_flag) |
3602 |
|
settings->tool_table[pocket].offset.b = PROGRAM_TO_USER_ANG(block->b_number); |
3603 |
9 |
if(block->c_flag) |
3604 |
|
settings->tool_table[pocket].offset.c = PROGRAM_TO_USER_ANG(block->c_number); |
3605 |
9 |
if(block->u_flag) |
3606 |
|
settings->tool_table[pocket].offset.u = PROGRAM_TO_USER_LEN(block->u_number); |
3607 |
9 |
if(block->v_flag) |
3608 |
|
settings->tool_table[pocket].offset.v = PROGRAM_TO_USER_LEN(block->v_number); |
3609 |
9 |
if(block->w_flag) |
3610 |
|
settings->tool_table[pocket].offset.w = PROGRAM_TO_USER_LEN(block->w_number); |
3611 |
|
} else { |
3612 |
17 |
int to_fixture = block->l_number == 11; |
3613 |
17 |
int destination_system = to_fixture? 9 : settings->origin_index; // maybe 9 (g59.3) should be user configurable? |
3614 |
|
|
3615 |
|
find_current_in_system_without_tlo(settings, destination_system, |
3616 |
|
&tx, &ty, &tz, |
3617 |
|
&ta, &tb, &tc, |
3618 |
17 |
&tu, &tv, &tw); |
3619 |
|
|
3620 |
17 |
if ( to_fixture && settings->parameters[5210]) { |
3621 |
|
// For G10L11, we don't want to move the origin of the |
3622 |
|
// fixture according to G92. Since find_current_in_system |
3623 |
|
// did this for us already, undo it. |
3624 |
2 |
tx += USER_TO_PROGRAM_LEN(settings->parameters[5211]); |
3625 |
2 |
ty += USER_TO_PROGRAM_LEN(settings->parameters[5212]); |
3626 |
2 |
tz += USER_TO_PROGRAM_LEN(settings->parameters[5213]); |
3627 |
2 |
ta += USER_TO_PROGRAM_ANG(settings->parameters[5214]); |
3628 |
2 |
tb += USER_TO_PROGRAM_ANG(settings->parameters[5215]); |
3629 |
2 |
tc += USER_TO_PROGRAM_ANG(settings->parameters[5216]); |
3630 |
2 |
tu += USER_TO_PROGRAM_LEN(settings->parameters[5217]); |
3631 |
2 |
tv += USER_TO_PROGRAM_LEN(settings->parameters[5218]); |
3632 |
2 |
tw += USER_TO_PROGRAM_LEN(settings->parameters[5219]); |
3633 |
|
} |
3634 |
|
|
3635 |
|
|
3636 |
17 |
if(block->x_flag && block->y_flag) { |
3637 |
3 |
tx -= block->x_number; |
3638 |
3 |
ty -= block->y_number; |
3639 |
3 |
rotate(&tx, &ty, settings->parameters[5210 + destination_system * 20]); |
3640 |
3 |
settings->tool_table[pocket].offset.tran.x = PROGRAM_TO_USER_LEN(tx); |
3641 |
3 |
settings->tool_table[pocket].offset.tran.y = PROGRAM_TO_USER_LEN(ty); |
3642 |
14 |
} else if(block->x_flag) { |
3643 |
|
// keep the component of the tool table's current setting that points |
3644 |
|
// along our possibly-rotated Y axis |
3645 |
|
double ox, oy; |
3646 |
4 |
ox = USER_TO_PROGRAM_LEN(settings->tool_table[pocket].offset.tran.x); |
3647 |
4 |
oy = USER_TO_PROGRAM_LEN(settings->tool_table[pocket].offset.tran.y); |
3648 |
4 |
rotate(&ox, &oy, -settings->parameters[5210 + destination_system * 20]); |
3649 |
4 |
ox = 0; |
3650 |
4 |
rotate(&ox, &oy, settings->parameters[5210 + destination_system * 20]); |
3651 |
|
|
3652 |
|
|
3653 |
4 |
tx -= block->x_number; |
3654 |
4 |
ty = 0; |
3655 |
4 |
rotate(&tx, &ty, settings->parameters[5210 + destination_system * 20]); |
3656 |
|
|
3657 |
4 |
settings->tool_table[pocket].offset.tran.x = PROGRAM_TO_USER_LEN(tx + ox); |
3658 |
4 |
settings->tool_table[pocket].offset.tran.y = PROGRAM_TO_USER_LEN(ty + oy); |
3659 |
10 |
} else if(block->y_flag) { |
3660 |
|
double ox, oy; |
3661 |
5 |
ox = USER_TO_PROGRAM_LEN(settings->tool_table[pocket].offset.tran.x); |
3662 |
5 |
oy = USER_TO_PROGRAM_LEN(settings->tool_table[pocket].offset.tran.y); |
3663 |
5 |
rotate(&ox, &oy, -settings->parameters[5210 + destination_system * 20]); |
3664 |
5 |
oy = 0; |
3665 |
5 |
rotate(&ox, &oy, settings->parameters[5210 + destination_system * 20]); |
3666 |
|
|
3667 |
5 |
ty -= block->y_number; |
3668 |
5 |
tx = 0; |
3669 |
|
|
3670 |
5 |
rotate(&tx, &ty, settings->parameters[5210 + destination_system * 20]); |
3671 |
5 |
settings->tool_table[pocket].offset.tran.x = PROGRAM_TO_USER_LEN(tx + ox); |
3672 |
5 |
settings->tool_table[pocket].offset.tran.y = PROGRAM_TO_USER_LEN(ty + oy); |
3673 |
|
} |
3674 |
|
|
3675 |
|
|
3676 |
17 |
if(block->z_flag) |
3677 |
9 |
settings->tool_table[pocket].offset.tran.z = PROGRAM_TO_USER_LEN(tz - block->z_number); |
3678 |
17 |
if(block->a_flag) |
3679 |
|
settings->tool_table[pocket].offset.a = PROGRAM_TO_USER_ANG(ta - block->a_number); |
3680 |
17 |
if(block->b_flag) |
3681 |
|
settings->tool_table[pocket].offset.b = PROGRAM_TO_USER_ANG(tb - block->b_number); |
3682 |
17 |
if(block->c_flag) |
3683 |
|
settings->tool_table[pocket].offset.c = PROGRAM_TO_USER_ANG(tc - block->c_number); |
3684 |
17 |
if(block->u_flag) |
3685 |
|
settings->tool_table[pocket].offset.u = PROGRAM_TO_USER_LEN(tu - block->u_number); |
3686 |
17 |
if(block->v_flag) |
3687 |
|
settings->tool_table[pocket].offset.v = PROGRAM_TO_USER_LEN(tv - block->v_number); |
3688 |
17 |
if(block->w_flag) |
3689 |
|
settings->tool_table[pocket].offset.w = PROGRAM_TO_USER_LEN(tw - block->w_number); |
3690 |
|
} |
3691 |
|
|
3692 |
26 |
if(block->r_flag) settings->tool_table[pocket].diameter = PROGRAM_TO_USER_LEN(block->r_number) * 2.; |
3693 |
26 |
if(block->i_flag) settings->tool_table[pocket].frontangle = block->i_number; |
3694 |
26 |
if(block->j_flag) settings->tool_table[pocket].backangle = block->j_number; |
3695 |
26 |
if(block->q_number != -1.0) { |
3696 |
|
CHKS((!is_near_int(&q, block->q_number)), _("Q number in G10 is not an integer")); |
3697 |
|
CHKS((q > 9), _("Invalid tool orientation")); |
3698 |
|
settings->tool_table[pocket].orientation = q; |
3699 |
|
} |
3700 |
|
|
3701 |
|
SET_TOOL_TABLE_ENTRY(pocket, |
3702 |
|
settings->tool_table[pocket].toolno, |
3703 |
|
settings->tool_table[pocket].offset, |
3704 |
|
settings->tool_table[pocket].diameter, |
3705 |
|
settings->tool_table[pocket].frontangle, |
3706 |
|
settings->tool_table[pocket].backangle, |
3707 |
26 |
settings->tool_table[pocket].orientation); |
3708 |
|
|
3709 |
|
// |
3710 |
|
// On non-random tool changers we just updated the tool's "home pocket" |
3711 |
|
// in the tool changer carousel, so now, if the tool is currently |
3712 |
|
// loaded, we need to copy the new tool information to the spindle |
3713 |
|
// (pocket 0). This is never needed on random tool changers because |
3714 |
|
// there tools don't have a home pocket, and instead we updated pocket |
3715 |
|
// 0 (the spindle) directly when modifying the loaded tool. |
3716 |
|
// |
3717 |
26 |
if ((!settings->random_toolchanger) && (settings->current_pocket == pocket)) { |
3718 |
26 |
settings->tool_table[0] = settings->tool_table[pocket]; |
3719 |
|
} |
3720 |
|
|
3721 |
|
// |
3722 |
|
// Update parameter #5400 with the tool currently in the spindle, or a |
3723 |
|
// special "invalid tool number" marker if no tool is in the spindle. |
3724 |
|
// Unfortunately, random and nonrandom toolchangers use a different |
3725 |
|
// number for "invalid tool number": nonrandom uses 0, random uses -1. |
3726 |
|
// |
3727 |
26 |
if (settings->random_toolchanger) |
3728 |
|
if (settings->tool_table[0].toolno >= 0) { |
3729 |
|
settings->parameters[5400] = settings->tool_table[0].toolno; |
3730 |
|
} else { |
3731 |
|
settings->parameters[5400] = -1; |
3732 |
|
} else { |
3733 |
26 |
if (settings->tool_table[0].toolno > 0) { |
3734 |
26 |
settings->parameters[5400] = settings->tool_table[0].toolno; |
3735 |
|
} else { |
3736 |
|
settings->parameters[5400] = 0; |
3737 |
|
} |
3738 |
|
} |
3739 |
|
|
3740 |
26 |
settings->parameters[5401] = settings->tool_table[0].offset.tran.x; |
3741 |
26 |
settings->parameters[5402] = settings->tool_table[0].offset.tran.y; |
3742 |
26 |
settings->parameters[5403] = settings->tool_table[0].offset.tran.z; |
3743 |
26 |
settings->parameters[5404] = settings->tool_table[0].offset.a; |
3744 |
26 |
settings->parameters[5405] = settings->tool_table[0].offset.b; |
3745 |
26 |
settings->parameters[5406] = settings->tool_table[0].offset.c; |
3746 |
26 |
settings->parameters[5407] = settings->tool_table[0].offset.u; |
3747 |
26 |
settings->parameters[5408] = settings->tool_table[0].offset.v; |
3748 |
26 |
settings->parameters[5409] = settings->tool_table[0].offset.w; |
3749 |
26 |
settings->parameters[5410] = settings->tool_table[0].diameter; |
3750 |
26 |
settings->parameters[5411] = settings->tool_table[0].frontangle; |
3751 |
26 |
settings->parameters[5412] = settings->tool_table[0].backangle; |
3752 |
26 |
settings->parameters[5413] = settings->tool_table[0].orientation; |
3753 |
|
|
3754 |
|
// if the modified tool is currently in the spindle, then copy its |
3755 |
|
// information to pocket 0 of the tool table (which signifies the |
3756 |
|
// spindle) |
3757 |
26 |
if ( !_setup.random_toolchanger |
3758 |
26 |
&& pocket == settings->current_pocket) { |
3759 |
|
SET_TOOL_TABLE_ENTRY(0, |
3760 |
|
settings->tool_table[pocket].toolno, |
3761 |
|
settings->tool_table[pocket].offset, |
3762 |
|
settings->tool_table[pocket].diameter, |
3763 |
|
settings->tool_table[pocket].frontangle, |
3764 |
|
settings->tool_table[pocket].backangle, |
3765 |
26 |
settings->tool_table[pocket].orientation); |
3766 |
|
} |
3767 |
|
|
3768 |
|
return INTERP_OK; |
3769 |
|
} |
3770 |
|
|
3771 |
|
/****************************************************************************/ |
3772 |
|
|
3773 |
|
/*! convert_setup |
3774 |
|
|
3775 |
|
Returned Value: int (INTERP_OK) |
3776 |
|
|
3777 |
|
Side effects: |
3778 |
|
SET_G5X_OFFSET is called, and the coordinate |
3779 |
|
values for the program origin are reset. |
3780 |
|
If the program origin is currently in use, the values of the |
3781 |
|
the coordinates of the current point are updated. |
3782 |
|
|
3783 |
|
Called by: convert_modal_0. |
3784 |
|
|
3785 |
|
This is called only if g10 is called. g10 L2 may be used to alter the |
3786 |
|
location of coordinate systems as described in [NCMS, pages 9 - 10] and |
3787 |
|
[Fanuc, page 65]. [Fanuc] has only six coordinate systems, while |
3788 |
|
[NCMS] has nine (the first six of which are the same as the six [Fanuc] |
3789 |
|
has). All nine are implemented here. |
3790 |
|
|
3791 |
|
Being in incremental distance mode has no effect on the action of G10 |
3792 |
|
in this implementation. The manual is not explicit about what is |
3793 |
|
intended. |
3794 |
|
|
3795 |
|
If L is 20 instead of 2, the coordinates are relative to the current |
3796 |
|
position instead of the origin. Like how G92 offsets are programmed, |
3797 |
|
the meaning is "set the coordinate system origin such that my current |
3798 |
|
position becomes the specified value". |
3799 |
|
|
3800 |
|
See documentation of convert_coordinate_system for more information. |
3801 |
|
|
3802 |
|
*/ |
3803 |
|
|
3804 |
32 |
int Interp::convert_setup(block_pointer block, //!< pointer to a block of RS274/NGC instructions |
3805 |
|
setup_pointer settings) //!< pointer to machine settings |
3806 |
|
{ |
3807 |
|
double x; |
3808 |
|
double y; |
3809 |
|
double z; |
3810 |
|
double a; |
3811 |
|
double b; |
3812 |
|
double c; |
3813 |
|
double u, v, w; |
3814 |
|
double r; |
3815 |
|
double *parameters; |
3816 |
|
int p_int; |
3817 |
|
|
3818 |
|
double cx, cy, cz, ca, cb, cc, cu, cv, cw; |
3819 |
|
|
3820 |
32 |
CHKS((block->i_flag || block->j_flag), _("I J words not allowed with G10 L2")); |
3821 |
|
|
3822 |
32 |
parameters = settings->parameters; |
3823 |
32 |
p_int = (int) (block->p_number + 0.0001); |
3824 |
|
|
3825 |
|
// if P = 0 then use whatever coordinate system that is currently active |
3826 |
32 |
if (p_int == 0) { |
3827 |
|
p_int = settings->origin_index; |
3828 |
|
} |
3829 |
|
|
3830 |
32 |
CHKS((block->l_number == 20 && block->a_flag && settings->a_axis_wrapped && |
3831 |
|
(block->a_number <= -360.0 || block->a_number >= 360.0)), |
3832 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), block->a_number, 'A'); |
3833 |
32 |
CHKS((block->l_number == 20 && block->b_flag && settings->b_axis_wrapped && |
3834 |
|
(block->b_number <= -360.0 || block->b_number >= 360.0)), |
3835 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), block->b_number, 'B'); |
3836 |
32 |
CHKS((block->l_number == 20 && block->c_flag && settings->c_axis_wrapped && |
3837 |
|
(block->c_number <= -360.0 || block->c_number >= 360.0)), |
3838 |
|
(_("Invalid absolute position %5.2f for wrapped rotary axis %c")), block->c_number, 'C'); |
3839 |
|
|
3840 |
32 |
CHKS((settings->cutter_comp_side && p_int == settings->origin_index), |
3841 |
|
(_("Cannot change the active coordinate system with cutter radius compensation on"))); |
3842 |
|
|
3843 |
|
find_current_in_system(settings, p_int, |
3844 |
|
&cx, &cy, &cz, |
3845 |
|
&ca, &cb, &cc, |
3846 |
32 |
&cu, &cv, &cw); |
3847 |
|
|
3848 |
32 |
if (block->r_flag) { |
3849 |
26 |
CHKS((block->l_number == 20), _("R not allowed in G10 L20")); |
3850 |
26 |
r = block->r_number; |
3851 |
26 |
parameters[5210 + (p_int * 20)] = r; |
3852 |
|
} else |
3853 |
6 |
r = parameters[5210 + (p_int * 20)]; |
3854 |
|
|
3855 |
32 |
if (block->l_number == 20) { |
3856 |
|
// old position in rotated system |
3857 |
3 |
double oldx = cx, oldy = cy; |
3858 |
|
|
3859 |
|
// find new desired position in rotated system |
3860 |
3 |
x = cx; |
3861 |
3 |
y = cy; |
3862 |
|
|
3863 |
3 |
if (block->x_flag) { |
3864 |
2 |
x = block->x_number; |
3865 |
|
} |
3866 |
3 |
if (block->y_flag) { |
3867 |
2 |
y = block->y_number; |
3868 |
|
} |
3869 |
|
|
3870 |
|
// move old current position into the unrotated system |
3871 |
3 |
rotate(&oldx, &oldy, r); |
3872 |
|
// move desired position into the unrotated system |
3873 |
3 |
rotate(&x, &y, r); |
3874 |
|
|
3875 |
|
// find new offset |
3876 |
3 |
x = oldx + USER_TO_PROGRAM_LEN(parameters[5201 + (p_int * 20)]) - x; |
3877 |
3 |
y = oldy + USER_TO_PROGRAM_LEN(parameters[5202 + (p_int * 20)]) - y; |
3878 |
|
|
3879 |
|
// parameters are not rotated |
3880 |
3 |
parameters[5201 + (p_int * 20)] = PROGRAM_TO_USER_LEN(x); |
3881 |
3 |
parameters[5202 + (p_int * 20)] = PROGRAM_TO_USER_LEN(y); |
3882 |
|
|
3883 |
3 |
if (p_int == settings->origin_index) { |
3884 |
|
// let the code below fix up the current coordinates correctly |
3885 |
3 |
rotate(&settings->current_x, &settings->current_y, settings->rotation_xy); |
3886 |
3 |
settings->rotation_xy = 0; |
3887 |
|
} |
3888 |
|
} else { |
3889 |
29 |
if (block->x_flag) { |
3890 |
24 |
x = block->x_number; |
3891 |
24 |
parameters[5201 + (p_int * 20)] = PROGRAM_TO_USER_LEN(x); |
3892 |
|
} else { |
3893 |
5 |
x = USER_TO_PROGRAM_LEN(parameters[5201 + (p_int * 20)]); |
3894 |
|
} |
3895 |
29 |
if (block->y_flag) { |
3896 |
23 |
y = block->y_number; |
3897 |
23 |
parameters[5202 + (p_int * 20)] = PROGRAM_TO_USER_LEN(y); |
3898 |
|
} else { |
3899 |
6 |
y = USER_TO_PROGRAM_LEN(parameters[5202 + (p_int * 20)]); |
3900 |
|
} |
3901 |
|
} |
3902 |
|
|
3903 |
32 |
if (block->z_flag) { |
3904 |
21 |
z = block->z_number; |
3905 |
21 |
if (block->l_number == 20) z = cz + USER_TO_PROGRAM_LEN(parameters[5203 + (p_int * 20)]) - z; |
3906 |
21 |
parameters[5203 + (p_int * 20)] = PROGRAM_TO_USER_LEN(z); |
3907 |
|
} else |
3908 |
11 |
z = USER_TO_PROGRAM_LEN(parameters[5203 + (p_int * 20)]); |
3909 |
|
|
3910 |
32 |
if (block->a_flag) { |
3911 |
|
a = block->a_number; |
3912 |
|
if (block->l_number == 20) a = ca + USER_TO_PROGRAM_ANG(parameters[5204 + (p_int * 20)]) - a; |
3913 |
|
parameters[5204 + (p_int * 20)] = PROGRAM_TO_USER_ANG(a); |
3914 |
|
} else |
3915 |
32 |
a = USER_TO_PROGRAM_ANG(parameters[5204 + (p_int * 20)]); |
3916 |
|
|
3917 |
32 |
if (block->b_flag) { |
3918 |
|
b = block->b_number; |
3919 |
|
if (block->l_number == 20) b = cb + USER_TO_PROGRAM_ANG(parameters[5205 + (p_int * 20)]) - b; |
3920 |
|
parameters[5205 + (p_int * 20)] = PROGRAM_TO_USER_ANG(b); |
3921 |
|
} else |
3922 |
32 |
b = USER_TO_PROGRAM_ANG(parameters[5205 + (p_int * 20)]); |
3923 |
|
|
3924 |
32 |
if (block->c_flag) { |
3925 |
|
c = block->c_number; |
3926 |
|
if (block->l_number == 20) c = cc + USER_TO_PROGRAM_ANG(parameters[5206 + (p_int * 20)]) - c; |
3927 |
|
parameters[5206 + (p_int * 20)] = PROGRAM_TO_USER_ANG(c); |
3928 |
|
} else |
3929 |
32 |
c = USER_TO_PROGRAM_ANG(parameters[5206 + (p_int * 20)]); |
3930 |
|
|
3931 |
32 |
if (block->u_flag) { |
3932 |
|
u = block->u_number; |
3933 |
|
if (block->l_number == 20) u = cu + USER_TO_PROGRAM_LEN(parameters[5207 + (p_int * 20)]) - u; |
3934 |
|
parameters[5207 + (p_int * 20)] = PROGRAM_TO_USER_LEN(u); |
3935 |
|
} else |
3936 |
32 |
u = USER_TO_PROGRAM_LEN(parameters[5207 + (p_int * 20)]); |
3937 |
|
|
3938 |
32 |
if (block->v_flag) { |
3939 |
|
v = block->v_number; |
3940 |
|
if (block->l_number == 20) v = cv + USER_TO_PROGRAM_LEN(parameters[5208 + (p_int * 20)]) - v; |
3941 |
|
parameters[5208 + (p_int * 20)] = PROGRAM_TO_USER_LEN(v); |
3942 |
|
} else |
3943 |
32 |
v = USER_TO_PROGRAM_LEN(parameters[5208 + (p_int * 20)]); |
3944 |
|
|
3945 |
32 |
if (block->w_flag) { |
3946 |
|
w = block->w_number; |
3947 |
|
if (block->l_number == 20) w = cw + USER_TO_PROGRAM_LEN(parameters[5209 + (p_int * 20)]) - w; |
3948 |
|
parameters[5209 + (p_int * 20)] = PROGRAM_TO_USER_LEN(w); |
3949 |
|
} else |
3950 |
32 |
w = USER_TO_PROGRAM_LEN(parameters[5209 + (p_int * 20)]); |
3951 |
|
|
3952 |
32 |
if (p_int == settings->origin_index) { /* system is currently used */ |
3953 |
|
|
3954 |
16 |
rotate(&settings->current_x, &settings->current_y, settings->rotation_xy); |
3955 |
|
|
3956 |
16 |
settings->current_x += settings->origin_offset_x; |
3957 |
16 |
settings->current_y += settings->origin_offset_y; |
3958 |
16 |
settings->current_z += settings->origin_offset_z; |
3959 |
16 |
settings->AA_current += settings->AA_origin_offset; |
3960 |
16 |
settings->BB_current += settings->BB_origin_offset; |
3961 |
16 |
settings->CC_current += settings->CC_origin_offset; |
3962 |
16 |
settings->u_current += settings->u_origin_offset; |
3963 |
16 |
settings->v_current += settings->v_origin_offset; |
3964 |
16 |
settings->w_current += settings->w_origin_offset; |
3965 |
|
|
3966 |
16 |
settings->origin_offset_x = x; |
3967 |
16 |
settings->origin_offset_y = y; |
3968 |
16 |
settings->origin_offset_z = z; |
3969 |
16 |
settings->AA_origin_offset = a; |
3970 |
16 |
settings->BB_origin_offset = b; |
3971 |
16 |
settings->CC_origin_offset = c; |
3972 |
16 |
settings->u_origin_offset = u; |
3973 |
16 |
settings->v_origin_offset = v; |
3974 |
16 |
settings->w_origin_offset = w; |
3975 |
|
|
3976 |
16 |
settings->current_x -= x; |
3977 |
16 |
settings->current_y -= y; |
3978 |
16 |
settings->current_z -= z; |
3979 |
16 |
settings->AA_current -= a; |
3980 |
16 |
settings->BB_current -= b; |
3981 |
16 |
settings->CC_current -= c; |
3982 |
16 |
settings->u_current -= u; |
3983 |
16 |
settings->v_current -= v; |
3984 |
16 |
settings->w_current -= w; |
3985 |
|
|
3986 |
16 |
SET_G5X_OFFSET(p_int, x, y, z, a, b, c, u, v, w); |
3987 |
|
|
3988 |
16 |
rotate(&settings->current_x, &settings->current_y, - r); |
3989 |
16 |
settings->rotation_xy = r; |
3990 |
16 |
SET_XY_ROTATION(settings->rotation_xy); |
3991 |
|
|
3992 |
|
} |
3993 |
|
#ifdef DEBUG_EMC |
3994 |
|
else |
3995 |
16 |
enqueue_COMMENT("interpreter: setting coordinate system origin"); |
3996 |
|
#endif |
3997 |
|
return INTERP_OK; |
3998 |
|
} |
3999 |
|
|
4000 |
|
/****************************************************************************/ |
4001 |
|
|
4002 |
|
/*! convert_set_plane |
4003 |
|
|
4004 |
|
Returned Value: int |
4005 |
|
If any of the following errors occur, this returns the error code shown. |
4006 |
|
Otherwise, it returns INTERP_OK. |
4007 |
|
1. The user tries to change to a different plane while comp is on: |
4008 |
|
NCE_CANNOT_CHANGE_PLANES_WITH_CUTTER_RADIUS_COMP_ON); |
4009 |
|
2. The g_code is not G_17, G_18, or G_19: |
4010 |
|
NCE_BUG_CODE_NOT_G17_G18_OR_G19 |
4011 |
|
|
4012 |
|
Side effects: |
4013 |
|
A canonical command setting the current plane is executed. |
4014 |
|
|
4015 |
|
Called by: convert_g. |
4016 |
|
|
4017 |
|
*/ |
4018 |
|
|
4019 |
11 |
int Interp::convert_set_plane(int g_code, //!< must be G_17, G_18, or G_19 |
4020 |
|
setup_pointer settings) //!< pointer to machine settings |
4021 |
|
{ |
4022 |
11 |
CHKS((settings->cutter_comp_side && g_code == G_17 && settings->plane != CANON_PLANE_XY), |
4023 |
|
NCE_CANNOT_CHANGE_PLANES_WITH_CUTTER_RADIUS_COMP_ON); |
4024 |
11 |
CHKS((settings->cutter_comp_side && g_code == G_18 && settings->plane != CANON_PLANE_XZ), |
4025 |
|
NCE_CANNOT_CHANGE_PLANES_WITH_CUTTER_RADIUS_COMP_ON); |
4026 |
11 |
CHKS((settings->cutter_comp_side && g_code == G_19 && settings->plane != CANON_PLANE_YZ), |
4027 |
|
NCE_CANNOT_CHANGE_PLANES_WITH_CUTTER_RADIUS_COMP_ON); |
4028 |
|
|
4029 |
11 |
CHKS((settings->cutter_comp_side && g_code == G_19), |
4030 |
|
NCE_RADIUS_COMP_ONLY_IN_XY_OR_XZ); |
4031 |
|
|
4032 |
11 |
if (g_code == G_17) { |
4033 |
3 |
SELECT_PLANE(CANON_PLANE_XY); |
4034 |
3 |
settings->plane = CANON_PLANE_XY; |
4035 |
8 |
} else if (g_code == G_18) { |
4036 |
6 |
SELECT_PLANE(CANON_PLANE_XZ); |
4037 |
6 |
settings->plane = CANON_PLANE_XZ; |
4038 |
2 |
} else if (g_code == G_19) { |
4039 |
2 |
SELECT_PLANE(CANON_PLANE_YZ); |
4040 |
2 |
settings->plane = CANON_PLANE_YZ; |
4041 |
|
} else if (g_code == G_17_1) { |
4042 |
|
SELECT_PLANE(CANON_PLANE_UV); |
4043 |
|
settings->plane = CANON_PLANE_UV; |
4044 |
|
} else if (g_code == G_18_1) { |
4045 |
|
SELECT_PLANE(CANON_PLANE_UW); |
4046 |
|
settings->plane = CANON_PLANE_UW; |
4047 |
|
} else if (g_code == G_19_1) { |
4048 |
|
SELECT_PLANE(CANON_PLANE_VW); |
4049 |
|
settings->plane = CANON_PLANE_VW; |
4050 |
|
} else |
4051 |
|
ERS(NCE_BUG_CODE_NOT_G17_G18_OR_G19); |
4052 |
|
return INTERP_OK; |
4053 |
|
} |
4054 |
|
|
4055 |
|
/****************************************************************************/ |
4056 |
|
|
4057 |
|
/*! convert_speed |
4058 |
|
|
4059 |
|
Returned Value: int (INTERP_OK) |
4060 |
|
|
4061 |
|
Side effects: |
4062 |
|
The machine spindle speed is set to the value of s_number in the |
4063 |
|
block by a call to SET_SPINDLE_SPEED. |
4064 |
|
The machine model for spindle speed is set to that value. |
4065 |
|
|
4066 |
|
Called by: execute_block. |
4067 |
|
|
4068 |
|
*/ |
4069 |
|
|
4070 |
7 |
int Interp::convert_speed(block_pointer block, //!< pointer to a block of RS274 instructions |
4071 |
|
setup_pointer settings) //!< pointer to machine settings |
4072 |
|
{ |
4073 |
7 |
enqueue_SET_SPINDLE_SPEED(block->s_number); |
4074 |
7 |
settings->speed = block->s_number; |
4075 |
7 |
return INTERP_OK; |
4076 |
|
} |
4077 |
|
|
4078 |
|
int Interp::convert_spindle_mode(block_pointer block, setup_pointer settings) |
4079 |
|
{ |
4080 |
|
if(block->g_modes[14] == G_97) { |
4081 |
|
settings->spindle_mode = CONSTANT_RPM; |
4082 |
|
enqueue_SET_SPINDLE_MODE(0); |
4083 |
|
} else { /* G_96 */ |
4084 |
|
settings->spindle_mode = CONSTANT_SURFACE; |
4085 |
|
if(block->d_flag) |
4086 |
|
enqueue_SET_SPINDLE_MODE(fabs(block->d_number_float)); |
4087 |
|
else |
4088 |
|
enqueue_SET_SPINDLE_MODE(1e30); |
4089 |
|
} |
4090 |
|
return INTERP_OK; |
4091 |
|
} |
4092 |
|
/****************************************************************************/ |
4093 |
|
|
4094 |
|
/*! convert_stop |
4095 |
|
|
4096 |
|
Returned Value: int |
4097 |
|
When an m2 or m30 (program_end) is encountered, this returns INTERP_EXIT. |
4098 |
|
If the code is not m0, m1, m2, m30, or m60, this returns |
4099 |
|
NCE_BUG_CODE_NOT_M0_M1_M2_M30_M60 |
4100 |
|
Otherwise, it returns INTERP_OK. |
4101 |
|
|
4102 |
|
Side effects: |
4103 |
|
An m0, m1, m2, m30, or m60 in the block is executed. |
4104 |
|
|
4105 |
|
For m0, m1, and m60, this makes a function call to the PROGRAM_STOP |
4106 |
|
canonical machining function (which stops program execution). |
4107 |
|
In addition, m60 calls PALLET_SHUTTLE. |
4108 |
|
|
4109 |
|
For m2 and m30, this resets the machine and then calls PROGRAM_END. |
4110 |
|
In addition, m30 calls PALLET_SHUTTLE. |
4111 |
|
Clear g92 offset if DISABLE_G92_PERSISTENCE is set in the .ini file. |
4112 |
|
|
4113 |
|
Called by: execute_block. |
4114 |
|
|
4115 |
|
This handles stopping or ending the program (m0, m1, m2, m30, m60) |
4116 |
|
|
4117 |
|
[NCMS] specifies how the following modes should be reset at m2 or |
4118 |
|
m30. The descriptions are not collected in one place, so this list |
4119 |
|
may be incomplete. |
4120 |
|
|
4121 |
|
G52 offsetting coordinate zero points [NCMS, page 10] |
4122 |
|
G92 coordinate offset using tool position [NCMS, page 10] |
4123 |
|
|
4124 |
|
The following should have reset values, but no description of reset |
4125 |
|
behavior could be found in [NCMS]. |
4126 |
|
G17, G18, G19 selected plane [NCMS, pages 14, 20] |
4127 |
|
G90, G91 distance mode [NCMS, page 15] |
4128 |
|
G93, G94 feed mode [NCMS, pages 35 - 37] |
4129 |
|
M48, M49 overrides enabled, disabled [NCMS, pages 37 - 38] |
4130 |
|
M3, M4, M5 spindle turning [NCMS, page 7] |
4131 |
|
|
4132 |
|
The following should be set to some value at machine start-up but |
4133 |
|
not automatically reset by any of the stopping codes. |
4134 |
|
1. G20, G21 length units [NCMS, page 15]. This is up to the installer. |
4135 |
|
2. motion_control_mode. This is set in Interp::init but not reset here. |
4136 |
|
Might add it here. |
4137 |
|
|
4138 |
|
The following resets have been added by calling the appropriate |
4139 |
|
canonical machining command and/or by resetting interpreter |
4140 |
|
settings. They occur on M2 or M30. |
4141 |
|
|
4142 |
|
1. origin offsets are set to the default (like G54) |
4143 |
|
2. Selected plane is set to CANON_PLANE_XY (like G17) - SELECT_PLANE |
4144 |
|
3. Distance mode is set to MODE_ABSOLUTE (like G90) - no canonical call |
4145 |
|
4. Feed mode is set to UNITS_PER_MINUTE (like G94) - no canonical call |
4146 |
|
5. Feed and speed overrides are set to true (like M48) - ENABLE_FEED_OVERRIDE |
4147 |
|
- ENABLE_SPEED_OVERRIDE |
4148 |
|
6. Cutter compensation is turned off (like G40) - no canonical call |
4149 |
|
7. The spindle is stopped (like M5) - STOP_SPINDLE_TURNING |
4150 |
|
8. The motion mode is set to G_1 (like G1) - no canonical call |
4151 |
|
9. Coolant is turned off (like M9) - FLOOD_OFF & MIST_OFF |
4152 |
|
10. G52/G92 is cleared if DISABLE_G92_PERSISTENCE is set in the .ini file |
4153 |
|
|
4154 |
|
*/ |
4155 |
|
|
4156 |
43 |
int Interp::convert_stop(block_pointer block, //!< pointer to a block of RS274/NGC instructions |
4157 |
|
setup_pointer settings) //!< pointer to machine settings |
4158 |
|
{ |
4159 |
|
int index; |
4160 |
|
char *line; |
4161 |
|
int length; |
4162 |
|
|
4163 |
|
double cx, cy, cz; |
4164 |
43 |
comp_get_current(settings, &cx, &cy, &cz); |
4165 |
43 |
CHP(move_endpoint_and_flush(settings, cx, cy)); |
4166 |
43 |
dequeue_canons(settings); |
4167 |
|
|
4168 |
43 |
if (block->m_modes[4] == 0) { |
4169 |
2 |
PROGRAM_STOP(); |
4170 |
41 |
} else if (block->m_modes[4] == 60) { |
4171 |
|
PALLET_SHUTTLE(); |
4172 |
|
PROGRAM_STOP(); |
4173 |
41 |
} else if (block->m_modes[4] == 1) { |
4174 |
|
OPTIONAL_PROGRAM_STOP(); |
4175 |
41 |
} else if ((block->m_modes[4] == 2) || (block->m_modes[4] == 30)) { /* reset stuff here */ |
4176 |
41 |
program_end_cleanup(settings); |
4177 |
41 |
if (block->m_modes[4] == 30) |
4178 |
5 |
PALLET_SHUTTLE(); |
4179 |
41 |
PROGRAM_END(); |
4180 |
41 |
if (_setup.percent_flag && _setup.file_pointer) { |
4181 |
2 |
line = _setup.linetext; |
4182 |
|
for (;;) { /* check for ending percent sign and comment if missing */ |
4183 |
6 |
if (fgets(line, LINELEN, _setup.file_pointer) == NULL) { |
4184 |
|
enqueue_COMMENT("interpreter: percent sign missing from end of file"); |
4185 |
|
break; |
4186 |
|
} |
4187 |
6 |
length = strlen(line); |
4188 |
6 |
if (length == (LINELEN - 1)) { // line is too long. need to finish reading the line |
4189 |
|
for (; fgetc(_setup.file_pointer) != '\n';); |
4190 |
|
continue; |
4191 |
|
} |
4192 |
6 |
for (index = (length - 1); // index set on last char |
4193 |
11 |
(index >= 0) && (isspace(line[index])); index--); |
4194 |
6 |
if (line[index] == '%') // found line with % at end |
4195 |
|
{ |
4196 |
2 |
for (index--; (index >= 0) && (isspace(line[index])); index--); |
4197 |
2 |
if (index == -1) // found line with only percent sign |
4198 |
|
break; |
4199 |
|
} |
4200 |
|
} |
4201 |
|
} |
4202 |
41 |
unwind_call(INTERP_EXIT, __FILE__,__LINE__,__FUNCTION__); |
4203 |
|
return INTERP_EXIT; |
4204 |
|
} else |
4205 |
|
ERS(NCE_BUG_CODE_NOT_M0_M1_M2_M30_M60); |
4206 |
|
return INTERP_OK; |
4207 |
|
} |
4208 |
|
|
4209 |
|
/*************************************************************************** */ |
4210 |
|
|
4211 |
|
/*! convert_straight |
4212 |
|
|
4213 |
|
Returned Value: int |
4214 |
|
If convert_straight_comp1 or convert_straight_comp2 is called |
4215 |
|
and returns an error code, this returns that code. |
4216 |
|
If any of the following errors occur, this returns the error shown. |
4217 |
|
Otherwise, it returns INTERP_OK. |
4218 |
|
1. The value of move is not G_0 or G_1: |
4219 |
|
NCE_BUG_CODE_NOT_G0_OR_G1 |
4220 |
|
2. A straight feed (g1) move is called with feed rate set to 0: |
4221 |
|
NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE |
4222 |
|
3. A straight feed (g1) move is called with inverse time feed in effect |
4223 |
|
but no f word (feed time) is provided: |
4224 |
|
NCE_F_WORD_MISSING_WITH_INVERSE_TIME_G1_MOVE |
4225 |
|
4. A move is called with G53 and cutter radius compensation on: |
4226 |
|
NCE_CANNOT_USE_G53_WITH_CUTTER_RADIUS_COMP |
4227 |
|
5. A G33 move is called without the necessary support compiled in: |
4228 |
|
NCE_G33_NOT_SUPPORTED |
4229 |
|
|
4230 |
|
Side effects: |
4231 |
|
This executes a STRAIGHT_FEED command at cutting feed rate |
4232 |
|
(if move is G_1) or a STRAIGHT_TRAVERSE command (if move is G_0). |
4233 |
|
It also updates the setting of the position of the tool point to the |
4234 |
|
end point of the move. If cutter radius compensation is on, it may |
4235 |
|
also generate an arc before the straight move. Also, in INVERSE_TIME |
4236 |
|
feed mode, SET_FEED_RATE will be called the feed rate setting changed. |
4237 |
|
|
4238 |
|
Called by: convert_motion. |
4239 |
|
|
4240 |
|
The approach to operating in incremental distance mode (g91) is to |
4241 |
|
put the the absolute position values into the block before using the |
4242 |
|
block to generate a move. |
4243 |
|
|
4244 |
|
In inverse time feed mode, a lower bound of 0.1 is placed on the feed |
4245 |
|
rate so that the feed rate is never set to zero. If the destination |
4246 |
|
point is the same as the current point, the feed rate would be |
4247 |
|
calculated as zero otherwise. |
4248 |
|
|
4249 |
|
If cutter compensation is in use, the path's length may increase or |
4250 |
|
decrease. Also an arc may be added, to go around a corner, before the |
4251 |
|
straight move. For the purpose of calculating the feed rate when in |
4252 |
|
inverse time mode, this length increase or decrease is ignored. The |
4253 |
|
feed is still set to the original programmed straight length divided by |
4254 |
|
the F number (with the above lower bound). The new arc (if needed) and |
4255 |
|
the new longer or shorter straight move are taken at this feed. |
4256 |
|
|
4257 |
|
*/ |
4258 |
|
|
4259 |
880 |
int Interp::convert_straight(int move, //!< either G_0 or G_1 |
4260 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
4261 |
|
setup_pointer settings) //!< pointer to machine settings |
4262 |
|
{ |
4263 |
|
double end_x; |
4264 |
|
double end_y; |
4265 |
|
double end_z; |
4266 |
|
double AA_end; |
4267 |
|
double BB_end; |
4268 |
|
double CC_end; |
4269 |
|
double u_end, v_end, w_end; |
4270 |
|
int status; |
4271 |
|
|
4272 |
880 |
settings->arc_not_allowed = false; |
4273 |
|
|
4274 |
880 |
if (move == G_1) { |
4275 |
720 |
if (settings->feed_mode == UNITS_PER_MINUTE) { |
4276 |
708 |
CHKS((settings->feed_rate == 0.0), NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE); |
4277 |
12 |
} else if (settings->feed_mode == UNITS_PER_REVOLUTION) { |
4278 |
|
CHKS((settings->feed_rate == 0.0), NCE_CANNOT_DO_G1_WITH_ZERO_FEED_RATE); |
4279 |
|
CHKS((settings->speed == 0.0), _("Cannot feed with zero spindle speed in feed per rev mode")); |
4280 |
12 |
} else if (settings->feed_mode == INVERSE_TIME) { |
4281 |
12 |
CHKS((!block->f_flag), |
4282 |
|
NCE_F_WORD_MISSING_WITH_INVERSE_TIME_G1_MOVE); |
4283 |
|
} |
4284 |
|
} |
4285 |
|
|
4286 |
879 |
settings->motion_mode = move; |
4287 |
879 |
CHP(find_ends(block, settings, &end_x, &end_y, &end_z, |
4288 |
|
&AA_end, &BB_end, &CC_end, &u_end, &v_end, &w_end)); |
4289 |
|
|
4290 |
879 |
if (move == G_1) { |
4291 |
|
inverse_time_rate_straight(end_x, end_y, end_z, |
4292 |
|
AA_end, BB_end, CC_end, |
4293 |
|
u_end, v_end, w_end, |
4294 |
719 |
block, settings); |
4295 |
|
} |
4296 |
|
|
4297 |
1229 |
if ((settings->cutter_comp_side) && /* ! "== true" */ |
4298 |
350 |
(settings->cutter_comp_radius > 0.0)) { /* radius always is >= 0 */ |
4299 |
|
|
4300 |
310 |
CHKS((block->g_modes[0] == G_53), |
4301 |
|
NCE_CANNOT_USE_G53_WITH_CUTTER_RADIUS_COMP); |
4302 |
|
|
4303 |
310 |
if(settings->plane == CANON_PLANE_XZ) { |
4304 |
32 |
if (settings->cutter_comp_firstmove) |
4305 |
|
status = convert_straight_comp1(move, block, settings, end_z, end_x, end_y, |
4306 |
2 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4307 |
|
else |
4308 |
|
status = convert_straight_comp2(move, block, settings, end_z, end_x, end_y, |
4309 |
30 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4310 |
278 |
} else if(settings->plane == CANON_PLANE_XY) { |
4311 |
278 |
if (settings->cutter_comp_firstmove) |
4312 |
|
status = convert_straight_comp1(move, block, settings, end_x, end_y, end_z, |
4313 |
57 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4314 |
|
else |
4315 |
|
status = convert_straight_comp2(move, block, settings, end_x, end_y, end_z, |
4316 |
221 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4317 |
|
} else ERS("BUG: Invalid plane for cutter compensation"); |
4318 |
310 |
CHP(status); |
4319 |
569 |
} else if (move == G_0) { |
4320 |
|
STRAIGHT_TRAVERSE(block->line_number, end_x, end_y, end_z, |
4321 |
|
AA_end, BB_end, CC_end, |
4322 |
156 |
u_end, v_end, w_end); |
4323 |
156 |
settings->current_x = end_x; |
4324 |
156 |
settings->current_y = end_y; |
4325 |
156 |
settings->current_z = end_z; |
4326 |
413 |
} else if (move == G_1) { |
4327 |
|
STRAIGHT_FEED(block->line_number, end_x, end_y, end_z, |
4328 |
|
AA_end, BB_end, CC_end, |
4329 |
412 |
u_end, v_end, w_end); |
4330 |
412 |
settings->current_x = end_x; |
4331 |
412 |
settings->current_y = end_y; |
4332 |
412 |
settings->current_z = end_z; |
4333 |
1 |
} else if (move == G_33) { |
4334 |
|
CHKS(((settings->spindle_turning != CANON_CLOCKWISE) && |
4335 |
|
(settings->spindle_turning != CANON_COUNTERCLOCKWISE)), |
4336 |
|
_("Spindle not turning in G33")); |
4337 |
|
START_SPEED_FEED_SYNCH(block->k_number, 0); |
4338 |
|
STRAIGHT_FEED(block->line_number, end_x, end_y, end_z, AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4339 |
|
STOP_SPEED_FEED_SYNCH(); |
4340 |
|
settings->current_x = end_x; |
4341 |
|
settings->current_y = end_y; |
4342 |
|
settings->current_z = end_z; |
4343 |
1 |
} else if (move == G_33_1) { |
4344 |
|
CHKS(((settings->spindle_turning != CANON_CLOCKWISE) && |
4345 |
|
(settings->spindle_turning != CANON_COUNTERCLOCKWISE)), |
4346 |
|
_("Spindle not turning in G33.1")); |
4347 |
|
START_SPEED_FEED_SYNCH(block->k_number, 0); |
4348 |
|
RIGID_TAP(block->line_number, end_x, end_y, end_z); |
4349 |
|
STOP_SPEED_FEED_SYNCH(); |
4350 |
|
// after the RIGID_TAP cycle we'll be in the same spot |
4351 |
1 |
} else if (move == G_76) { |
4352 |
1 |
CHKS(((settings->spindle_turning != CANON_CLOCKWISE) && |
4353 |
|
(settings->spindle_turning != CANON_COUNTERCLOCKWISE)), |
4354 |
|
_("Spindle not turning in G76")); |
4355 |
1 |
CHKS((settings->AA_current != AA_end || |
4356 |
|
settings->BB_current != BB_end || |
4357 |
|
settings->CC_current != CC_end || |
4358 |
|
settings->u_current != u_end || |
4359 |
|
settings->v_current != v_end || |
4360 |
|
settings->w_current != w_end), NCE_CANNOT_MOVE_ROTARY_AXES_WITH_G76); |
4361 |
1 |
int result = convert_threading_cycle(block, settings, end_x, end_y, end_z); |
4362 |
1 |
if(result != INTERP_OK) return result; |
4363 |
|
} else |
4364 |
|
ERS(NCE_BUG_CODE_NOT_G0_OR_G1); |
4365 |
|
|
4366 |
878 |
settings->AA_current = AA_end; |
4367 |
878 |
settings->BB_current = BB_end; |
4368 |
878 |
settings->CC_current = CC_end; |
4369 |
878 |
settings->u_current = u_end; |
4370 |
878 |
settings->v_current = v_end; |
4371 |
878 |
settings->w_current = w_end; |
4372 |
878 |
return INTERP_OK; |
4373 |
|
} |
4374 |
|
|
4375 |
|
int Interp::convert_straight_indexer(int axis, int jnum, block_pointer block, setup_pointer settings) { |
4376 |
|
double end_x, end_y, end_z; |
4377 |
|
double AA_end, BB_end, CC_end; |
4378 |
|
double u_end, v_end, w_end; |
4379 |
|
|
4380 |
|
find_ends(block, settings, &end_x, &end_y, &end_z, |
4381 |
|
&AA_end, &BB_end, &CC_end, &u_end, &v_end, &w_end); |
4382 |
|
|
4383 |
|
CHKS((end_x != settings->current_x || |
4384 |
|
end_y != settings->current_y || |
4385 |
|
end_z != settings->current_z || |
4386 |
|
u_end != settings->u_current || |
4387 |
|
v_end != settings->v_current || |
4388 |
|
w_end != settings->w_current || |
4389 |
|
(axis != 3 && AA_end != settings->AA_current) || |
4390 |
|
(axis != 4 && BB_end != settings->BB_current) || |
4391 |
|
(axis != 5 && CC_end != settings->CC_current)), |
4392 |
|
_("BUG: An axis incorrectly moved along with an indexer")); |
4393 |
|
|
4394 |
|
switch(axis) { |
4395 |
|
case 3: |
4396 |
|
issue_straight_index(axis, jnum, AA_end, block->line_number, settings); |
4397 |
|
break; |
4398 |
|
case 4: |
4399 |
|
issue_straight_index(axis, jnum, BB_end, block->line_number, settings); |
4400 |
|
break; |
4401 |
|
case 5: |
4402 |
|
issue_straight_index(axis, jnum, CC_end, block->line_number, settings); |
4403 |
|
break; |
4404 |
|
default: |
4405 |
|
ERS((_("BUG: trying to index incorrect axis"))); |
4406 |
|
} |
4407 |
|
return INTERP_OK; |
4408 |
|
} |
4409 |
|
|
4410 |
|
int Interp::issue_straight_index(int axis, int jnum, double target, int lineno, setup_pointer settings) { |
4411 |
|
CANON_MOTION_MODE save_mode; |
4412 |
|
double save_tolerance; |
4413 |
|
// temporarily switch to exact stop mode for indexing move |
4414 |
|
save_mode = GET_EXTERNAL_MOTION_CONTROL_MODE(); |
4415 |
|
save_tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE(); |
4416 |
|
if (save_mode != CANON_EXACT_PATH) |
4417 |
|
SET_MOTION_CONTROL_MODE(CANON_EXACT_PATH, 0); |
4418 |
|
|
4419 |
|
double AA_end = axis == 3? target: settings->AA_current; |
4420 |
|
double BB_end = axis == 4? target: settings->BB_current; |
4421 |
|
double CC_end = axis == 5? target: settings->CC_current; |
4422 |
|
|
4423 |
|
// tell canon that this is a special indexing move |
4424 |
|
UNLOCK_ROTARY(lineno, jnum); |
4425 |
|
STRAIGHT_TRAVERSE(lineno, settings->current_x, settings->current_y, settings->current_z, |
4426 |
|
AA_end, BB_end, CC_end, |
4427 |
|
settings->u_current, settings->v_current, settings->w_current); |
4428 |
|
LOCK_ROTARY(lineno, jnum); |
4429 |
|
|
4430 |
|
// restore path mode |
4431 |
|
if(save_mode != CANON_EXACT_PATH) |
4432 |
|
SET_MOTION_CONTROL_MODE(save_mode, save_tolerance); |
4433 |
|
|
4434 |
|
settings->AA_current = AA_end; |
4435 |
|
settings->BB_current = BB_end; |
4436 |
|
settings->CC_current = CC_end; |
4437 |
|
return INTERP_OK; |
4438 |
|
} |
4439 |
|
|
4440 |
|
|
4441 |
|
#define AABBCC settings->AA_current, settings->BB_current, settings->CC_current, settings->u_current, settings->v_current, settings->w_current |
4442 |
|
|
4443 |
|
// make one threading pass. only called from convert_threading_cycle. |
4444 |
|
static void |
4445 |
35 |
threading_pass(setup_pointer settings, block_pointer block, |
4446 |
|
int boring, double safe_x, double depth, double end_depth, |
4447 |
|
double start_y, double start_z, double zoff, double taper_dist, |
4448 |
|
int entry_taper, int exit_taper, double taper_pitch, |
4449 |
|
double pitch, double full_threadheight, double target_z) { |
4450 |
|
STRAIGHT_TRAVERSE(block->line_number, boring? |
4451 |
|
safe_x + depth - end_depth: |
4452 |
35 |
safe_x - depth + end_depth, |
4453 |
70 |
start_y, start_z - zoff, AABBCC); //back |
4454 |
35 |
if(taper_dist && entry_taper) { |
4455 |
|
DISABLE_FEED_OVERRIDE(); |
4456 |
|
START_SPEED_FEED_SYNCH(taper_pitch, 0); |
4457 |
|
STRAIGHT_FEED(block->line_number, boring? |
4458 |
|
safe_x + depth - full_threadheight: |
4459 |
|
safe_x - depth + full_threadheight, |
4460 |
|
start_y, start_z - zoff, AABBCC); //in |
4461 |
|
STRAIGHT_FEED(block->line_number, boring? safe_x + depth: safe_x - depth, //angled in |
4462 |
|
start_y, start_z - zoff - taper_dist, AABBCC); |
4463 |
|
START_SPEED_FEED_SYNCH(pitch, 0); |
4464 |
|
} else { |
4465 |
|
STRAIGHT_TRAVERSE(block->line_number, boring? safe_x + depth: safe_x - depth, |
4466 |
35 |
start_y, start_z - zoff, AABBCC); //in |
4467 |
35 |
DISABLE_FEED_OVERRIDE(); |
4468 |
35 |
START_SPEED_FEED_SYNCH(pitch, 0); |
4469 |
|
} |
4470 |
|
|
4471 |
35 |
if(taper_dist && exit_taper) { |
4472 |
|
STRAIGHT_FEED(block->line_number, boring? safe_x + depth: safe_x - depth, //over |
4473 |
35 |
start_y, target_z - zoff + taper_dist, AABBCC); |
4474 |
35 |
START_SPEED_FEED_SYNCH(taper_pitch, 0); |
4475 |
|
STRAIGHT_FEED(block->line_number, boring? |
4476 |
|
safe_x + depth - full_threadheight: |
4477 |
35 |
safe_x - depth + full_threadheight, |
4478 |
70 |
start_y, target_z - zoff, AABBCC); //angled out |
4479 |
|
} else { |
4480 |
|
STRAIGHT_FEED(block->line_number, boring? safe_x + depth: safe_x - depth, |
4481 |
|
start_y, target_z - zoff, AABBCC); //over |
4482 |
|
} |
4483 |
35 |
STOP_SPEED_FEED_SYNCH(); |
4484 |
|
STRAIGHT_TRAVERSE(block->line_number, boring? |
4485 |
|
safe_x + depth - end_depth: |
4486 |
35 |
safe_x - depth + end_depth, |
4487 |
70 |
start_y, target_z - zoff, AABBCC); //out |
4488 |
35 |
ENABLE_FEED_OVERRIDE(); |
4489 |
35 |
} |
4490 |
|
|
4491 |
1 |
int Interp::convert_threading_cycle(block_pointer block, |
4492 |
|
setup_pointer settings, |
4493 |
|
double end_x, double end_y, double end_z) { |
4494 |
|
|
4495 |
|
|
4496 |
1 |
CHKS((settings->cutter_comp_side), |
4497 |
|
(_("Cannot use G76 threading cycle with cutter radius compensation on"))); |
4498 |
|
|
4499 |
1 |
CHKS((block->i_number == 0), |
4500 |
|
(_("In G76, I must not be 0"))); |
4501 |
1 |
CHKS((block->j_number <= 0), |
4502 |
|
(_("In G76, J must be greater than 0"))); |
4503 |
1 |
CHKS((block->k_number <= block->j_number), |
4504 |
|
(_("In G76, K must be greater than J"))); |
4505 |
|
|
4506 |
1 |
double start_x = settings->current_x; |
4507 |
1 |
double start_y = settings->current_y; |
4508 |
1 |
double start_z = settings->current_z; |
4509 |
|
|
4510 |
1 |
double i_number = block->i_number; |
4511 |
1 |
double j_number = block->j_number; |
4512 |
1 |
double k_number = block->k_number; |
4513 |
|
|
4514 |
1 |
if(_setup.lathe_diameter_mode){ |
4515 |
|
i_number /= 2; |
4516 |
|
j_number /= 2; |
4517 |
|
k_number /= 2; |
4518 |
|
} |
4519 |
|
|
4520 |
|
|
4521 |
1 |
int boring = 0; |
4522 |
|
|
4523 |
1 |
if (i_number > 0.0) |
4524 |
|
boring = 1; |
4525 |
|
|
4526 |
1 |
double safe_x = start_x; |
4527 |
1 |
double full_dia_depth = fabs(i_number); |
4528 |
1 |
double start_depth = fabs(i_number) + fabs(j_number); |
4529 |
1 |
double cut_increment = fabs(j_number); |
4530 |
1 |
double full_threadheight = fabs(k_number); |
4531 |
1 |
double end_depth = fabs(k_number) + fabs(i_number); |
4532 |
|
|
4533 |
1 |
double pitch = block->p_number; |
4534 |
1 |
double compound_angle = block->q_number; |
4535 |
1 |
if(compound_angle == -1) compound_angle = 0; |
4536 |
1 |
compound_angle *= M_PIl/180.0; |
4537 |
1 |
if(end_z > start_z) compound_angle = -compound_angle; |
4538 |
|
|
4539 |
1 |
int spring_cuts = block->h_flag ? block->h_number: 0; |
4540 |
|
|
4541 |
1 |
double degression = block->r_number; |
4542 |
1 |
if(degression < 1.0 || !block->r_flag) degression = 1.0; |
4543 |
|
|
4544 |
1 |
double taper_dist = block->e_flag? block->e_number: 0.0; |
4545 |
1 |
if(taper_dist < 0.0) taper_dist = 0.0; |
4546 |
|
double taper_pitch = taper_dist > 0.0? |
4547 |
1 |
pitch * hypot(taper_dist, full_threadheight)/taper_dist: pitch; |
4548 |
|
|
4549 |
1 |
if(end_z > start_z) taper_dist = -taper_dist; |
4550 |
|
|
4551 |
1 |
int taper_flags = block->l_number; |
4552 |
1 |
if(taper_flags < 0) taper_flags = 0; |
4553 |
|
|
4554 |
1 |
int entry_taper = taper_flags & 1; |
4555 |
1 |
int exit_taper = taper_flags & 2; |
4556 |
|
|
4557 |
|
double depth, zoff; |
4558 |
1 |
int pass = 1; |
4559 |
|
|
4560 |
1 |
double target_z = end_z + fabs(k_number) * tan(compound_angle); |
4561 |
|
|
4562 |
1 |
depth = start_depth; |
4563 |
1 |
zoff = (depth - full_dia_depth) * tan(compound_angle); |
4564 |
33 |
while (depth < end_depth) { |
4565 |
|
threading_pass(settings, block, boring, safe_x, depth, end_depth, start_y, |
4566 |
|
start_z, zoff, taper_dist, entry_taper, exit_taper, |
4567 |
31 |
taper_pitch, pitch, full_threadheight, target_z); |
4568 |
31 |
depth = full_dia_depth + cut_increment * pow(++pass, 1.0/degression); |
4569 |
31 |
zoff = (depth - full_dia_depth) * tan(compound_angle); |
4570 |
|
} |
4571 |
|
// full specified depth now |
4572 |
1 |
depth = end_depth; |
4573 |
1 |
zoff = (depth - full_dia_depth) * tan(compound_angle); |
4574 |
|
// cut at least once -- more if spring cuts. |
4575 |
5 |
for(int i = 0; i<spring_cuts+1; i++) { |
4576 |
|
threading_pass(settings, block, boring, safe_x, depth, end_depth, start_y, |
4577 |
|
start_z, zoff, taper_dist, entry_taper, exit_taper, |
4578 |
4 |
taper_pitch, pitch, full_threadheight, target_z); |
4579 |
|
} |
4580 |
1 |
STRAIGHT_TRAVERSE(block->line_number, end_x, end_y, end_z, AABBCC); |
4581 |
1 |
settings->current_x = end_x; |
4582 |
1 |
settings->current_y = end_y; |
4583 |
1 |
settings->current_z = end_z; |
4584 |
|
#undef AABBC |
4585 |
1 |
return INTERP_OK; |
4586 |
|
} |
4587 |
|
|
4588 |
|
|
4589 |
|
/****************************************************************************/ |
4590 |
|
|
4591 |
|
/*! convert_straight_comp1 |
4592 |
|
|
4593 |
|
Returned Value: int |
4594 |
|
If any of the following errors occur, this returns the error shown. |
4595 |
|
Otherwise, it returns INTERP_OK. |
4596 |
|
1. The side is not RIGHT or LEFT: |
4597 |
|
NCE_BUG_SIDE_NOT_RIGHT_OR_LEFT |
4598 |
|
2. The destination tangent point is not more than a tool radius |
4599 |
|
away (indicating gouging): NCE_CUTTER_GOUGING_WITH_CUTTER_RADIUS_COMP |
4600 |
|
3. The value of move is not G_0 or G_1 |
4601 |
|
NCE_BUG_CODE_NOT_G0_OR_G1 |
4602 |
|
|
4603 |
|
Side effects: |
4604 |
|
This executes a STRAIGHT_MOVE command at cutting feed rate |
4605 |
|
or a STRAIGHT_TRAVERSE command. |
4606 |
|
It also updates the setting of the position of the tool point |
4607 |
|
to the end point of the move and updates the programmed point. |
4608 |
|
|
4609 |
|
Called by: convert_straight. |
4610 |
|
|
4611 |
|
This is called if cutter radius compensation is on and |
4612 |
|
settings->cutter_comp_firstmove is true, indicating that this is the |
4613 |
|
first move after cutter radius compensation is turned on. |
4614 |
|
|
4615 |
|
The algorithm used here for determining the path is to draw a straight |
4616 |
|
line from the destination point which is tangent to a circle whose |
4617 |
|
center is at the current point and whose radius is the radius of the |
4618 |
|
cutter. The destination point of the cutter tip is then found as the |
4619 |
|
center of a circle of the same radius tangent to the tangent line at |
4620 |
|
the destination point. |
4621 |
|
|
4622 |
|
*/ |
4623 |
|
|
4624 |
59 |
int Interp::convert_straight_comp1(int move, //!< either G_0 or G_1 |
4625 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
4626 |
|
setup_pointer settings, //!< pointer to machine settings |
4627 |
|
double px, //!< X coordinate of end point |
4628 |
|
double py, //!< Y coordinate of end point |
4629 |
|
double pz, //!< Z coordinate of end point |
4630 |
|
double AA_end, //!< A coordinate of end point |
4631 |
|
double BB_end, //!< B coordinate of end point |
4632 |
|
double CC_end, //!< C coordinate of end point |
4633 |
|
double u_end, double v_end, double w_end) |
4634 |
|
{ |
4635 |
|
double alpha; |
4636 |
|
double distance; |
4637 |
59 |
double radius = settings->cutter_comp_radius; /* always will be positive */ |
4638 |
|
double end_x, end_y; |
4639 |
|
|
4640 |
59 |
int side = settings->cutter_comp_side; |
4641 |
|
double cx, cy, cz; |
4642 |
|
|
4643 |
59 |
comp_get_current(settings, &cx, &cy, &cz); |
4644 |
59 |
distance = hypot((px - cx), (py - cy)); |
4645 |
|
|
4646 |
59 |
CHKS(((side != LEFT) && (side != RIGHT)), NCE_BUG_SIDE_NOT_RIGHT_OR_LEFT); |
4647 |
59 |
CHKS((distance <= radius), _("Length of cutter compensation entry move is not greater than the tool radius")); |
4648 |
|
|
4649 |
59 |
alpha = atan2(py - cy, px - cx) + (side == LEFT ? M_PIl/2. : -M_PIl/2.); |
4650 |
|
|
4651 |
59 |
end_x = (px + (radius * cos(alpha))); |
4652 |
59 |
end_y = (py + (radius * sin(alpha))); |
4653 |
|
|
4654 |
|
// with these moves we don't need to record the direction vector. |
4655 |
|
// they cannot get reversed because they are guaranteed to be long |
4656 |
|
// enough. |
4657 |
|
|
4658 |
59 |
set_endpoint(cx, cy); |
4659 |
|
|
4660 |
59 |
if (move == G_0) { |
4661 |
|
enqueue_STRAIGHT_TRAVERSE(settings, block->line_number, |
4662 |
|
cos(alpha), sin(alpha), 0, |
4663 |
|
end_x, end_y, pz, |
4664 |
|
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4665 |
|
} |
4666 |
59 |
else if (move == G_1) { |
4667 |
|
enqueue_STRAIGHT_FEED(settings, block->line_number, |
4668 |
|
cos(alpha), sin(alpha), 0, |
4669 |
|
end_x, end_y, pz, |
4670 |
59 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4671 |
|
} else |
4672 |
|
ERS(NCE_BUG_CODE_NOT_G0_OR_G1); |
4673 |
|
|
4674 |
59 |
settings->cutter_comp_firstmove = false; |
4675 |
|
|
4676 |
59 |
comp_set_current(settings, end_x, end_y, pz); |
4677 |
59 |
settings->AA_current = AA_end; |
4678 |
59 |
settings->BB_current = BB_end; |
4679 |
59 |
settings->CC_current = CC_end; |
4680 |
59 |
settings->u_current = u_end; |
4681 |
59 |
settings->v_current = v_end; |
4682 |
59 |
settings->w_current = w_end; |
4683 |
59 |
comp_set_programmed(settings, px, py, pz); |
4684 |
|
return INTERP_OK; |
4685 |
|
} |
4686 |
|
/****************************************************************************/ |
4687 |
|
|
4688 |
|
/*! convert_straight_comp2 |
4689 |
|
|
4690 |
|
Returned Value: int |
4691 |
|
If any of the following errors occur, this returns the error shown. |
4692 |
|
Otherwise, it returns INTERP_OK. |
4693 |
|
1. The compensation side is not RIGHT or LEFT: |
4694 |
|
NCE_BUG_SIDE_NOT_RIGHT_OR_LEFT |
4695 |
|
2. A concave corner is found: |
4696 |
|
NCE_CONCAVE_CORNER_WITH_CUTTER_RADIUS_COMP |
4697 |
|
|
4698 |
|
Side effects: |
4699 |
|
This executes a STRAIGHT_FEED command at cutting feed rate |
4700 |
|
or a STRAIGHT_TRAVERSE command. |
4701 |
|
It also generates an ARC_FEED to go around a corner, if necessary. |
4702 |
|
It also updates the setting of the position of the tool point to |
4703 |
|
the end point of the move and updates the programmed point. |
4704 |
|
|
4705 |
|
Called by: convert_straight. |
4706 |
|
|
4707 |
|
This is called if cutter radius compensation is on and |
4708 |
|
settings->cutter_comp_firstmove is not true, indicating that this is not |
4709 |
|
the first move after cutter radius compensation is turned on. |
4710 |
|
|
4711 |
|
The algorithm used here is: |
4712 |
|
1. Determine the direction of the last motion. This is done by finding |
4713 |
|
the direction of the line from the last programmed point to the |
4714 |
|
current tool tip location. This line is a radius of the tool and is |
4715 |
|
perpendicular to the direction of motion since the cutter is tangent |
4716 |
|
to that direction. |
4717 |
|
2. Determine the direction of the programmed motion. |
4718 |
|
3. If there is a convex corner, insert an arc to go around the corner. |
4719 |
|
4. Find the destination point for the tool tip. The tool will be |
4720 |
|
tangent to the line from the last programmed point to the present |
4721 |
|
programmed point at the present programmed point. |
4722 |
|
5. Go in a straight line from the current tool tip location to the |
4723 |
|
destination tool tip location. |
4724 |
|
|
4725 |
|
This uses an angle tolerance of TOLERANCE_CONCAVE_CORNER (0.01 radian) |
4726 |
|
to determine if: |
4727 |
|
1) an illegal concave corner exists (tool will not fit into corner), |
4728 |
|
2) no arc is required to go around the corner (i.e. the current line |
4729 |
|
is in the same direction as the end of the previous move), or |
4730 |
|
3) an arc is required to go around a convex corner and start off in |
4731 |
|
a new direction. |
4732 |
|
|
4733 |
|
If a rotary axis is moved in this block and an extra arc is required |
4734 |
|
to go around a sharp corner, all the rotary axis motion occurs on the |
4735 |
|
arc. An alternative might be to distribute the rotary axis motion |
4736 |
|
over the arc and the straight move in proportion to their lengths. |
4737 |
|
|
4738 |
|
If the Z-axis is moved in this block and an extra arc is required to |
4739 |
|
go around a sharp corner, all the Z-axis motion occurs on the straight |
4740 |
|
line and none on the extra arc. An alternative might be to distribute |
4741 |
|
the Z-axis motion over the extra arc and the straight line in |
4742 |
|
proportion to their lengths. |
4743 |
|
|
4744 |
|
This handles the case of there being no XY motion. |
4745 |
|
|
4746 |
|
This handles G0 moves. Where an arc is inserted to round a corner in a |
4747 |
|
G1 move, no arc is inserted for a G0 move; a STRAIGHT_TRAVERSE is made |
4748 |
|
from the current point to the end point. The end point for a G0 |
4749 |
|
move is the same as the end point for a G1 move, however. |
4750 |
|
|
4751 |
|
*/ |
4752 |
|
|
4753 |
251 |
int Interp::convert_straight_comp2(int move, //!< either G_0 or G_1 |
4754 |
|
block_pointer block, //!< pointer to a block of RS274 instructions |
4755 |
|
setup_pointer settings, //!< pointer to machine settings |
4756 |
|
double px, //!< X coordinate of programmed end point |
4757 |
|
double py, //!< Y coordinate of programmed end point |
4758 |
|
double pz, //!< Z coordinate of end point |
4759 |
|
double AA_end, //!< A coordinate of end point |
4760 |
|
double BB_end, //!< B coordinate of end point |
4761 |
|
double CC_end, //!< C coordinate of end point |
4762 |
|
double u_end, double v_end, double w_end) |
4763 |
|
{ |
4764 |
|
double alpha; |
4765 |
|
double beta; |
4766 |
|
double end_x, end_y, end_z; /* x-coordinate of actual end point */ |
4767 |
|
double gamma; |
4768 |
|
double mid_x, mid_y; /* x-coordinate of end of added arc, if needed */ |
4769 |
|
double radius; |
4770 |
|
int side; |
4771 |
251 |
double small = TOLERANCE_CONCAVE_CORNER; /* radians, testing corners */ |
4772 |
|
double opx, opy, opz; /* old programmed beginning point */ |
4773 |
|
double theta; |
4774 |
|
double cx, cy, cz; |
4775 |
|
int concave; |
4776 |
|
|
4777 |
251 |
comp_get_current(settings, &cx, &cy, &cz); |
4778 |
251 |
comp_get_current(settings, &end_x, &end_y, &end_z); |
4779 |
251 |
comp_get_programmed(settings, &opx, &opy, &opz); |
4780 |
|
|
4781 |
251 |
if ((py == opy) && (px == opx)) { /* no XY motion */ |
4782 |
17 |
if (move == G_0) { |
4783 |
|
enqueue_STRAIGHT_TRAVERSE(settings, block->line_number, |
4784 |
|
px - opx, py - opy, pz - opz, |
4785 |
|
cx, cy, pz, |
4786 |
3 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4787 |
14 |
} else if (move == G_1) { |
4788 |
|
enqueue_STRAIGHT_FEED(settings, block->line_number, |
4789 |
|
px - opx, py - opy, pz - opz, |
4790 |
14 |
cx, cy, pz, AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4791 |
|
} else |
4792 |
|
ERS(NCE_BUG_CODE_NOT_G0_OR_G1); |
4793 |
|
// end already filled out, above |
4794 |
|
} else { |
4795 |
|
// some XY motion |
4796 |
234 |
side = settings->cutter_comp_side; |
4797 |
234 |
radius = settings->cutter_comp_radius; /* will always be positive */ |
4798 |
234 |
theta = atan2(cy - opy, cx - opx); |
4799 |
234 |
alpha = atan2(py - opy, px - opx); |
4800 |
|
|
4801 |
234 |
if (side == LEFT) { |
4802 |
99 |
if (theta < alpha) |
4803 |
47 |
theta = (theta + (2 * M_PIl)); |
4804 |
99 |
beta = ((theta - alpha) - M_PI_2l); |
4805 |
99 |
gamma = M_PI_2l; |
4806 |
135 |
} else if (side == RIGHT) { |
4807 |
135 |
if (alpha < theta) |
4808 |
51 |
alpha = (alpha + (2 * M_PIl)); |
4809 |
135 |
beta = ((alpha - theta) - M_PI_2l); |
4810 |
135 |
gamma = -M_PI_2l; |
4811 |
|
} else |
4812 |
|
ERS(NCE_BUG_SIDE_NOT_RIGHT_OR_LEFT); |
4813 |
234 |
end_x = (px + (radius * cos(alpha + gamma))); |
4814 |
234 |
end_y = (py + (radius * sin(alpha + gamma))); |
4815 |
234 |
mid_x = (opx + (radius * cos(alpha + gamma))); |
4816 |
234 |
mid_y = (opy + (radius * sin(alpha + gamma))); |
4817 |
|
|
4818 |
234 |
if ((beta < -small) || (beta > (M_PIl + small))) { |
4819 |
|
concave = 1; |
4820 |
286 |
} else if (beta > (M_PIl - small) && |
4821 |
12 |
(!qc().empty() && qc().front().type == QARC_FEED && |
4822 |
4 |
((side == RIGHT && qc().front().data.arc_feed.turn > 0) || |
4823 |
4 |
(side == LEFT && qc().front().data.arc_feed.turn < 0)))) { |
4824 |
|
// this is an "h" shape, tool on right, going right to left |
4825 |
|
// over the hemispherical round part, then up next to the |
4826 |
|
// vertical part (or, the mirror case). there are two ways |
4827 |
|
// to stay to the "right", either loop down and around, or |
4828 |
|
// stay above and right. we're forcing above and right. |
4829 |
|
concave = 1; |
4830 |
|
} else { |
4831 |
139 |
concave = 0; |
4832 |
139 |
mid_x = (opx + (radius * cos(alpha + gamma))); |
4833 |
139 |
mid_y = (opy + (radius * sin(alpha + gamma))); |
4834 |
|
} |
4835 |
|
|
4836 |
234 |
if (!concave && (beta > small)) { /* ARC NEEDED */ |
4837 |
93 |
CHP(move_endpoint_and_flush(settings, cx, cy)); |
4838 |
93 |
if(move == G_1) { |
4839 |
|
enqueue_ARC_FEED(settings, block->line_number, |
4840 |
|
0.0, // doesn't matter, since we will not move this arc's endpoint |
4841 |
|
mid_x, mid_y, opx, opy, |
4842 |
|
((side == LEFT) ? -1 : 1), cz, |
4843 |
93 |
AA_end, BB_end, CC_end, u_end, v_end, w_end); |
4844 |
93 |
dequeue_canons(settings); |
4845 |
93 |
set_endpoint(mid_x, mid_y); |
4846 |
|
} else if(move == G_0) { |
4847 |
|
// we can't go around the corner because there is no |
4848 |
|
// arc traverse. but, if we do this anyway, at least |
4849 |
|
// most of our rapid will be parallel to the original |
4850 |
|
// programmed one. if nothing else, this will look a |
4851 |
|
// little less confusing in the preview. |
4852 |
|
enqueue_STRAIGHT_TRAVERSE(settings, block->line_number, |
4853 |
|
0.0, 0.0, 0.0, |
4854 |
|
mid_x, mid_y, cz, |
4855 |
|
AA_end, BB_end, CC_end, |
4856 |
|
u_end, v_end, w_end); |
4857 |
|
dequeue_canons(settings); |
4858 |
|
set_endpoint(mid_x, mid_y); |
4859 |
|
} else ERS(NCE_BUG_CODE_NOT_G0_OR_G1); |
4860 |
141 |
} else if (concave) { |
4861 |
190 |
if (qc().front().type != QARC_FEED) { |
4862 |
|
// line->line |
4863 |
|
double retreat; |
4864 |
|
// half the angle of the inside corner |
4865 |
70 |
double halfcorner = (beta + M_PIl) / 2.0; |
4866 |
70 |
CHKS((halfcorner == 0.0), (_("Zero degree inside corner is invalid for cutter compensation"))); |
4867 |
70 |
retreat = radius / tan(halfcorner); |
4868 |
|
// move back along the compensated path |
4869 |
|
// this should replace the endpoint of the previous move |
4870 |
70 |
mid_x = cx + retreat * cos(theta + gamma); |
4871 |
70 |
mid_y = cy + retreat * sin(theta + gamma); |
4872 |
|
// we actually want to move the previous line's endpoint here. That's the same as |
4873 |
|
// discarding that line and doing this one instead. |
4874 |
70 |
CHP(move_endpoint_and_flush(settings, mid_x, mid_y)); |
4875 |
|
} else { |
4876 |
|
// arc->line |
4877 |
|
// beware: the arc we saved is the compensated one. |
4878 |
50 |
arc_feed prev = qc().front().data.arc_feed; |
4879 |
25 |
double oldrad = hypot(prev.center2 - prev.end2, prev.center1 - prev.end1); |
4880 |
|
double oldrad_uncomp; |
4881 |
|
|
4882 |
|
// new line's direction |
4883 |
25 |
double base_dir = atan2(py - opy, px - opx); |
4884 |
|
double theta; |
4885 |
|
double phi; |
4886 |
|
|
4887 |
25 |
theta = (prev.turn > 0) ? base_dir + M_PI_2l : base_dir - M_PI_2l; |
4888 |
25 |
phi = atan2(prev.center2 - opy, prev.center1 - opx); |
4889 |
25 |
if TOOL_INSIDE_ARC(side, prev.turn) { |
4890 |
8 |
oldrad_uncomp = oldrad + radius; |
4891 |
|
} else { |
4892 |
17 |
oldrad_uncomp = oldrad - radius; |
4893 |
|
} |
4894 |
|
|
4895 |
25 |
double alpha = theta - phi; |
4896 |
|
// distance to old arc center perpendicular to the new line |
4897 |
25 |
double d = oldrad_uncomp * cos(alpha); |
4898 |
|
double d2; |
4899 |
|
double angle_from_center; |
4900 |
|
|
4901 |
25 |
if TOOL_INSIDE_ARC(side, prev.turn) { |
4902 |
8 |
d2 = d - radius; |
4903 |
8 |
double l = d2/oldrad; |
4904 |
8 |
CHKS((l > 1.0 || l < -1.0), _("Arc to straight motion makes a corner the compensated tool can't fit in without gouging")); |
4905 |
8 |
if(prev.turn > 0) |
4906 |
2 |
angle_from_center = - acos(l) + theta + M_PIl; |
4907 |
|
else |
4908 |
6 |
angle_from_center = acos(l) + theta + M_PIl; |
4909 |
|
} else { |
4910 |
17 |
d2 = d + radius; |
4911 |
17 |
double l = d2/oldrad; |
4912 |
17 |
CHKS((l > 1.0 || l < -1.0), _("Arc to straight motion makes a corner the compensated tool can't fit in without gouging")); |
4913 |
17 |
if(prev.turn > 0) |
4914 |
8 |
angle_from_center = acos(l) + theta + M_PIl; |
4915 |
|
else |
4916 |
9 |
angle_from_center = - acos(l) + theta + M_PIl; |
4917 |
|
} |
4918 |
25 |
mid_x = prev.center1 + oldrad * cos(angle_from_center); |
4919 |
25 |
mid_y = prev.center2 + oldrad * sin(angle_from_center); |
4920 |
25 |
CHP(move_endpoint_and_flush(settings, mid_x, mid_y)); |
4921 |
|
} |
4922 |
|
} else { |
4923 |
|
// no arc needed, also not concave (colinear lines or tangent arc->line) |
4924 |
46 |
dequeue_canons(settings); |
4925 |
46 |
set_endpoint(cx, cy); |
4926 |
|
} |
4927 |
|
(move == G_0? enqueue_STRAIGHT_TRAVERSE: enqueue_STRAIGHT_FEED) |
4928 |
|
(settings, block->line_number, |
4929 |
|
px - opx, py - opy, pz - opz, |
4930 |
|
end_x, end_y, pz, |
4931 |
|
AA_end, BB_end, CC_end, |
4932 |
233 |
u_end, v_end, w_end); |
4933 |
|
} |
4934 |
|
|
4935 |
250 |
comp_set_current(settings, end_x, end_y, pz); |
4936 |
250 |
settings->AA_current = AA_end; |
4937 |
250 |
settings->BB_current = BB_end; |
4938 |
250 |
settings->CC_current = CC_end; |
4939 |
250 |
settings->u_current = u_end; |
4940 |
250 |
settings->v_current = v_end; |
4941 |
250 |
settings->w_current = w_end; |
4942 |
250 |
comp_set_programmed(settings, px, py, pz); |
4943 |
|
return INTERP_OK; |
4944 |
|
} |
4945 |
|
|
4946 |
|
/****************************************************************************/ |
4947 |
|
|
4948 |
|
/*! convert_tool_change |
4949 |
|
|
4950 |
|
Returned Value: int (INTERP_OK) |
4951 |
|
|
4952 |
|
Side effects: |
4953 |
|
This makes function calls to canonical machining functions, and sets |
4954 |
|
the machine model as described below. |
4955 |
|
|
4956 |
|
Called by: convert_m |
4957 |
|
|
4958 |
|
This function carries out an M6 command, which changes the tool. |
4959 |
|
If M61 is called, the toolnumber gets changed (without causing an actual toolchange). |
4960 |
|
|
4961 |
|
When the CHANGE_TOOL call completes, the specified tool should be |
4962 |
|
loaded. What this means varies by machine. According to configuration, |
4963 |
|
the interpreter may also issue commands to do one or more of the |
4964 |
|
following things before calling CHANGE_TOOL: |
4965 |
|
|
4966 |
|
1. stop the spindle |
4967 |
|
2. move the quill up (Z to machine zero, like G0 G53 Z0) |
4968 |
|
3. move the axes to reference point #2 (like G30) |
4969 |
|
|
4970 |
|
Further, the interpreter makes no assumptions about the axis positions |
4971 |
|
after the tool change completes. This state is queried and the internal |
4972 |
|
model is resynched before the program continues. This means CHANGE_TOOL |
4973 |
|
itself can also issue motion (and it currently may, according to |
4974 |
|
configuration). |
4975 |
|
|
4976 |
|
This implements the "Next tool in T word" approach to tool selection. |
4977 |
|
The tool is selected when the T word is read (and the carousel may |
4978 |
|
move at that time) but is changed when M6 is read. |
4979 |
|
|
4980 |
|
Note that if a different tool is put into the spindle, the current_z |
4981 |
|
location setting will be incorrect. It is assumed the program will |
4982 |
|
contain an appropriate USE_TOOL_LENGTH_OFFSET (G43) command before any |
4983 |
|
subsequent motion. It is also assumed that the program will restart the |
4984 |
|
spindle and make new entry moves if necessary. |
4985 |
|
|
4986 |
|
*/ |
4987 |
|
|
4988 |
9 |
int Interp::convert_tool_change(setup_pointer settings) //!< pointer to machine settings |
4989 |
|
{ |
4990 |
|
|
4991 |
9 |
if (settings->selected_pocket < 0) { |
4992 |
|
ERS(NCE_TXX_MISSING_FOR_M6); |
4993 |
|
} |
4994 |
|
|
4995 |
9 |
CHKS((settings->cutter_comp_side), |
4996 |
|
(_("Cannot change tools with cutter radius compensation on"))); |
4997 |
|
|
4998 |
9 |
START_CHANGE(); // indicate start of change operation |
4999 |
9 |
if (!settings->tool_change_with_spindle_on) { |
5000 |
9 |
STOP_SPINDLE_TURNING(); |
5001 |
9 |
settings->spindle_turning = CANON_STOPPED; |
5002 |
|
} |
5003 |
|
|
5004 |
9 |
if (settings->tool_change_quill_up) { |
5005 |
|
double up_z; |
5006 |
|
double discard; |
5007 |
|
find_relative(0., 0., 0., 0., 0., 0., 0., 0., 0., |
5008 |
|
&discard, &discard, &up_z, |
5009 |
|
&discard, &discard, &discard, |
5010 |
|
&discard, &discard, &discard, |
5011 |
1 |
settings); |
5012 |
1 |
COMMENT("AXIS,hide"); |
5013 |
|
STRAIGHT_TRAVERSE(-1, settings->current_x, settings->current_y, up_z, |
5014 |
|
settings->AA_current, settings->BB_current, settings->CC_current, |
5015 |
1 |
settings->u_current, settings->v_current, settings->w_current); |
5016 |
1 |
COMMENT("AXIS,show"); |
5017 |
1 |
settings->current_z = up_z; |
5018 |
|
} |
5019 |
|
|
5020 |
9 |
if (settings->tool_change_at_g30) { |
5021 |
|
double end_x; |
5022 |
|
double end_y; |
5023 |
|
double end_z; |
5024 |
|
double AA_end; |
5025 |
|
double BB_end; |
5026 |
|
double CC_end; |
5027 |
|
double u_end; |
5028 |
|
double v_end; |
5029 |
|
double w_end; |
5030 |
|
|
5031 |
|
find_relative(USER_TO_PROGRAM_LEN(settings->parameters[5181]), |
5032 |
|
USER_TO_PROGRAM_LEN(settings->parameters[5182]), |
5033 |
|
USER_TO_PROGRAM_LEN(settings->parameters[5183]), |
5034 |
|
USER_TO_PROGRAM_ANG(settings->parameters[5184]), |
5035 |
|
USER_TO_PROGRAM_ANG(settings->parameters[5185]), |
5036 |
|
USER_TO_PROGRAM_ANG(settings->parameters[5186]), |
5037 |
|
USER_TO_PROGRAM_LEN(settings->parameters[5187]), |
5038 |
|
USER_TO_PROGRAM_LEN(settings->parameters[5188]), |
5039 |
|
USER_TO_PROGRAM_LEN(settings->parameters[5189]), |
5040 |
|
&end_x, &end_y, &end_z, |
5041 |
|
&AA_end, &BB_end, &CC_end, |
5042 |
|
&u_end, &v_end, &w_end, settings); |
5043 |
|
COMMENT("AXIS,hide"); |
5044 |
|
|
5045 |
|
// move indexers first, one at a time |
5046 |
|
// JOINTS_AXES settings->*_indexer_jnum == -1 means notused |
5047 |
|
if (AA_end != settings->AA_current && (-1 != settings->a_indexer_jnum) ) |
5048 |
|
issue_straight_index(3,settings->a_indexer_jnum, AA_end, -1, settings); |
5049 |
|
if (BB_end != settings->BB_current && (-1 != settings->b_indexer_jnum) ) |
5050 |
|
issue_straight_index(4,settings->b_indexer_jnum, BB_end, -1, settings); |
5051 |
|
if (CC_end != settings->CC_current && (-1 != settings->c_indexer_jnum) ) |
5052 |
|
issue_straight_index(5,settings->c_indexer_jnum, CC_end, -1, settings); |
5053 |
|
|
5054 |
|
STRAIGHT_TRAVERSE(-1, end_x, end_y, end_z, |
5055 |
|
AA_end, BB_end, CC_end, |
5056 |
|
u_end, v_end, w_end); |
5057 |
|
COMMENT("AXIS,show"); |
5058 |
|
settings->current_x = end_x; |
5059 |
|
settings->current_y = end_y; |
5060 |
|
settings->current_z = end_z; |
5061 |
|
settings->AA_current = AA_end; |
5062 |
|
settings->BB_current = BB_end; |
5063 |
|
settings->CC_current = CC_end; |
5064 |
|
settings->u_current = u_end; |
5065 |
|
settings->v_current = v_end; |
5066 |
|
settings->w_current = w_end; |
5067 |
|
} |
5068 |
|
|
5069 |
9 |
CHANGE_TOOL(settings->selected_pocket); |
5070 |
|
|
5071 |
9 |
settings->current_pocket = settings->selected_pocket; |
5072 |
|
// tool change can move the controlled point. reread it: |
5073 |
9 |
settings->toolchange_flag = true; |
5074 |
9 |
set_tool_parameters(); |
5075 |
9 |
return INTERP_OK; |
5076 |
|
} |
5077 |
|
|
5078 |
|
/****************************************************************************/ |
5079 |
|
|
5080 |
|
/*! convert_tool_length_offset |
5081 |
|
|
5082 |
|
Returned Value: int |
5083 |
|
If any of the following errors occur, this returns the error code shown. |
5084 |
|
Otherwise, it returns INTERP_OK. |
5085 |
|
1. The block has no offset index (h number): NCE_OFFSET_INDEX_MISSING |
5086 |
|
2. The g_code argument is not G_43 or G_49: |
5087 |
|
NCE_BUG_CODE_NOT_G43_OR_G49 |
5088 |
|
|
5089 |
|
Side effects: |
5090 |
|
A USE_TOOL_LENGTH_OFFSET function call is made. Current_z, |
5091 |
|
tool_length_offset, and length_offset_index are reset. |
5092 |
|
|
5093 |
|
Called by: convert_g |
5094 |
|
|
5095 |
|
This is called to execute g43 or g49. |
5096 |
|
|
5097 |
|
The g49 RS274/NGC command translates into a USE_TOOL_LENGTH_OFFSET(0.0) |
5098 |
|
function call. |
5099 |
|
|
5100 |
|
The g43 RS274/NGC command translates into a USE_TOOL_LENGTH_OFFSET(length) |
5101 |
|
function call, where length is the value of the entry in the tool length |
5102 |
|
offset table whose index is the H number in the block. |
5103 |
|
|
5104 |
|
The H number in the block (if present) was checked for being a non-negative |
5105 |
|
integer when it was read, so that check does not need to be repeated. |
5106 |
|
|
5107 |
|
*/ |
5108 |
|
|
5109 |
17 |
int Interp::convert_tool_length_offset(int g_code, //!< g_code being executed (must be G_43 or G_49) |
5110 |
|
block_pointer block, //!< pointer to a block of RS274/NGC instructions |
5111 |
|
setup_pointer settings) //!< pointer to machine settings |
5112 |
|
{ |
5113 |
|
int pocket_number; |
5114 |
|
EmcPose tool_offset; |
5115 |
17 |
ZERO_EMC_POSE(tool_offset); |
5116 |
|
|
5117 |
17 |
CHKS((settings->cutter_comp_side), |
5118 |
|
(_("Cannot change tool offset with cutter radius compensation on"))); |
5119 |
17 |
if (g_code == G_49) { |
5120 |
7 |
pocket_number = 0; |
5121 |
10 |
} else if (g_code == G_43) { |
5122 |
10 |
logDebug("convert_tool_length_offset h_flag=%d h_number=%d toolchange_flag=%d current_pocket=%d\n", |
5123 |
|
block->h_flag,block->h_number,settings->toolchange_flag,settings->current_pocket); |
5124 |
10 |
if(block->h_flag) { |
5125 |
|
CHP((find_tool_pocket(settings, block->h_number, &pocket_number))); |
5126 |
10 |
} else if (settings->toolchange_flag) { |
5127 |
|
// Tool change is in progress, so the "current tool" is in its |
5128 |
|
// original pocket still. |
5129 |
4 |
pocket_number = settings->current_pocket; |
5130 |
|
} else { |
5131 |
|
// Tool change is done so the current tool is in pocket 0 (aka the |
5132 |
|
// spindle). |
5133 |
6 |
pocket_number = 0; |
5134 |
|
} |
5135 |
10 |
logDebug("convert_tool_length_offset: using index=%d spindle_toolno=%d pocket_toolno=%d", |
5136 |
|
pocket_number, settings->tool_table[0].toolno,settings->tool_table[settings->current_pocket].toolno); |
5137 |
|
|
5138 |
10 |
tool_offset.tran.x = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.x); |
5139 |
10 |
tool_offset.tran.y = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.y); |
5140 |
10 |
tool_offset.tran.z = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.z); |
5141 |
10 |
tool_offset.a = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.a); |
5142 |
10 |
tool_offset.b = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.b); |
5143 |
10 |
tool_offset.c = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.c); |
5144 |
10 |
tool_offset.u = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.u); |
5145 |
10 |
tool_offset.v = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.v); |
5146 |
10 |
tool_offset.w = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.w); |
5147 |
|
} else if (g_code == G_43_1) { |
5148 |
|
tool_offset = settings->tool_offset; |
5149 |
|
pocket_number = -1; |
5150 |
|
if(block->x_flag) tool_offset.tran.x = block->x_number; |
5151 |
|
if(block->y_flag) tool_offset.tran.y = block->y_number; |
5152 |
|
if(block->z_flag) tool_offset.tran.z = block->z_number; |
5153 |
|
if(block->a_flag) tool_offset.a = block->a_number; |
5154 |
|
if(block->b_flag) tool_offset.b = block->b_number; |
5155 |
|
if(block->c_flag) tool_offset.c = block->c_number; |
5156 |
|
if(block->u_flag) tool_offset.u = block->u_number; |
5157 |
|
if(block->v_flag) tool_offset.v = block->v_number; |
5158 |
|
if(block->w_flag) tool_offset.w = block->w_number; |
5159 |
|
} else if (g_code == G_43_2) { |
5160 |
|
CHKS((!block->h_flag), (_("G43.2: H-word missing"))); |
5161 |
|
CHP((find_tool_pocket(settings, block->h_number, &pocket_number))); |
5162 |
|
tool_offset = settings->tool_offset; |
5163 |
|
tool_offset.tran.x += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.x); |
5164 |
|
tool_offset.tran.y += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.y); |
5165 |
|
tool_offset.tran.z += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.z); |
5166 |
|
tool_offset.a += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.a); |
5167 |
|
tool_offset.b += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.b); |
5168 |
|
tool_offset.c += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.c); |
5169 |
|
tool_offset.u += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.u); |
5170 |
|
tool_offset.v += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.v); |
5171 |
|
tool_offset.w += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.w); |
5172 |
|
} else { |
5173 |
|
ERS("BUG: Code not G43, G43.1, G43.2, or G49"); |
5174 |
|
} |
5175 |
17 |
USE_TOOL_LENGTH_OFFSET(tool_offset); |
5176 |
|
|
5177 |
|
double dx, dy; |
5178 |
|
|
5179 |
17 |
dx = settings->tool_offset.tran.x - tool_offset.tran.x; |
5180 |
17 |
dy = settings->tool_offset.tran.y - tool_offset.tran.y; |
5181 |
|
|
5182 |
17 |
rotate(&dx, &dy, -settings->rotation_xy); |
5183 |
|
|
5184 |
17 |
settings->current_x += dx; |
5185 |
17 |
settings->current_y += dy; |
5186 |
17 |
settings->current_z += settings->tool_offset.tran.z - tool_offset.tran.z; |
5187 |
17 |
settings->AA_current += settings->tool_offset.a - tool_offset.a; |
5188 |
17 |
settings->BB_current += settings->tool_offset.b - tool_offset.b; |
5189 |
17 |
settings->CC_current += settings->tool_offset.c - tool_offset.c; |
5190 |
17 |
settings->u_current += settings->tool_offset.u - tool_offset.u; |
5191 |
17 |
settings->v_current += settings->tool_offset.v - tool_offset.v; |
5192 |
17 |
settings->w_current += settings->tool_offset.w - tool_offset.w; |
5193 |
|
|
5194 |
17 |
settings->tool_offset = tool_offset; |
5195 |
17 |
return INTERP_OK; |
5196 |
|
} |
5197 |
|
|
5198 |
|
/****************************************************************************/ |
5199 |
|
|
5200 |
|
/*! convert_tool_select |
5201 |
|
|
5202 |
|
Returned Value: int |
5203 |
|
If the tool number given in the block is not found in the tool table, |
5204 |
|
it returns INTERP_ERROR. Otherwise (if the tool *is* found) it returns |
5205 |
|
INTERP_OK. |
5206 |
|
|
5207 |
|
Side effects: See below |
5208 |
|
|
5209 |
|
Called by: execute_block |
5210 |
|
|
5211 |
|
A select tool command is given, which causes the changer chain to move |
5212 |
|
so that the slot with the tool identified by the t_number given in the |
5213 |
|
block is next to the tool changer, ready for a tool change. The |
5214 |
|
settings->selected_tool_slot is set to the given slot. |
5215 |
|
|
5216 |
|
A check that the t_number is not negative has already been made in read_t. |
5217 |
|
A zero t_number is allowed and means no tool should be selected. |
5218 |
|
|
5219 |
|
*/ |
5220 |
|
|
5221 |
|
// OK to select tool in a concave corner, I think? |
5222 |
|
|
5223 |
9 |
int Interp::convert_tool_select(block_pointer block, //!< pointer to a block of RS274 instructions |
5224 |
|
setup_pointer settings) //!< pointer to machine settings |
5225 |
|
{ |
5226 |
|
int pocket; |
5227 |
9 |
CHP((find_tool_pocket(settings, block->t_number, &pocket))); |
5228 |
9 |
SELECT_POCKET(pocket, block->t_number); |
5229 |
9 |
settings->selected_pocket = pocket; |
5230 |
9 |
settings->selected_tool = block->t_number; |
5231 |
9 |
return INTERP_OK; |
5232 |
207 |
} |
5233 |
|
|
5234 |
|
|