Toolchange generator

This commit is contained in:
sliptonic
2022-01-29 15:48:50 -06:00
parent 00319582e3
commit 0be2903aca
5 changed files with 176 additions and 18 deletions

View File

@@ -149,6 +149,7 @@ SET(Generator_SRCS
Generators/drill_generator.py
Generators/rotation_generator.py
Generators/helix_generator.py
Generators/toolchange_generator.py
)
SET(PathScripts_post_SRCS
@@ -240,6 +241,7 @@ SET(PathTests_SRCS
PathTests/TestPathPropertyBag.py
PathTests/TestPathSetupSheet.py
PathTests/TestPathStock.py
PathTests/TestPathToolChangeGenerator.py
PathTests/TestPathThreadMilling.py
PathTests/TestPathTool.py
PathTests/TestPathToolBit.py

View File

@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2021 sliptonic <shopinthewoods@gmail.com> *
# * *
# * 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 *
# * *
# ***************************************************************************
import PathScripts.PathLog as PathLog
import math
import Path
import FreeCAD
from enum import Enum
__title__ = "Toolchange Path Generator"
__author__ = "sliptonic (Brad Collette)"
__url__ = "https://www.freecadweb.org"
__doc__ = "Generates the rotation toolpath"
if True:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
class SpindleDirection(Enum):
OFF = "OFF"
CW = "M3"
CCW = "M4"
def generate(
toolnumber, toollabel, spindlespeed=0, spindledirection=SpindleDirection.OFF
):
"""
Generates Gcode for a simple toolchange.
"""
PathLog.track(
f"toolnumber:{toolnumber} toollabel: {toollabel} spindlespeed:{spindlespeed} spindledirection: {spindledirection}"
)
if spindledirection is not SpindleDirection.OFF and spindlespeed == 0:
raise ValueError("Turning on spindle with zero speed is invalid")
if spindlespeed < 0:
raise ValueError("Spindle speed must be a positive value")
commands = []
commands.append(Path.Command(f"({toollabel})"))
commands.append(Path.Command("M6", {"T": int(toolnumber)}))
if spindledirection is SpindleDirection.OFF:
return commands
else:
commands.append(Path.Command(spindledirection.value, {"S": spindlespeed}))
return commands

View File

@@ -28,6 +28,8 @@ import Path
import PathScripts.PathLog as PathLog
import PathScripts.PathPreferences as PathPreferences
import PathScripts.PathToolBit as PathToolBit
from Generators import toolchange_generator as toolchange_generator
from Generators.toolchange_generator import SpindleDirection
if False:
@@ -259,27 +261,28 @@ class ToolController:
def execute(self, obj):
PathLog.track()
commands = ""
commands += "(" + obj.Label + ")" + "\n"
commands += "M6 T" + str(obj.ToolNumber) + "\n"
args = {
"toolnumber": obj.ToolNumber,
"toollabel": obj.Label,
"spindlespeed": obj.SpindleSpeed,
"spindledirection": SpindleDirection.OFF,
}
# If a toolbit is used, check to see if spindlepower is allowed.
# This is to prevent accidentally spinning the spindle with an
# unpowered tool like probe or dragknife
allowSpindlePower = True
if not isinstance(obj.Tool, Path.Tool) and hasattr(obj.Tool, "SpindlePower"):
allowSpindlePower = obj.Tool.SpindlePower
if allowSpindlePower:
PathLog.debug("selected tool preventing spindle power")
if obj.SpindleDir == "Forward":
commands += "M3 S" + str(obj.SpindleSpeed) + "\n"
if hasattr(obj.Tool, "SpindlePower"):
if not obj.Tool.SpindlePower:
args["spindledirection"] = SpindleDirection.OFF
else:
commands += "M4 S" + str(obj.SpindleSpeed) + "\n"
if obj.SpindleDir == "Forward":
args["spindledirection"] = SpindleDirection.CW
else:
args["spindledirection"] = SpindleDirection.CCW
else:
if obj.SpindleDir == "Forward":
args["spindledirection"] = SpindleDirection.CW
else:
args["spindledirection"] = SpindleDirection.CCW
if commands == "":
commands += "(No commands processed)"
commands = toolchange_generator.generate(**args)
path = Path.Path(commands)
obj.Path = path

View File

@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2021 sliptonic <shopinthewoods@gmail.com> *
# * *
# * 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 *
# * *
# ***************************************************************************
import Path
import FreeCAD
import Generators.toolchange_generator as generator
from Generators.toolchange_generator import SpindleDirection
import PathScripts.PathLog as PathLog
import PathTests.PathTestUtils as PathTestUtils
import numpy as np
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
class TestPathToolChangeGenerator(PathTestUtils.PathTestBase):
def test00(self):
"""Test Basic Tool Change Generator Return"""
args = {
"toolnumber": 1,
"toollabel": "My Label",
"spindlespeed": 500,
"spindledirection": SpindleDirection.OFF,
}
results = generator.generate(**args)
# Get a label
self.assertTrue(len(results) == 2)
commentcommand = results[0]
self.assertTrue(isinstance(commentcommand, Path.Command))
self.assertTrue(commentcommand.toGCode() == "(My Label)")
# Get a tool command
toolcommand = results[1]
self.assertTrue(toolcommand.Name == "M6")
# Turn on the spindle
args["spindledirection"] = SpindleDirection.CW
results = generator.generate(**args)
self.assertTrue(len(results) == 3)
speedcommand = results[2]
self.assertTrue(speedcommand.Name == "M3")
self.assertTrue(speedcommand.Parameters["S"] == 500)
# speed zero with spindle on
args["spindlespeed"] = 0
self.assertRaises(ValueError, generator.generate, **args)
# negative spindlespeed
args["spindlespeed"] = -10
self.assertRaises(ValueError, generator.generate, **args)

View File

@@ -46,6 +46,7 @@ from PathTests.TestPathStock import TestPathStock
from PathTests.TestPathThreadMilling import TestPathThreadMilling
from PathTests.TestPathTool import TestPathTool
from PathTests.TestPathToolBit import TestPathToolBit
from PathTests.TestPathToolChangeGenerator import TestPathToolChangeGenerator
from PathTests.TestPathToolController import TestPathToolController
from PathTests.TestPathTooltable import TestPathTooltable
from PathTests.TestPathUtil import TestPathUtil
@@ -76,6 +77,7 @@ False if TestPathStock.__name__ else True
False if TestPathThreadMilling.__name__ else True
False if TestPathTool.__name__ else True
False if TestPathToolBit.__name__ else True
False if TestPathToolChangeGenerator.__name__ else True
False if TestPathToolController.__name__ else True
False if TestPathTooltable.__name__ else True
False if TestPathUtil.__name__ else True