I wrote a small python script to convert a LinuxCNC tooltable "tool.tbl" into JSON format which can be imported by the Path workbench ToolTable Editor.
If a Toolcontroller is then created the tool numbers are the same as on my CNC mill.
Maybe somebody finds this useful too.
Code: Select all
# -*- coding: utf-8 -*-
# ***************************************************************************
# * *
# * Author: Alexander K, <> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * 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 Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
"""
FreeCAD LinuxCNC tooltable to Path Tooltable converter macro
INSTALLATION
Place this script in your macros folder. (default is $HOME/.FreeCAD/Macro on mac/linux,
C:/Users/youruser/Application Data/FreeCAD/Macro on windows).
USAGE:
In the FileOpenDialog select a LinuxCNC tooltable file (usually tool.tbl). It will then
be converted into JSON-format which the Tooltable Editor of the Path workbench can read.
The output file is located in the same directory as the input file and named "EMC Imported.json"
"""
__Name__ = "PathToolTableConvert"
__Comment__ = "Converts a LinuxCNC Tooltable into Path ToolTable json-format"
__Author__ = "alexK"
__Version__ = "0.1"
__Date__ = "2020-10-12"
__License__ = "LGPL-2.0-or-later"
__Web__ = ''
__Wiki__ = ''
__Icon__ = 'PathToolTableConvert.svg'
__Help__ = ''
__Status__ = ''
__Requires__ = ''
__Communication__ = ''
__Files__ = "PathToolTableConvert.FCMacro,PathToolTableConvert.svg"
import re
from pathlib import PurePath
from PySide import QtGui, QtCore
import FreeCAD as app
import FreeCADGui as Gui
import Path
# To debug start debug vscode, then run the script in FC.
#import ptvsd
#print("Waiting for debugger attach")
#ptvsd.enable_attach(address=('0.0.0.0', 5678))
#ptvsd.break_into_debugger()
# End debug
class ToolTable:
"""Class to process EMC tooltables."""
def __init__(self, fin):
self._tablename = 'EMC Imported'
self._infile = fin
self._p = PurePath(fin)
self._outfile = str(self._p.parent) + '/' + self._tablename + '.json'
self._tooltable_string = ''
self._tools = []
self._tooltypes = ['Undefined',
'EndMill',
'Drill',
'CenterDrill',
'CounterSink',
'CounterBore',
'FlyCutter',
'Reamer',
'Tap',
'SlotCutter',
'BallEndMill',
'ChamferMill',
'CornerRound',
'Engraver'
]
self._rx_dict = {
'number': re.compile(r'(?P<number>T[0-9]*)'),
'lengthoffset': re.compile(r'(?P<lengthoffset>Z-?[0-9]*\.[0-9]*|Z[0-9]*)'),
'diameter': re.compile(r'(?P<diameter>D[0-9]*\.[0-9]*|D[0-9]*)'),
'name': re.compile(r'(?P<name>;.*)\n')
}
def convert_tool_data(self):
''' Reads the LinuxCNC saved tooltable and parses it '''
print('Infile: ' + self._infile)
print('Outfile: ' + self._outfile)
with open(self._infile, 'r') as infile:
for line in infile:
tool = {'number': 0,
'cornerRadius': 0.0,
'cuttingEdgeAngle': 0.0,
'cuttingEdgeHeight': 0.0,
'diameter': 0.0,
'flatRadius': 0.0,
'lengthOffset': 0.0,
'material': 'undefined',
'name': 'undefined',
'tooltype': 'undefined',
'version': 1
}
for key, rx in self._rx_dict.items():
match = rx.search(line)
if match:
if key == 'number':
tool['number'] = match.group('number')[1:]
if key == 'lengthoffset':
tool['lengthOffset'] = match.group('lengthoffset')[1:]
if key == 'diameter':
tool['diameter'] = match.group('diameter')[1:]
if key == 'name':
tool['name'] = match.group('name')[1:]
for tooltype in self._tooltypes:
if self.contains_tooltype(tool['name'], tooltype):
tool['tooltype'] = tooltype
self._tools.append(tool)
self._tooltable_string = '[{"TableName":"' + self._tablename + '","Tools":{'
for tool in self._tools:
self._tooltable_string += '"' + tool['number'] + '":{' + \
'"cornerRadius":' + str(tool['cornerRadius']) + ',' + \
'"cuttingEdgeAngle":' + str(tool['cuttingEdgeAngle']) + ',' + \
'"cuttingEdgeHeight":' + str(tool['cuttingEdgeHeight']) + ',' + \
'"diameter":' + str(tool['diameter']) + ',' + \
'"flatRadius":' + str(tool['flatRadius']) + ',' + \
'"lengthOffset":' + str(tool['lengthOffset']) + ',' + \
'"material":"' + str(tool['material']).strip() + '",' + \
'"name":"' + str(tool['name']).strip() + '",' + \
'"tooltype":"' + str(tool['tooltype']).strip() + '",' + \
'"version": 1},'
self._tooltable_string = self._tooltable_string[:-1]
self._tooltable_string += '},"Version": 1}]'
#print(self._tooltable_string)
outfile = open(self._outfile, 'w')
outfile.write(self._tooltable_string)
infile.close()
outfile.close()
print('Finished writing tooltable: ' + self._outfile)
reply = QtGui.QMessageBox.question(None, "", "Finished converting.\nYou can now import:\n" + self._outfile \
+ "\nDo you want to open the toolmanager now?",
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
Gui.runCommand('Path_ToolLibraryEdit',0)
if reply == QtGui.QMessageBox.No:
pass
def contains_tooltype(self, s, w):
return (' ' + w.lower() + ' ') in (' ' + s.lower() + ' ')
def main():
''' Main function '''
infilename, _ = QtGui.QFileDialog.getOpenFileName(caption='Open Tooltable File',
filter='Tooltable (*.tbl)')
if len(infilename) > 0:
fctt = ToolTable(infilename)
fctt.convert_tool_data()
if __name__ == '__main__':
main()
Alex