Merged in marius_stanciu/flatcam_beta/Beta (pull request #214)
Beta - adding new command line parameter --shellvars
This commit is contained in:
@@ -60,11 +60,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
fc = App()
|
fc = App()
|
||||||
|
|
||||||
if settings.contains("maximized_gui"):
|
|
||||||
maximized_ui = settings.value('maximized_gui', type=bool)
|
|
||||||
if maximized_ui is True:
|
|
||||||
fc.ui.showMaximized()
|
|
||||||
else:
|
|
||||||
fc.ui.show()
|
|
||||||
|
|
||||||
sys.exit(app.exec_())
|
sys.exit(app.exec_())
|
||||||
|
|||||||
@@ -80,10 +80,14 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
# Get Cmd Line Options
|
# Get Cmd Line Options
|
||||||
cmd_line_shellfile = ''
|
cmd_line_shellfile = ''
|
||||||
cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>"
|
cmd_line_shellvars = ''
|
||||||
|
|
||||||
|
cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>\nFlatCam.py --shellvars=<cmd_line_shellvars"
|
||||||
try:
|
try:
|
||||||
# Multiprocessing pool will spawn additional processes with 'multiprocessing-fork' flag
|
# Multiprocessing pool will spawn additional processes with 'multiprocessing-fork' flag
|
||||||
cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", ["shellfile=", "multiprocessing-fork="])
|
cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", ["shellfile=",
|
||||||
|
"shellvars=",
|
||||||
|
"multiprocessing-fork="])
|
||||||
except getopt.GetoptError:
|
except getopt.GetoptError:
|
||||||
print(cmd_line_help)
|
print(cmd_line_help)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
@@ -93,6 +97,8 @@ class App(QtCore.QObject):
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
elif opt == '--shellfile':
|
elif opt == '--shellfile':
|
||||||
cmd_line_shellfile = arg
|
cmd_line_shellfile = arg
|
||||||
|
elif opt == '--shellvars':
|
||||||
|
cmd_line_shellvars = arg
|
||||||
|
|
||||||
# ## Logging ###
|
# ## Logging ###
|
||||||
log = logging.getLogger('base')
|
log = logging.getLogger('base')
|
||||||
@@ -1905,7 +1911,7 @@ class App(QtCore.QObject):
|
|||||||
self.on_excellon_options_button)
|
self.on_excellon_options_button)
|
||||||
|
|
||||||
# when there are arguments at application startup this get launched
|
# when there are arguments at application startup this get launched
|
||||||
self.args_at_startup[list].connect(lambda: self.on_startup_args())
|
self.args_at_startup[list].connect(self.on_startup_args)
|
||||||
|
|
||||||
# connect the 'Apply' buttons from the Preferences/File Associations
|
# connect the 'Apply' buttons from the Preferences/File Associations
|
||||||
self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect(
|
self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect(
|
||||||
@@ -2406,7 +2412,26 @@ class App(QtCore.QObject):
|
|||||||
except Exception as ext:
|
except Exception as ext:
|
||||||
print("ERROR: ", ext)
|
print("ERROR: ", ext)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
elif self.cmd_line_shellvars:
|
||||||
|
try:
|
||||||
|
with open(self.cmd_line_shellvars, "r") as myfile:
|
||||||
|
if show_splash:
|
||||||
|
self.splash.showMessage('%s: %ssec\n%s' % (
|
||||||
|
_("Canvas initialization started.\n"
|
||||||
|
"Canvas initialization finished in"), '%.2f' % self.used_time,
|
||||||
|
_("Reading Shell vars ...")),
|
||||||
|
alignment=Qt.AlignBottom | Qt.AlignLeft,
|
||||||
|
color=QtGui.QColor("gray"))
|
||||||
|
cmd_line_shellvars_text = myfile.read()
|
||||||
|
for line in cmd_line_shellvars_text.splitlines():
|
||||||
|
var, __, var_value = line.partition('=')
|
||||||
|
var = var.replace(' ', '')
|
||||||
|
var_value = var_value.replace(' ', '')
|
||||||
|
command_tcl = 'set {var} {var_value}'.format(var=var, var_value=var_value)
|
||||||
|
self.shell._sysShell.exec_command(command_tcl, no_echo=True)
|
||||||
|
except Exception as ext:
|
||||||
|
print("ERROR: ", ext)
|
||||||
|
sys.exit(2)
|
||||||
# accept some type file as command line parameter: FlatCAM project, FlatCAM preferences or scripts
|
# accept some type file as command line parameter: FlatCAM project, FlatCAM preferences or scripts
|
||||||
# the path/file_name must be enclosed in quotes if it contain spaces
|
# the path/file_name must be enclosed in quotes if it contain spaces
|
||||||
if App.args:
|
if App.args:
|
||||||
@@ -2415,6 +2440,18 @@ class App(QtCore.QObject):
|
|||||||
# finish the splash
|
# finish the splash
|
||||||
self.splash.finish(self.ui)
|
self.splash.finish(self.ui)
|
||||||
|
|
||||||
|
# #####################################################################################
|
||||||
|
# ########################## SHOW GUI #################################################
|
||||||
|
# #####################################################################################
|
||||||
|
|
||||||
|
settings = QSettings("Open Source", "FlatCAM")
|
||||||
|
if settings.contains("maximized_gui"):
|
||||||
|
maximized_ui = settings.value('maximized_gui', type=bool)
|
||||||
|
if maximized_ui is True:
|
||||||
|
self.ui.showMaximized()
|
||||||
|
else:
|
||||||
|
self.ui.show()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def copy_and_overwrite(from_path, to_path):
|
def copy_and_overwrite(from_path, to_path):
|
||||||
"""
|
"""
|
||||||
@@ -2433,14 +2470,15 @@ class App(QtCore.QObject):
|
|||||||
from_new_path = os.path.dirname(os.path.realpath(__file__)) + '\\flatcamGUI\\VisPyData\\data'
|
from_new_path = os.path.dirname(os.path.realpath(__file__)) + '\\flatcamGUI\\VisPyData\\data'
|
||||||
shutil.copytree(from_new_path, to_path)
|
shutil.copytree(from_new_path, to_path)
|
||||||
|
|
||||||
def on_startup_args(self, args=None):
|
def on_startup_args(self, args):
|
||||||
"""
|
"""
|
||||||
This will process any arguments provided to the application at startup. Like trying to launch a file or project.
|
This will process any arguments provided to the application at startup. Like trying to launch a file or project.
|
||||||
|
|
||||||
:param args: a list containing the application args at startup
|
:param args: a list containing the application args at startup
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
if args:
|
|
||||||
|
if args is not None:
|
||||||
args_to_process = args
|
args_to_process = args
|
||||||
else:
|
else:
|
||||||
args_to_process = App.args
|
args_to_process = App.args
|
||||||
@@ -2491,6 +2529,13 @@ class App(QtCore.QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.debug("Could not open FlatCAM Script file as App parameter due: %s" % str(e))
|
log.debug("Could not open FlatCAM Script file as App parameter due: %s" % str(e))
|
||||||
|
|
||||||
|
elif 'quit' in argument or 'exit' in argument:
|
||||||
|
log.debug("App.on_startup_args() --> Quit event.")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
elif 'save' in argument:
|
||||||
|
log.debug("App.on_startup_args() --> Save event. App Defaults saved.")
|
||||||
|
self.save_defaults()
|
||||||
else:
|
else:
|
||||||
exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().split(',')
|
exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().split(',')
|
||||||
proc_arg = argument.lower()
|
proc_arg = argument.lower()
|
||||||
@@ -3125,18 +3170,20 @@ class App(QtCore.QObject):
|
|||||||
self.display_tcl_error(text)
|
self.display_tcl_error(text)
|
||||||
raise self.TclErrorException(text)
|
raise self.TclErrorException(text)
|
||||||
|
|
||||||
def exec_command(self, text, no_plot=None):
|
def exec_command(self, text, no_echo=False):
|
||||||
"""
|
"""
|
||||||
Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
|
Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
|
||||||
Also handles execution in separated threads
|
Also handles execution in separated threads
|
||||||
|
|
||||||
:param text: FlatCAM TclCommand with parameters
|
:param text: FlatCAM TclCommand with parameters
|
||||||
|
:param no_echo: If True it will not try to print to the Shell because most likely the shell is hidden and it
|
||||||
|
will create crashes of the _Expandable_Edit widget
|
||||||
:return: output if there was any
|
:return: output if there was any
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.report_usage('exec_command')
|
self.report_usage('exec_command')
|
||||||
|
|
||||||
result = self.exec_command_test(text, False)
|
result = self.exec_command_test(text, False, no_echo=no_echo)
|
||||||
|
|
||||||
# MS: added this method call so the geometry is updated once the TCL command is executed
|
# MS: added this method call so the geometry is updated once the TCL command is executed
|
||||||
# if no_plot is None:
|
# if no_plot is None:
|
||||||
@@ -3144,35 +3191,40 @@ class App(QtCore.QObject):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def exec_command_test(self, text, reraise=True):
|
def exec_command_test(self, text, reraise=True, no_echo=False):
|
||||||
"""
|
"""
|
||||||
Same as exec_command(...) with additional control over exceptions.
|
Same as exec_command(...) with additional control over exceptions.
|
||||||
Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
|
Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
|
||||||
|
|
||||||
:param text: Input command
|
:param text: Input command
|
||||||
:param reraise: Re-raise TclError exceptions in Python (mostly for unitttests).
|
:param reraise: Re-raise TclError exceptions in Python (mostly for unitttests).
|
||||||
|
:param no_echo: If True it will not try to print to the Shell because most likely the shell is hidden and it
|
||||||
|
will create crashes of the _Expandable_Edit widget
|
||||||
:return: Output from the command
|
:return: Output from the command
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tcl_command_string = str(text)
|
tcl_command_string = str(text)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.shell.open_proccessing() # Disables input box.
|
if no_echo is False:
|
||||||
|
self.shell.open_proccessing() # Disables input box.
|
||||||
|
|
||||||
result = self.tcl.eval(str(tcl_command_string))
|
result = self.tcl.eval(str(tcl_command_string))
|
||||||
if result != 'None':
|
if result != 'None' and no_echo is False:
|
||||||
self.shell.append_output(result + '\n')
|
self.shell.append_output(result + '\n')
|
||||||
|
|
||||||
except tk.TclError as e:
|
except tk.TclError as e:
|
||||||
# This will display more precise answer if something in TCL shell fails
|
# This will display more precise answer if something in TCL shell fails
|
||||||
result = self.tcl.eval("set errorInfo")
|
result = self.tcl.eval("set errorInfo")
|
||||||
self.log.error("Exec command Exception: %s" % (result + '\n'))
|
self.log.error("Exec command Exception: %s" % (result + '\n'))
|
||||||
self.shell.append_error('ERROR: ' + result + '\n')
|
if no_echo is False:
|
||||||
|
self.shell.append_error('ERROR: ' + result + '\n')
|
||||||
# Show error in console and just return or in test raise exception
|
# Show error in console and just return or in test raise exception
|
||||||
if reraise:
|
if reraise:
|
||||||
raise e
|
raise e
|
||||||
finally:
|
finally:
|
||||||
self.shell.close_proccessing()
|
if no_echo is False:
|
||||||
|
self.shell.close_proccessing()
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ CAD program, and create G-Code for Isolation routing.
|
|||||||
- fixed issue #315 where a script run with the --shellfile argument crashed the program if it contained a TclCommand New
|
- fixed issue #315 where a script run with the --shellfile argument crashed the program if it contained a TclCommand New
|
||||||
- added messages in the Splash Screen when running FlatCAM with arguments at startup
|
- added messages in the Splash Screen when running FlatCAM with arguments at startup
|
||||||
- fixed issue #313 where TclCommand drillcncjob is spitting errors in Tcl Shell which should be ignored
|
- fixed issue #313 where TclCommand drillcncjob is spitting errors in Tcl Shell which should be ignored
|
||||||
|
- fixed an bug where the pywrapcp name from Google OR-Tools is not defined; fix issue #316
|
||||||
|
- if FlatCAM is started with the 'quit' or 'exit' as argument it will close immediately and it will close also another instance of FlatCAM that may be running
|
||||||
|
- added a new command line parameter for FlatCAM named '--shellvars' which can load a text file with variables for Tcl Shell in the format: one variable assignment per line and looking like: 'a=3' without quotes
|
||||||
|
|
||||||
16.09.2019
|
16.09.2019
|
||||||
|
|
||||||
|
|||||||
535
camlib.py
535
camlib.py
@@ -5868,313 +5868,320 @@ class CNCjob(Geometry):
|
|||||||
self.app.inform.emit('%s...' %
|
self.app.inform.emit('%s...' %
|
||||||
_("Starting G-Code"))
|
_("Starting G-Code"))
|
||||||
|
|
||||||
if excellon_optimization_type == 'M':
|
current_platform = platform.architecture()[0]
|
||||||
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
if current_platform == '64bit':
|
||||||
if exobj.drills:
|
used_excellon_optimization_type = excellon_optimization_type
|
||||||
for tool in tools:
|
if used_excellon_optimization_type == 'M':
|
||||||
self.tool=tool
|
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
||||||
self.postdata['toolC'] = exobj.tools[tool]["C"]
|
if exobj.drills:
|
||||||
self.tooldia = exobj.tools[tool]["C"]
|
for tool in tools:
|
||||||
|
self.tool=tool
|
||||||
|
self.postdata['toolC'] = exobj.tools[tool]["C"]
|
||||||
|
self.tooldia = exobj.tools[tool]["C"]
|
||||||
|
|
||||||
if self.app.abort_flag:
|
|
||||||
# graceful abort requested by the user
|
|
||||||
raise FlatCAMApp.GracefulException
|
|
||||||
|
|
||||||
# ###############################################
|
|
||||||
# ############ Create the data. #################
|
|
||||||
# ###############################################
|
|
||||||
|
|
||||||
node_list = []
|
|
||||||
locations = create_data_array()
|
|
||||||
tsp_size = len(locations)
|
|
||||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
|
||||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
|
||||||
depot = 0
|
|
||||||
# Create routing model.
|
|
||||||
if tsp_size > 0:
|
|
||||||
manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
|
|
||||||
routing = pywrapcp.RoutingModel(manager)
|
|
||||||
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
|
|
||||||
search_parameters.local_search_metaheuristic = (
|
|
||||||
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
|
|
||||||
|
|
||||||
# Set search time limit in milliseconds.
|
|
||||||
if float(self.app.defaults["excellon_search_time"]) != 0:
|
|
||||||
search_parameters.time_limit.seconds = int(
|
|
||||||
float(self.app.defaults["excellon_search_time"]))
|
|
||||||
else:
|
|
||||||
search_parameters.time_limit.seconds = 3
|
|
||||||
|
|
||||||
# Callback to the distance function. The callback takes two
|
|
||||||
# arguments (the from and to node indices) and returns the distance between them.
|
|
||||||
dist_between_locations = CreateDistanceCallback()
|
|
||||||
dist_callback = dist_between_locations.Distance
|
|
||||||
transit_callback_index = routing.RegisterTransitCallback(dist_callback)
|
|
||||||
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
|
|
||||||
|
|
||||||
# Solve, returns a solution if any.
|
|
||||||
assignment = routing.SolveWithParameters(search_parameters)
|
|
||||||
|
|
||||||
if assignment:
|
|
||||||
# Solution cost.
|
|
||||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
|
||||||
|
|
||||||
# Inspect solution.
|
|
||||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
|
||||||
route_number = 0
|
|
||||||
node = routing.Start(route_number)
|
|
||||||
start_node = node
|
|
||||||
|
|
||||||
while not routing.IsEnd(node):
|
|
||||||
if self.app.abort_flag:
|
|
||||||
# graceful abort requested by the user
|
|
||||||
raise FlatCAMApp.GracefulException
|
|
||||||
|
|
||||||
node_list.append(node)
|
|
||||||
node = assignment.Value(routing.NextVar(node))
|
|
||||||
else:
|
|
||||||
log.warning('No solution found.')
|
|
||||||
else:
|
|
||||||
log.warning('Specify an instance greater than 0.')
|
|
||||||
# ############################################# ##
|
|
||||||
|
|
||||||
# Only if tool has points.
|
|
||||||
if tool in points:
|
|
||||||
if self.app.abort_flag:
|
if self.app.abort_flag:
|
||||||
# graceful abort requested by the user
|
# graceful abort requested by the user
|
||||||
raise FlatCAMApp.GracefulException
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
# Tool change sequence (optional)
|
# ###############################################
|
||||||
if toolchange:
|
# ############ Create the data. #################
|
||||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
# ###############################################
|
||||||
gcode += self.doformat(p.spindle_code) # Spindle start
|
|
||||||
if self.dwell is True:
|
node_list = []
|
||||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
locations = create_data_array()
|
||||||
|
tsp_size = len(locations)
|
||||||
|
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||||
|
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||||
|
depot = 0
|
||||||
|
# Create routing model.
|
||||||
|
if tsp_size > 0:
|
||||||
|
manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
|
||||||
|
routing = pywrapcp.RoutingModel(manager)
|
||||||
|
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
|
||||||
|
search_parameters.local_search_metaheuristic = (
|
||||||
|
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
|
||||||
|
|
||||||
|
# Set search time limit in milliseconds.
|
||||||
|
if float(self.app.defaults["excellon_search_time"]) != 0:
|
||||||
|
search_parameters.time_limit.seconds = int(
|
||||||
|
float(self.app.defaults["excellon_search_time"]))
|
||||||
|
else:
|
||||||
|
search_parameters.time_limit.seconds = 3
|
||||||
|
|
||||||
|
# Callback to the distance function. The callback takes two
|
||||||
|
# arguments (the from and to node indices) and returns the distance between them.
|
||||||
|
dist_between_locations = CreateDistanceCallback()
|
||||||
|
dist_callback = dist_between_locations.Distance
|
||||||
|
transit_callback_index = routing.RegisterTransitCallback(dist_callback)
|
||||||
|
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
|
||||||
|
|
||||||
|
# Solve, returns a solution if any.
|
||||||
|
assignment = routing.SolveWithParameters(search_parameters)
|
||||||
|
|
||||||
|
if assignment:
|
||||||
|
# Solution cost.
|
||||||
|
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||||
|
|
||||||
|
# Inspect solution.
|
||||||
|
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||||
|
route_number = 0
|
||||||
|
node = routing.Start(route_number)
|
||||||
|
start_node = node
|
||||||
|
|
||||||
|
while not routing.IsEnd(node):
|
||||||
|
if self.app.abort_flag:
|
||||||
|
# graceful abort requested by the user
|
||||||
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
|
node_list.append(node)
|
||||||
|
node = assignment.Value(routing.NextVar(node))
|
||||||
|
else:
|
||||||
|
log.warning('No solution found.')
|
||||||
else:
|
else:
|
||||||
gcode += self.doformat(p.spindle_code)
|
log.warning('Specify an instance greater than 0.')
|
||||||
if self.dwell is True:
|
# ############################################# ##
|
||||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
|
||||||
|
|
||||||
if self.units == 'MM':
|
# Only if tool has points.
|
||||||
current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
|
if tool in points:
|
||||||
else:
|
if self.app.abort_flag:
|
||||||
current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
|
# graceful abort requested by the user
|
||||||
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
self.app.inform.emit(
|
# Tool change sequence (optional)
|
||||||
'%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
|
if toolchange:
|
||||||
str(current_tooldia),
|
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||||
str(self.units))
|
gcode += self.doformat(p.spindle_code) # Spindle start
|
||||||
)
|
if self.dwell is True:
|
||||||
|
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||||
|
else:
|
||||||
|
gcode += self.doformat(p.spindle_code)
|
||||||
|
if self.dwell is True:
|
||||||
|
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||||
|
|
||||||
# TODO apply offset only when using the GUI, for TclCommand this will create an error
|
if self.units == 'MM':
|
||||||
# because the values for Z offset are created in build_ui()
|
current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
|
||||||
try:
|
else:
|
||||||
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
|
||||||
except KeyError:
|
|
||||||
z_offset = 0
|
|
||||||
self.z_cut += z_offset
|
|
||||||
|
|
||||||
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
|
self.app.inform.emit(
|
||||||
if self.coordinates_type == "G90":
|
'%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
|
||||||
# Drillling! for Absolute coordinates type G90
|
str(current_tooldia),
|
||||||
# variables to display the percentage of work done
|
str(self.units))
|
||||||
geo_len = len(node_list)
|
)
|
||||||
disp_number = 0
|
|
||||||
old_disp_number = 0
|
|
||||||
log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
|
|
||||||
|
|
||||||
loc_nr = 0
|
# TODO apply offset only when using the GUI, for TclCommand this will create an error
|
||||||
for k in node_list:
|
# because the values for Z offset are created in build_ui()
|
||||||
if self.app.abort_flag:
|
try:
|
||||||
# graceful abort requested by the user
|
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
||||||
raise FlatCAMApp.GracefulException
|
except KeyError:
|
||||||
|
z_offset = 0
|
||||||
|
self.z_cut += z_offset
|
||||||
|
|
||||||
locx = locations[k][0]
|
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
|
||||||
locy = locations[k][1]
|
if self.coordinates_type == "G90":
|
||||||
|
# Drillling! for Absolute coordinates type G90
|
||||||
|
# variables to display the percentage of work done
|
||||||
|
geo_len = len(node_list)
|
||||||
|
disp_number = 0
|
||||||
|
old_disp_number = 0
|
||||||
|
log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
|
||||||
|
|
||||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
loc_nr = 0
|
||||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
for k in node_list:
|
||||||
|
if self.app.abort_flag:
|
||||||
|
# graceful abort requested by the user
|
||||||
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
locx = locations[k][0]
|
||||||
|
locy = locations[k][1]
|
||||||
|
|
||||||
if self.f_retract is False:
|
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||||
measured_up_to_zero_distance += abs(self.z_cut)
|
|
||||||
measured_lift_distance += abs(self.z_move)
|
|
||||||
else:
|
|
||||||
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
|
||||||
|
|
||||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
||||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
|
||||||
self.oldx = locx
|
|
||||||
self.oldy = locy
|
|
||||||
|
|
||||||
loc_nr += 1
|
if self.f_retract is False:
|
||||||
disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
|
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||||
|
measured_up_to_zero_distance += abs(self.z_cut)
|
||||||
|
measured_lift_distance += abs(self.z_move)
|
||||||
|
else:
|
||||||
|
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
||||||
|
|
||||||
if old_disp_number < disp_number <= 100:
|
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||||
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||||
old_disp_number = disp_number
|
self.oldx = locx
|
||||||
|
self.oldy = locy
|
||||||
|
|
||||||
else:
|
loc_nr += 1
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
|
||||||
_('G91 coordinates not implemented'))
|
|
||||||
return 'fail'
|
|
||||||
else:
|
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
|
||||||
"The loaded Excellon file has no drills ...")
|
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
|
||||||
_('The loaded Excellon file has no drills'))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
|
if old_disp_number < disp_number <= 100:
|
||||||
elif excellon_optimization_type == 'B':
|
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
||||||
log.debug("Using OR-Tools Basic drill path optimization.")
|
old_disp_number = disp_number
|
||||||
if exobj.drills:
|
|
||||||
for tool in tools:
|
|
||||||
if self.app.abort_flag:
|
|
||||||
# graceful abort requested by the user
|
|
||||||
raise FlatCAMApp.GracefulException
|
|
||||||
|
|
||||||
self.tool=tool
|
else:
|
||||||
self.postdata['toolC']=exobj.tools[tool]["C"]
|
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
||||||
self.tooldia = exobj.tools[tool]["C"]
|
_('G91 coordinates not implemented'))
|
||||||
|
return 'fail'
|
||||||
|
else:
|
||||||
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||||
|
"The loaded Excellon file has no drills ...")
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
||||||
|
_('The loaded Excellon file has no drills'))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
# ############################################# ##
|
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
|
||||||
node_list = []
|
|
||||||
locations = create_data_array()
|
|
||||||
tsp_size = len(locations)
|
|
||||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
|
||||||
|
|
||||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
if used_excellon_optimization_type == 'B':
|
||||||
depot = 0
|
log.debug("Using OR-Tools Basic drill path optimization.")
|
||||||
|
if exobj.drills:
|
||||||
# Create routing model.
|
for tool in tools:
|
||||||
if tsp_size > 0:
|
|
||||||
manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
|
|
||||||
routing = pywrapcp.RoutingModel(manager)
|
|
||||||
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
|
|
||||||
|
|
||||||
# Callback to the distance function. The callback takes two
|
|
||||||
# arguments (the from and to node indices) and returns the distance between them.
|
|
||||||
dist_between_locations = CreateDistanceCallback()
|
|
||||||
dist_callback = dist_between_locations.Distance
|
|
||||||
transit_callback_index = routing.RegisterTransitCallback(dist_callback)
|
|
||||||
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
|
|
||||||
|
|
||||||
# Solve, returns a solution if any.
|
|
||||||
assignment = routing.SolveWithParameters(search_parameters)
|
|
||||||
|
|
||||||
if assignment:
|
|
||||||
# Solution cost.
|
|
||||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
|
||||||
|
|
||||||
# Inspect solution.
|
|
||||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
|
||||||
route_number = 0
|
|
||||||
node = routing.Start(route_number)
|
|
||||||
start_node = node
|
|
||||||
|
|
||||||
while not routing.IsEnd(node):
|
|
||||||
node_list.append(node)
|
|
||||||
node = assignment.Value(routing.NextVar(node))
|
|
||||||
else:
|
|
||||||
log.warning('No solution found.')
|
|
||||||
else:
|
|
||||||
log.warning('Specify an instance greater than 0.')
|
|
||||||
# ############################################# ##
|
|
||||||
|
|
||||||
# Only if tool has points.
|
|
||||||
if tool in points:
|
|
||||||
if self.app.abort_flag:
|
if self.app.abort_flag:
|
||||||
# graceful abort requested by the user
|
# graceful abort requested by the user
|
||||||
raise FlatCAMApp.GracefulException
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
# Tool change sequence (optional)
|
self.tool=tool
|
||||||
if toolchange:
|
self.postdata['toolC']=exobj.tools[tool]["C"]
|
||||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
self.tooldia = exobj.tools[tool]["C"]
|
||||||
gcode += self.doformat(p.spindle_code) # Spindle start)
|
|
||||||
if self.dwell is True:
|
# ############################################# ##
|
||||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
node_list = []
|
||||||
|
locations = create_data_array()
|
||||||
|
tsp_size = len(locations)
|
||||||
|
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||||
|
|
||||||
|
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||||
|
depot = 0
|
||||||
|
|
||||||
|
# Create routing model.
|
||||||
|
if tsp_size > 0:
|
||||||
|
manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
|
||||||
|
routing = pywrapcp.RoutingModel(manager)
|
||||||
|
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
|
||||||
|
|
||||||
|
# Callback to the distance function. The callback takes two
|
||||||
|
# arguments (the from and to node indices) and returns the distance between them.
|
||||||
|
dist_between_locations = CreateDistanceCallback()
|
||||||
|
dist_callback = dist_between_locations.Distance
|
||||||
|
transit_callback_index = routing.RegisterTransitCallback(dist_callback)
|
||||||
|
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
|
||||||
|
|
||||||
|
# Solve, returns a solution if any.
|
||||||
|
assignment = routing.SolveWithParameters(search_parameters)
|
||||||
|
|
||||||
|
if assignment:
|
||||||
|
# Solution cost.
|
||||||
|
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||||
|
|
||||||
|
# Inspect solution.
|
||||||
|
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||||
|
route_number = 0
|
||||||
|
node = routing.Start(route_number)
|
||||||
|
start_node = node
|
||||||
|
|
||||||
|
while not routing.IsEnd(node):
|
||||||
|
node_list.append(node)
|
||||||
|
node = assignment.Value(routing.NextVar(node))
|
||||||
|
else:
|
||||||
|
log.warning('No solution found.')
|
||||||
else:
|
else:
|
||||||
gcode += self.doformat(p.spindle_code)
|
log.warning('Specify an instance greater than 0.')
|
||||||
if self.dwell is True:
|
# ############################################# ##
|
||||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
|
||||||
|
|
||||||
if self.units == 'MM':
|
# Only if tool has points.
|
||||||
current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
|
if tool in points:
|
||||||
else:
|
if self.app.abort_flag:
|
||||||
current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
|
# graceful abort requested by the user
|
||||||
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
self.app.inform.emit(
|
# Tool change sequence (optional)
|
||||||
'%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
|
if toolchange:
|
||||||
str(current_tooldia),
|
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||||
str(self.units))
|
gcode += self.doformat(p.spindle_code) # Spindle start)
|
||||||
)
|
if self.dwell is True:
|
||||||
|
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||||
|
else:
|
||||||
|
gcode += self.doformat(p.spindle_code)
|
||||||
|
if self.dwell is True:
|
||||||
|
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||||
|
|
||||||
# TODO apply offset only when using the GUI, for TclCommand this will create an error
|
if self.units == 'MM':
|
||||||
# because the values for Z offset are created in build_ui()
|
current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
|
||||||
try:
|
else:
|
||||||
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
|
||||||
except KeyError:
|
|
||||||
z_offset = 0
|
|
||||||
self.z_cut += z_offset
|
|
||||||
|
|
||||||
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
|
self.app.inform.emit(
|
||||||
if self.coordinates_type == "G90":
|
'%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
|
||||||
# Drillling! for Absolute coordinates type G90
|
str(current_tooldia),
|
||||||
# variables to display the percentage of work done
|
str(self.units))
|
||||||
geo_len = len(node_list)
|
)
|
||||||
disp_number = 0
|
|
||||||
old_disp_number = 0
|
|
||||||
log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
|
|
||||||
|
|
||||||
loc_nr = 0
|
# TODO apply offset only when using the GUI, for TclCommand this will create an error
|
||||||
for k in node_list:
|
# because the values for Z offset are created in build_ui()
|
||||||
if self.app.abort_flag:
|
try:
|
||||||
# graceful abort requested by the user
|
z_offset = float(self.tool_offset[current_tooldia]) * (-1)
|
||||||
raise FlatCAMApp.GracefulException
|
except KeyError:
|
||||||
|
z_offset = 0
|
||||||
|
self.z_cut += z_offset
|
||||||
|
|
||||||
locx = locations[k][0]
|
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
|
||||||
locy = locations[k][1]
|
if self.coordinates_type == "G90":
|
||||||
|
# Drillling! for Absolute coordinates type G90
|
||||||
|
# variables to display the percentage of work done
|
||||||
|
geo_len = len(node_list)
|
||||||
|
disp_number = 0
|
||||||
|
old_disp_number = 0
|
||||||
|
log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
|
||||||
|
|
||||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
loc_nr = 0
|
||||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
for k in node_list:
|
||||||
|
if self.app.abort_flag:
|
||||||
|
# graceful abort requested by the user
|
||||||
|
raise FlatCAMApp.GracefulException
|
||||||
|
|
||||||
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
locx = locations[k][0]
|
||||||
|
locy = locations[k][1]
|
||||||
|
|
||||||
if self.f_retract is False:
|
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||||
measured_up_to_zero_distance += abs(self.z_cut)
|
|
||||||
measured_lift_distance += abs(self.z_move)
|
|
||||||
else:
|
|
||||||
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
|
||||||
|
|
||||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
||||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
|
||||||
self.oldx = locx
|
|
||||||
self.oldy = locy
|
|
||||||
|
|
||||||
loc_nr += 1
|
if self.f_retract is False:
|
||||||
disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
|
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||||
|
measured_up_to_zero_distance += abs(self.z_cut)
|
||||||
|
measured_lift_distance += abs(self.z_move)
|
||||||
|
else:
|
||||||
|
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
||||||
|
|
||||||
if old_disp_number < disp_number <= 100:
|
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||||
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||||
old_disp_number = disp_number
|
self.oldx = locx
|
||||||
|
self.oldy = locy
|
||||||
|
|
||||||
else:
|
loc_nr += 1
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
|
||||||
_('G91 coordinates not implemented'))
|
|
||||||
return 'fail'
|
|
||||||
else:
|
|
||||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
|
||||||
"The loaded Excellon file has no drills ...")
|
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
|
||||||
_('The loaded Excellon file has no drills'))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
if old_disp_number < disp_number <= 100:
|
||||||
|
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
||||||
|
old_disp_number = disp_number
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
||||||
|
_('G91 coordinates not implemented'))
|
||||||
|
return 'fail'
|
||||||
|
else:
|
||||||
|
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||||
|
"The loaded Excellon file has no drills ...")
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s...' %
|
||||||
|
_('The loaded Excellon file has no drills'))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
||||||
else:
|
else:
|
||||||
|
used_excellon_optimization_type = 'T'
|
||||||
|
|
||||||
|
if used_excellon_optimization_type == 'T':
|
||||||
log.debug("Using Travelling Salesman drill path optimization.")
|
log.debug("Using Travelling Salesman drill path optimization.")
|
||||||
for tool in tools:
|
for tool in tools:
|
||||||
if self.app.abort_flag:
|
if self.app.abort_flag:
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
portable=False
|
portable=False
|
||||||
|
headless=False
|
||||||
|
|||||||
Reference in New Issue
Block a user