Basic Milling Workflow Sample
Description
Demonstrates the creation of a basic milling workflow from scriptDemonstrates creating a setup, searching tool library to retrieve a tool, create a couple of machining operations and a NC program, ready for post processing.
Use the 2D Strategies model from the Fusion CAM Samples folder as your CAD model.
Code Samples
#include <Core/CoreAll.h> #include <Fusion/FusionAll.h> #include <Cam/CamAll.h> #include <chrono> #include <thread> #include <algorithm> #ifdef _WINDOWS #include <shlwapi.h> #else #include <stdlib.h> #endif using namespace adsk::core; using namespace adsk::fusion; using namespace adsk::cam; extern "C" XI_EXPORT bool run(const char* context) { // Initialisation Ptr<Application> app = Application::get(); Ptr<UserInterface> ui = app->userInterface(); Ptr<Document> doc = nullptr; // Load by URN a specific sample project to demonstrate a basic milling workflow. std::string urn = "urn:adsk.wipprod:fs.file:vf.KoBHzV4mTOiNvFStiBwpzA?version=1"; // Production // Load 2D Strategies model from the Fusion CAM Samples folder Ptr<DataFile> sampleFile = app->data()->findFileById(urn); if (sampleFile) { doc = app->documents()->open(sampleFile, true); } // Did we find our document? if (!doc) { ui->messageBox("Sample file not found, using the current document.", "", MessageBoxButtonTypes::OKButtonType); // Use existing document, load 2D Strategies model from the Fusion CAM Samples folder doc = app->activeDocument(); } // Switch to manufacturing space Ptr<Workspace> camWS = ui->workspaces()->itemById("CAMEnvironment"); camWS->activate(); Ptr<Products> products = doc->products(); if (!products) return false; // Check if the document has a CAMProductType. It will return if there are no CAM operations in it. Ptr<CAM> camProduct = products->itemByProductType("CAMProductType"); if (!camProduct) { ui->messageBox( "There are no CAM operations in the active document. This script requires the active document to contain " "at least one CAM operation.", "No CAM Operations Exist", MessageBoxButtonTypes::OKButtonType, MessageBoxIconTypes::CriticalIconType); return false; } // Find tools in sample tool library // Get the tool libraries from the library manager Ptr<CAMManager> camManager = CAMManager::get(); Ptr<CAMLibraryManager> libraryManager = camManager->libraryManager(); Ptr<ToolLibraries> toolLibraries = libraryManager->toolLibraries(); // We can use a library URl directly if we know its address (here we use Fusion"s Metric sample library) Ptr<URL> toolLibraryUrl = URL::create("systemlibraryroot://Samples/Milling Tools (Metric).json"); // Load tool library Ptr<ToolLibrary> toolLibrary = toolLibraries->toolLibraryAtURL(toolLibraryUrl); if (!toolLibrary) { ui->messageBox("Failed to load tool library"); return false; } // Create some variables for the milling tools which will be used in the operations Ptr<Tool> faceTool = nullptr; Ptr<Tool> adaptiveTool = nullptr; // Searching the face mill and the bull nose using a loop for the roughing operations for (Ptr<Tool>& tool : toolLibrary) { // Read the tool type Ptr<ChoiceParameterValue> toolTypeParameter = tool->parameters()->itemByName("tool_type")->value(); std::string toolType = toolTypeParameter->value(); // Select the first face tool found if (toolType == "face mill" && !faceTool) { faceTool = tool; } // Search the roughing tool else if (toolType == "bull nose end mill" && !adaptiveTool) { // We look for a bull nose end mill tool larger or equal to 10mm but less than 14mm Ptr<FloatParameterValue> diameterParameter = tool->parameters()->itemByName("tool_diameter")->value(); double diameter = diameterParameter->value(); if (diameter >= 1.0 && diameter < 1.4) { adaptiveTool = tool; } } // Exit when the 2 tools are found if (faceTool && adaptiveTool) { break; } } if (!faceTool) { ui->messageBox("No face mill tool found"); return false; } if (!adaptiveTool) { ui->messageBox("No bull nose end mill tool found"); return false; } // Create setup Ptr<CAM> cam = products->itemByProductType("CAMProductType"); Ptr<Setups> setups = cam->setups(); Ptr<SetupInput> setupInput = setups->createInput(OperationTypes::MillingOperation); // Create a list for the models to add to the setup Input std::vector<Ptr<Base>> models; Ptr<BRepBody> part = cam->designRootOccurrence()->bRepBodies()->item(0); if (!part) { ui->messageBox( "No part found in the current document, exiting sample script.", "", MessageBoxButtonTypes::OKButtonType); return false; } // Add the part to the model list models.push_back(part); // Pass the model list to the setup input setupInput->models(models); // Create the setup Ptr<Setup> setup = setups->add(setupInput); // Change some properties of the setup setup->name() = "CAM Basic Script Sample"; setup->stockMode(SetupStockModes::RelativeBoxStock); // Set offset mode setup->parameters()->itemByName("job_stockOffsetMode")->expression("'simple'"); // Set offset stock side setup->parameters()->itemByName("job_stockOffsetSides")->expression("0 mm"); // Set offset stock top setup->parameters()->itemByName("job_stockOffsetTop")->expression("2 mm"); // Set setup origin Ptr<ChoiceParameterValue> wcs_origin_boxPoint = setup->parameters()->itemByName("wcs_origin_boxPoint")->value(); wcs_origin_boxPoint->value("top 1"); // Face operation // Create a face operation input Ptr<OperationInput> faceInput = setup->operations()->createInput("face"); faceInput->tool(faceTool); faceInput->displayName("Face Operation"); faceInput->parameters()->itemByName("tolerance")->expression("0.01 mm"); faceInput->parameters()->itemByName("stepover")->expression("0.75 * tool_diameter"); faceInput->parameters() ->itemByName("direction") ->expression("'climb'"); // Must be single quotes inside double quotes // Add the operation to the setup Ptr<Operation> faceOp = setup->operations()->add(faceInput); // Adaptive operation Ptr<OperationInput> adaptiveInput = setup->operations()->createInput("adaptive"); adaptiveInput->tool(adaptiveTool); adaptiveInput->displayName("Adaptive Roughing"); adaptiveInput->parameters()->itemByName("tolerance")->expression("0.1 mm"); adaptiveInput->parameters()->itemByName("maximumStepdown")->expression("5 mm"); adaptiveInput->parameters()->itemByName("fineStepdown")->expression("0.25 * maximumStepdown"); adaptiveInput->parameters()->itemByName("flatAreaMachining")->expression("false"); // Add the operation to the setup Ptr<Operation> adaptiveOp = setup->operations()->add(adaptiveInput); // Generate operations cam->generateToolpath(faceOp); Ptr<GenerateToolpathFuture> genFuture = cam->generateToolpath(adaptiveOp); // ncProgram and post-processing // Get the post library from library manager Ptr<PostLibrary> postLibrary = libraryManager->postLibrary(); // Query post library to get postprocessor list Ptr<PostConfigurationQuery> postQuery = postLibrary->createQuery(LibraryLocations::Fusion360LibraryLocation); postQuery->vendor("Autodesk"); postQuery->capability(PostCapabilities::Milling); std::vector<Ptr<PostConfiguration>> postConfigs = postQuery->execute(); Ptr<URL> importedURL; std::string ncExtension; // Find the "XYZ" post in the post library and import it to local library for (Ptr<PostConfiguration>& config : postConfigs) { if (config->description() == "XYZ") { ncExtension = config->extension(); Ptr<URL> configUrl = URL::create("user://"); importedURL = postLibrary->importPostConfiguration(config, configUrl, "NCProgramSamplePost.cps"); break; } } // Get the imported local post config Ptr<PostConfiguration> postConfig = postLibrary->postConfigurationAtURL(importedURL); // Create NCProgramInput object Ptr<NCProgramInput> ncInput = cam->ncPrograms()->createInput(); ncInput->displayName("NC Program Sample"); // Change some nc program parameters... Ptr<CAMParameters> ncParameters = ncInput->parameters(); Ptr<StringParameterValue> nc_program_filename = ncParameters->itemByName("nc_program_filename")->value(); nc_program_filename->value("NCProgramSample"); Ptr<BooleanParameterValue> nc_program_openInEditor = ncParameters->itemByName("nc_program_openInEditor")->value(); nc_program_openInEditor->value(true); // Set temp directory as output directory std::string outputFolder = cam->temporaryFolder(); // Variable outputFolder may contain backslashes but nc_program_output_folder requires forward slashes std::replace_if( outputFolder.begin(), outputFolder.end(), [](char ch) { return ch == '\\'; }, '/'); Ptr<StringParameterValue> nc_program_output_folder = ncParameters->itemByName("nc_program_output_folder")->value(); nc_program_output_folder->value(outputFolder); // Select the operations to generate (we skip steep_and_shallow here) ncInput->operations({faceOp, adaptiveOp}); // Add a new ncprogram from the ncprogram input Ptr<NCProgram> newProgram = cam->ncPrograms()->add(ncInput); // Set post processor newProgram->postConfiguration(postConfig); // Change some post parameter Ptr<CAMParameters> postParameters = newProgram->postParameters(); // NcProgram parameters are passed without units to the postprocessor Ptr<FloatParameterValue> builtin_tolerance = postParameters->itemByName("builtin_tolerance")->value(); builtin_tolerance->value(0.01); Ptr<FloatParameterValue> builtin_minimumChordLength = postParameters->itemByName("builtin_minimumChordLength")->value(); builtin_minimumChordLength->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 Ptr<NCProgramPostProcessOptions> postOptions = NCProgramPostProcessOptions::create(); // Ensure toolpaths are visible faceOp->isLightBulbOn(true); adaptiveOp->isLightBulbOn(true); // To avoid errors, post-process only when toolpath generation has completed if (!genFuture) return false; while (!genFuture->isGenerationCompleted()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } newProgram->postProcess(postOptions); // Advise where the NC file is located to indicate completion ui->messageBox( "The result has been written to:\n" + outputFolder + "/" + nc_program_filename->value() + ncExtension, "Post processing is complete \t\t\t\t\t"); return true; }