Adding tools to manufacture turning operation

Adding tools to manufacture turning operation

treiFMCJL
Explorer Explorer
271 Views
1 Reply
Message 1 of 2

Adding tools to manufacture turning operation

treiFMCJL
Explorer
Explorer

Hi, is anyone able to help me with Fusion API? I am not able to add tools from tool library to my operation and when following guides on Fusion webpage it seems to be out of date and does not work. Any samples for turning application would be well appreciated.

0 Likes
272 Views
1 Reply
Reply (1)
Message 2 of 2

rohit_maneYV8C9
Autodesk
Autodesk

Hello @treiFMCJL ,
The basic workflow of milling and turning operations is almost the same; you can refer to the script below for more details.

import adsk.core
import adsk.fusion
import adsk.cam
import traceback
import time


def run(context):
    ui = None
    try:

        #################### Initialisation #####################
        app = adsk.core.Application.get()
        ui = app.userInterface

        PROJECT_URN = 'urn:adsk.wipprod:dm.lineage:YlsP6ejaTuOf_j_PIHMWBQ'
        # Load by URN a specific sample project to demonstrate a basic milling workflow.
        doc = loadProjectFromURN(PROJECT_URN)
        if doc is None:
            return

        design = adsk.fusion.Design.cast(
            doc.products.itemByProductType("DesignProductType"))
        if not design:
            ui.messageBox('No active Fusion design found.')
            return

        design.timeline.moveToEnd()

        # Switch to manufacturing space
        camWS: adsk.core.Workspace = ui.workspaces.itemById('CAMEnvironment')
        camWS.activate()

        # Get the CAM product
        products: adsk.core.Products = doc.products

        #################### Find tools in sample tool library ####################
        # Get the tool libraries from the library manager
        camManager = adsk.cam.CAMManager.get()
        libraryManager: adsk.cam.CAMLibraryManager = camManager.libraryManager
        toolLibraries: adsk.cam.ToolLibraries = libraryManager.toolLibraries

        # We can use a library URl directly if we know its address (here we use Fusion's Metric sample library)
        url = adsk.core.URL.create(
            'systemlibraryroot://Samples/Turning Tools (Metric).json')

        # Load tool library
        toolLibrary: adsk.cam.ToolLibrary = toolLibraries.toolLibraryAtURL(url)

        # Create some variables for the milling tools which will be used in the operations
        faceTool: adsk.cam.Tool = None
        adaptiveTool: adsk.cam.Tool = None

        # Searching the turning tool using a loop for the roughing operations
        for tool in toolLibrary:
            # Read the tool type
            toolType = tool.parameters.itemByName('tool_type').value.value
            hand = tool.parameters.itemByName('tool_hand').value.value
            shape = tool.parameters.itemByName('tool_insertType').value.value

            # Select the first face tool found
            if toolType == 'turning general' and hand == 'R' and shape == 'C' and not faceTool:
                tool.parameters.itemByName('tool_number').expression = '1'
                faceTool = tool

            # Search the roughing tool
            elif toolType == 'turning general' and hand == 'R' and shape == 'V' and not adaptiveTool:
                tool.parameters.itemByName('tool_number').expression = '2'
                adaptiveTool = tool

            # Exit when the 2 tools are found
            if faceTool and adaptiveTool:
                break

        #################### Create setup ####################
        cam: adsk.cam.CAM = adsk.cam.CAM.cast(
            products.itemByProductType("CAMProductType"))
        setups: adsk.cam.Setups = cam.setups
        setupInput: adsk.cam.SetupInput = setups.createInput(
            adsk.cam.OperationTypes.TurningOperation)
        # Create a list for the models to add to the setup Input
        models = []

        # Identify the part or exit gracefully
        try:
            part: adsk.fusion.BRepBody = cam.designRootOccurrence.bRepBodies.item(
                0)
        except Exception as e:
            ui.messageBox(
                'No part found in the current document, exiting sample script.')
            return

        # Add the part to the model list
        models.append(part)
        # Pass the model list to the setup input
        setupInput.models = models
        # Create the setup
        setup: adsk.cam.Setup = setups.add(setupInput)
        # Change some properties of the setup
        setup.name = 'CAM Turning Basic Script Sample'
        setup.stockMode = adsk.cam.SetupStockModes.RelativeCylinderStock
        # Set offset mode
        setup.parameters.itemByName(
            'job_stockOffsetMode').expression = "'simple'"
        # Set offset stock side
        setup.parameters.itemByName('job_stockOffsetSides').expression = '1 mm'
        # Set offset stock top
        setup.parameters.itemByName('job_stockOffsetTop').expression = '0.5 mm'
        # Set setup origin
        setup.parameters.itemByName(
            'wcs_origin_boxPoint').value.value = 'top 1'

        #################### Face operation ####################
        # Create a face operation input
        faceInput: adsk.cam.OperationInput = setup.operations.createInput(
            'turningFace')
        faceInput.tool = faceTool
        faceInput.displayName = 'Trun Face Operation'
        faceInput.parameters.itemByName('tolerance').expression = '0.01 mm'
        faceInput.parameters.itemByName(
            'stepover').expression = '0.75 * tool_diameter'
        faceInput.parameters.itemByName(
            'direction').expression = "'outside to inside'"

        # Add the operation to the setup
        faceOp: adsk.cam.OperationBase = setup.operations.add(faceInput)

        #################### Adaptive operation ####################
        adaptiveInput = setup.operations.createInput('turningProfileRoughing')
        adaptiveInput.tool = adaptiveTool
        adaptiveInput.displayName = 'Turning Roughing'
        adaptiveInput.parameters.itemByName('tolerance').expression = '0.1 mm'
        adaptiveInput.parameters.itemByName(
            'depthOfCut').expression = '1.1 mm'

        # Add the operation to the setup
        adaptiveOp: adsk.cam.OperationBase = setup.operations.add(
            adaptiveInput)

        ##################### Generate operations ####################
        cam.generateToolpath(faceOp)
        genFuture: adsk.cam.GenerateToolpathFuture = cam.generateToolpath(
            adaptiveOp)
        adsk.doEvents()

        #################### ncProgram and post-processing ####################
        # Get the post library from library manager
        postLibrary: adsk.cam.PostLibrary = libraryManager.postLibrary

        # Query post library to get postprocessor list
        libraryLocation = adsk.cam.LibraryLocations.Fusion360LibraryLocation
        postQuery: adsk.cam.PostConfigurationQuery = postLibrary.createQuery(
            libraryLocation)
        postQuery.vendor = "Fanuc"
        postQuery.capability = adsk.cam.PostCapabilities.Turning
        postConfigs: list[adsk.cam.PostConfiguration] = postQuery.execute()

        # Find the "XYZ" post in the post library and import it to local library
        ncExtension = ''
        for config in postConfigs:
            if config.description == 'FANUC Turning':
                ncExtension = config.extension
                url = adsk.core.URL.create("user://")
                importedURL = postLibrary.importPostConfiguration(
                    config, url, "NCProgramSampleTurnPost.cps")

        # Get the imported local post config
        postConfig: adsk.cam.PostConfiguration = postLibrary.postConfigurationAtURL(
            importedURL)

        # Create NCProgramInput object
        ncInput: adsk.cam.NCProgramInput = cam.ncPrograms.createInput()
        ncInput.displayName = 'NC Program Sample'

        # Change some nc program parameters...
        ncFilename = 'NCProgramSample'
        ncParameters: adsk.cam.CAMParameters = ncInput.parameters
        ncParameters.itemByName('nc_program_filename').value.value = ncFilename
        ncParameters.itemByName('nc_program_openInEditor').value.value = True
        ncParameters.itemByName(
            'nc_program_nc_extension').value.value = ncExtension

        # Set temp directory as output directory
        # Make the path valid for Fusion by replacing \\ to / in the path
        outputFolder = str(cam.temporaryFolder).replace('\\', '/')
        ncParameters.itemByName(
            'nc_program_output_folder').value.value = outputFolder

        # Select the operations to generate
        ncInput.operations = [faceOp, adaptiveOp]

        # Add a new ncprogram from the ncprogram input
        newProgram: adsk.cam.NCProgram = cam.ncPrograms.add(ncInput)

        # Set post processor
        newProgram.postConfiguration = postConfig

        # Change some post parameters
        postParameters: adsk.cam.CAMParameters = newProgram.postParameters

        # NcProgram parameters are passed without units to the postprocessor
        postParameters.itemByName('builtin_tolerance').value.value = 0.01
        postParameters.itemByName(
            'builtin_minimumChordLength').value.value = 0.33

        # Update/apply post parameters
        newProgram.updatePostParameters(postParameters)

        # Post-process
        # Set post options, by default post process only valid operations containing toolpath data
        postOptions = adsk.cam.NCProgramPostProcessOptions.create()

        # Ensure toolpaths are visible
        faceOp.isLightBulbOn = True
        adaptiveOp.isLightBulbOn = True

        # To avoid errors, post-process only when toolpath generation has completed
        while not genFuture.isGenerationCompleted:
            time.sleep(1)
        newProgram.postProcess(postOptions)

        # Advise where the NC file is located to indicate completion
        ui.messageBox(f'The results have been written to:\n{outputFolder}/{ncFilename}{ncExtension}',
                      # Prevent line breaks of the pathname
                      'Post processing is complete  \t\t\t\t\t')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def loadProjectFromURN(urn: str = None) -> adsk.core.Document:
    ''' Minimal self-contained function to load and return a document via URN or return None safely '''
    doc: adsk.core.Document = None
    app = adsk.core.Application.get()
    if urn is not None:
        try:  # File not found causes an exception
            project: adsk.core.DataFile = app.data.findFileById(urn)
            if project:
                doc = app.documents.open(project, True)
            else:
                app.userInterface.messageBox(f'File not found for URN: {urn}!')
        except Exception as e:
            if str(e)[0:38] == '3 : Design is located in another team.':
                # Although the document has been loaded, variable 'doc' may not be populated
                if doc is None:
                    doc: adsk.core.Document = adsk.core.Application.get().activeDocument
            elif str(e)[0:20] == '3 : file not found':
                app.userInterface.messageBox(f'File not found for URN: {urn}!')
            else:
                # Abandon for unhandled errors, displaying the error message.
                app.userInterface.messageBox(
                    f'Failed:{str(e)}\n{traceback.format_exc()}')
    return doc