Import LinuxCNC source tree
This commit is contained in:
361
lib/python/plasmac/run_from_line.py
Normal file
361
lib/python/plasmac/run_from_line.py
Normal file
@@ -0,0 +1,361 @@
|
||||
'''
|
||||
run_from_line.py
|
||||
|
||||
Copyright (C) 2019 - 2024 Phillip A Carter
|
||||
Copyright (C) 2020 - 2025 Gregory D Carl
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
'''
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def run_from_line_get(file, startLine, lastLine=0):
|
||||
preData, postData, newData, params, material = [], [], [], [], [None, None]
|
||||
codes = {'g2_': '', 'g4_': '', 'g6_': '', 'g9_': '', 'g9arc': '', 'd3': '', 'd2': '', 'a3': '', 'x1': '', 'y1': '', 'x2': '', 'y2': ''}
|
||||
codes['last'] = {'feed': '', 'code': ''}
|
||||
codes['move'] = {'isSet': False, 'isG00': False}
|
||||
codes['spindle'] = {'code': False, 'line': None}
|
||||
oSub = []
|
||||
cutComp = False
|
||||
count = 0
|
||||
with open(file, 'r') as inFile:
|
||||
for line in inFile:
|
||||
# code before selected line
|
||||
if count < startLine:
|
||||
preData.append(line)
|
||||
# remaining code
|
||||
else:
|
||||
if count == startLine:
|
||||
if 'G21' in line:
|
||||
newData.append('G21')
|
||||
elif 'G20' in line:
|
||||
newData.append('G20')
|
||||
# find the type of first move
|
||||
if not codes['move']['isSet'] and 'G53G00' not in line.replace(' ', '') and 'G20' not in line and 'G21' not in line:
|
||||
if 'G00' in line:
|
||||
codes['move']['isSet'] = True
|
||||
codes['move']['isG00'] = True
|
||||
codes['x2'] = get_rfl_pos(line.strip(), codes['x2'], 'X')
|
||||
codes['y2'] = get_rfl_pos(line.strip(), codes['y2'], 'Y')
|
||||
if 'G01' in line or 'G02' in line or 'G03' in line:
|
||||
codes['move']['isSet'] = True
|
||||
codes['move']['isG00'] = False
|
||||
codes['x2'] = get_rfl_pos(line.strip(), codes['x2'], 'X')
|
||||
codes['y2'] = get_rfl_pos(line.strip(), codes['y2'], 'Y')
|
||||
if 'M03' in line:
|
||||
if not codes['spindle']['line']:
|
||||
codes['spindle']['line'] = line.strip()
|
||||
continue
|
||||
codes['spindle']['line'] = line.strip()
|
||||
postData.append(line)
|
||||
if lastLine and count == lastLine:
|
||||
postData.append('M02\n')
|
||||
postData.append(';qtplasmac filtered G-code file\n')
|
||||
break
|
||||
count += 1
|
||||
# read all lines before selected line to get last used codes
|
||||
for line in preData:
|
||||
if line.startswith('('):
|
||||
if line.startswith('(o='):
|
||||
material = [line.strip()]
|
||||
continue
|
||||
elif line.startswith('M190'):
|
||||
material = [line.strip()]
|
||||
continue
|
||||
elif line.replace(' ', '').startswith('M66P3'):
|
||||
material.append(line.strip())
|
||||
continue
|
||||
elif line.startswith('#'):
|
||||
params.append(line.strip())
|
||||
continue
|
||||
for t1 in ['G20', 'G21', 'G40', 'G41.1', 'G42.1', 'G61', 'G61.1', 'G64', 'G90', 'G90.1', 'G91', 'G91.1']:
|
||||
if t1 in line:
|
||||
if t1[1] == '2':
|
||||
codes['g2_'] = t1
|
||||
elif t1[1] == '4':
|
||||
codes['g4_'] = t1
|
||||
if t1 != 'G40':
|
||||
cutComp = True
|
||||
else:
|
||||
cutComp = False
|
||||
elif t1[1] == '6':
|
||||
codes['g6_'] = t1 + line.split(t1)[1]
|
||||
elif t1 == 'G90' and 'G90.1' not in line:
|
||||
codes['g9_'] = 'G90'
|
||||
elif t1 == 'G91' and 'G91.1' not in line:
|
||||
codes['g9_'] = 'G91'
|
||||
elif 'G90.1' in line:
|
||||
codes['g9arc'] = 'G90.1'
|
||||
elif 'G91.1' in line:
|
||||
codes['g9arc'] = 'G91.1'
|
||||
if 'G00' in line and 'G53G00' not in line:
|
||||
codes['last']['code'] = 'G00'
|
||||
if 'G01' in line:
|
||||
tmp = line.split('G01')[1]
|
||||
if tmp[0] not in '0123456789':
|
||||
codes['last']['code'] = 'G01'
|
||||
if 'G02' in line:
|
||||
tmp = line.split('G02')[1]
|
||||
if tmp[0] not in '0123456789':
|
||||
codes['last']['code'] = 'G02'
|
||||
if 'G03' in line:
|
||||
tmp = line.split('G03')[1]
|
||||
if tmp[0] not in '0123456789':
|
||||
codes['last']['code'] = 'G03'
|
||||
if 'X' in line:
|
||||
codes['x1'] = get_rfl_pos(line.strip(), codes['x1'], 'X')
|
||||
if 'Y' in line:
|
||||
codes['y1'] = get_rfl_pos(line.strip(), codes['y1'], 'Y')
|
||||
# track spindle state: M03 starts, M05 stops
|
||||
if 'M03' in line.replace(' ', ''):
|
||||
codes['spindle']['line'] = line.strip()
|
||||
if 'M05' in line.replace(' ', ''):
|
||||
codes['spindle']['line'] = None
|
||||
if 'M62P3' in line.replace(' ', ''):
|
||||
codes['d3'] = 'M62 P3 (Disable Torch)'
|
||||
elif 'M63P3' in line.replace(' ', ''):
|
||||
codes['d3'] = 'M63 P3 (Enable Torch)'
|
||||
elif 'M64P3' in line.replace(' ', ''):
|
||||
codes['d3'] = 'M64 P3 (Disable Torch)'
|
||||
elif 'M65P3' in line.replace(' ', ''):
|
||||
codes['d3'] = 'M65 P3 (Enable Torch)'
|
||||
if 'M62P2' in line.replace(' ', ''):
|
||||
codes['d2'] = 'M62 P2 (Disable THC)'
|
||||
elif 'M63P2' in line.replace(' ', ''):
|
||||
codes['d2'] = 'M63 P2 (Enable THC)'
|
||||
elif 'M64P2' in line.replace(' ', ''):
|
||||
codes['d2'] = 'M64 P2 (Disable THC)'
|
||||
elif 'M65P2' in line.replace(' ', ''):
|
||||
codes['d2'] = 'M65 P2 (Enable THC)'
|
||||
if 'M67E3Q' in line.replace(' ', ''):
|
||||
codes['a3'] = 'M67 E3 Q'
|
||||
tmp = line.replace(' ', '').split('M67E3Q')[1]
|
||||
while 1:
|
||||
if tmp[0] in '-.0123456789':
|
||||
codes['a3'] += tmp[0]
|
||||
tmp = tmp[1:]
|
||||
else:
|
||||
break
|
||||
pc = float(codes['a3'].split('M67 E3 Q')[1])
|
||||
pc = pc if pc > 0 else 100
|
||||
codes['a3'] += f' (Velocity {pc}%)'
|
||||
if 'M68E3Q' in line.replace(' ', ''):
|
||||
codes['a3'] = 'M68 E3 Q'
|
||||
tmp = line.replace(' ', '').split('M68E3Q')[1]
|
||||
while 1:
|
||||
if tmp[0] in '-.0123456789':
|
||||
codes['a3'] += tmp[0]
|
||||
tmp = tmp[1:]
|
||||
else:
|
||||
break
|
||||
pc = float(codes['a3'].split('M68 E3 Q')[1])
|
||||
pc = pc if pc > 0 else 100
|
||||
codes['a3'] += f' (Velocity {pc}%)'
|
||||
# test if inside a subroutine
|
||||
if line.startswith('O'):
|
||||
if 'END' in line:
|
||||
oSub = False
|
||||
else:
|
||||
if line[1] == '<':
|
||||
os = 'O<'
|
||||
tmp = line.replace(' ', '').split('O<')[1]
|
||||
while 1:
|
||||
if tmp[0] != '>':
|
||||
os += tmp[0]
|
||||
tmp = tmp[1:]
|
||||
else:
|
||||
break
|
||||
oSub.append(f'{os}>')
|
||||
else:
|
||||
os = 'O'
|
||||
tmp = line.replace(' ', '').split('O')[1]
|
||||
while 1:
|
||||
if tmp[0] in '0123456789':
|
||||
os += tmp[0]
|
||||
tmp = tmp[1:]
|
||||
else:
|
||||
break
|
||||
oSub.append(os)
|
||||
if '#<_hal[plasmac.cut-feed-rate]>' in line:
|
||||
codes['last']['feed'] = line.strip()
|
||||
# return an error line within a subroutine or if using cutter compensation
|
||||
if cutComp or oSub:
|
||||
return {'error': True, 'compError': cutComp, 'subError': oSub}
|
||||
# else return all data
|
||||
return {'error': False, 'codes': codes, 'params': params, 'material': material, 'postData': postData, 'newData': newData}
|
||||
|
||||
|
||||
def run_from_line_set(rflFile, data, leadin, unitsPerMm):
|
||||
error = False
|
||||
# add all the codes retrieved from before the start line
|
||||
for param in data['params']:
|
||||
if param:
|
||||
data['newData'].append(param)
|
||||
scale = 1
|
||||
zMax = ''
|
||||
if unitsPerMm == 1:
|
||||
if data['codes']['g2_'] == 'G20':
|
||||
scale = 0.03937
|
||||
zMax = 'G53 G00 Z[[#<_ini[axis_z]max_limit> - 5] * 0.03937]'
|
||||
else:
|
||||
zMax = 'G53 G00 Z[#<_ini[axis_z]max_limit> - 5]'
|
||||
else:
|
||||
if data['codes']['g2_'] == 'G21':
|
||||
scale = 25.4
|
||||
zMax = 'G53 G00 Z[[#<_ini[axis_z]max_limit> * 25.4] - 5]'
|
||||
else:
|
||||
zMax = 'G53 G00 Z[#<_ini[axis_z]max_limit> - 0.02]'
|
||||
if data['codes']['g2_']:
|
||||
data['newData'].append(data['codes']['g2_'])
|
||||
if data['codes']['g4_']:
|
||||
data['newData'].append(data['codes']['g4_'])
|
||||
if data['codes']['g6_']:
|
||||
data['newData'].append(data['codes']['g6_'])
|
||||
if data['codes']['g9_']:
|
||||
data['newData'].append(data['codes']['g9_'])
|
||||
if data['codes']['g9arc']:
|
||||
data['newData'].append(data['codes']['g9arc'])
|
||||
data['newData'].append('M52 P1')
|
||||
if data['codes']['d3']:
|
||||
data['newData'].append(data['codes']['d3'])
|
||||
if data['codes']['d2']:
|
||||
data['newData'].append(data['codes']['d2'])
|
||||
if data['codes']['a3']:
|
||||
data['newData'].append(data['codes']['a3'])
|
||||
if zMax:
|
||||
data['newData'].append(zMax)
|
||||
if data['material'][0]:
|
||||
data['newData'].append(data['material'][0])
|
||||
if data['material'][1]:
|
||||
data['newData'].append(data['material'][1])
|
||||
if data['codes']['last']['feed']:
|
||||
data['newData'].append(data['codes']['last']['feed'])
|
||||
# if g00 is not the first motion command after selected line set x and y coordinates
|
||||
if not data['codes']['move']['isG00']:
|
||||
if leadin['do']:
|
||||
error, xL, yL = set_leadin_coordinates(data['codes']['x1'], data['codes']['y1'], scale, leadin['length'], leadin['angle'])
|
||||
else:
|
||||
xL = data['codes']['x1']
|
||||
yL = data['codes']['y1']
|
||||
data['codes']['spindle']['code'] = set_spindle_start(xL, yL, data['codes']['x1'], data['codes']['y1'], data['codes']['spindle']['line'], data['newData'], False)
|
||||
# if no spindle command yet then find the next one for the correct tool
|
||||
if not data['codes']['spindle']['line']:
|
||||
for line in data['postData']:
|
||||
if 'M03' in line.replace(' ', ''):
|
||||
data['codes']['spindle']['line'] = line.strip()
|
||||
break
|
||||
# add all the code from the selected line to the end
|
||||
for line in data['postData']:
|
||||
# if we have the first spindle code we don't need it again
|
||||
if 'M03' in line.replace(' ', '') and data['codes']['spindle']['code']:
|
||||
data['codes']['spindle']['code'] = False
|
||||
continue
|
||||
# if G00 is the first motion command after the selected line
|
||||
if data['codes']['move']['isG00']:
|
||||
# if G00 is the current motion command
|
||||
if 'G00' in line:
|
||||
# no need to process a G53G00 command]
|
||||
if 'G53G00' in line or 'G20' in line or 'G21' in line:
|
||||
data['newData'].append(line.strip())
|
||||
continue
|
||||
if leadin['do']:
|
||||
error, xL, yL = set_leadin_coordinates(data['codes']['x2'], data['codes']['y2'], scale, leadin['length'], leadin['angle'])
|
||||
else:
|
||||
xL = data['codes']['x2']
|
||||
yL = data['codes']['y2']
|
||||
data['codes']['spindle']['code'] = set_spindle_start(xL, yL, data['codes']['x2'], data['codes']['y2'], data['codes']['spindle']['line'], data['newData'], True)
|
||||
# no need to process any more G00 commands
|
||||
data['codes']['move']['isG00'] = False
|
||||
continue
|
||||
data['newData'].append(line.strip())
|
||||
# create the rfl file
|
||||
with open(rflFile, 'w') as outFile:
|
||||
for line in data['newData']:
|
||||
outFile.write(f'{line}\n')
|
||||
return {'error': error}
|
||||
|
||||
|
||||
def set_leadin_coordinates(x, y, scale, length, angle):
|
||||
xL = x
|
||||
yL = y
|
||||
try:
|
||||
if x[-1] == ']':
|
||||
xL = f'{x[:1]}[[{x[1:]}]+{(length * scale) * math.cos(math.radians(angle)):0.6f}]'
|
||||
yL = f'{y[:1]}[[{y[1:]}]+{(length * scale) * math.sin(math.radians(angle)):0.6f}]'
|
||||
else:
|
||||
xL = float(x) + ((length * scale) * math.cos(math.radians(angle)))
|
||||
yL = float(y) + ((length * scale) * math.sin(math.radians(angle)))
|
||||
except:
|
||||
return(True, x, y)
|
||||
return(False, xL, yL)
|
||||
|
||||
|
||||
def set_spindle_start(xL, yL, x, y, line, newData, reply):
|
||||
leadIn = {}
|
||||
if xL != x and yL != y:
|
||||
newData.append(f'G00 X{xL} Y{yL}')
|
||||
leadIn['x'] = x
|
||||
leadIn['y'] = y
|
||||
else:
|
||||
if x and y:
|
||||
newData.append(f'G00 X{x} Y{y}')
|
||||
elif x:
|
||||
newData.append(f'G00 X{x}')
|
||||
elif y:
|
||||
newData.append(f'G00 Y{y}')
|
||||
if line:
|
||||
newData.append(line)
|
||||
if leadIn:
|
||||
newData.append(f'G01 X{leadIn["x"]} Y{leadIn["y"]} (leadin)')
|
||||
return reply
|
||||
|
||||
|
||||
def get_rfl_pos(line, axisPos, axisLetter):
|
||||
maths = 0
|
||||
pos = ''
|
||||
done = False
|
||||
if line.startswith('(') or line.startswith(';'):
|
||||
return pos if pos else axisPos
|
||||
while len(line):
|
||||
if line[0] == ('('):
|
||||
break
|
||||
if not line[0] == axisLetter:
|
||||
line = line[1:]
|
||||
else:
|
||||
while 1:
|
||||
line = line[1:]
|
||||
if line[0] in '-.0123456789#':
|
||||
pos += line[0]
|
||||
elif line[0] == '[' or line[0] == '<':
|
||||
pos += line[0]
|
||||
maths += 1
|
||||
elif (line[0] == ']' or line[0] == '>') and maths > 0:
|
||||
pos += line[0]
|
||||
maths -= 1
|
||||
elif maths:
|
||||
pos += line[0]
|
||||
elif (pos and not maths) or line[0] == '(':
|
||||
done = True
|
||||
break
|
||||
else:
|
||||
if len(line) == 1:
|
||||
break
|
||||
break
|
||||
if len(line) == 1:
|
||||
break
|
||||
if done:
|
||||
break
|
||||
return pos if pos else axisPos
|
||||
Reference in New Issue
Block a user