530,119 active members*
3,513 visitors online*
Register for free
Login
IndustryArena Forum > CAM Software > Autodesk CAM > A working post processor from Fusion 360 to .mmg?
Results 1 to 3 of 3
  1. #1
    Member
    Join Date
    Oct 2019
    Posts
    11

    A working post processor from Fusion 360 to .mmg?

    Hi everyone,

    I have a Laguna Smartshop Maker M with a RichAuto B-57E controller. The controller will only read .mmg files (this according to their company and my own trials). Fusion 360 is currently my best available option for CAD/CAM. Laguna has a .cps for seemingly every other model except mine which produces .prg files. Autodesk recommended I simply change the file extension to .mmg, which I did. This allowed my controller to read the file, but not run it AND the file corrupted my controller: it deleted nearly all machine parameters and added strange values, like xSpeedOfFast became 60 Trillion! It also deleted all of my tool coordinates and the reset took two days (yes, I am a novice.

    I would REALLY like a functioning post processor. Laguna has not returned my calls in more than a week and Autodesk still believes their solution works,and so far has not returned my emails about further testing.

    Any information helps! Thank you all in advance for sharing your wealth of knowledge!

  2. #2
    Member
    Join Date
    Apr 2015
    Posts
    305

    Re: A working post processor from Fusion 360 to .mmg?

    Hello,

    let me know, maybe i can help you.

    Im a programmer focuse on a postprocessor also for Autodesk Cam, I have many experience with CNC and javascript postprocessor. Let me know on m.skotak@cadcam-softcz.cz if you are interested.
    Alphacam post and VBA macros, Autodesk HSM post.
    www.cadcam-softcz.cz

  3. #3
    Member
    Join Date
    Oct 2019
    Posts
    11
    Quote Originally Posted by Maroslav4 View Post
    Hello,

    let me know, maybe i can help you.

    Im a programmer focuse on a postprocessor also for Autodesk Cam, I have many experience with CNC and javascript postprocessor. Let me know on m.skotak@cadcam-softcz.cz if you are interested.
    Hi there--I am interested in your help, for sure! What do you need from me?

  4. #4
    Registered
    Join Date
    Jun 2008
    Posts
    1824

    Re: A working post processor from Fusion 360 to .mmg?

    Quote Originally Posted by KannaKraft View Post
    Hi everyone,

    I have a Laguna Smartshop Maker M with a RichAuto B-57E controller. The controller will only read .mmg files (this according to their company and my own trials). Fusion 360 is currently my best available option for CAD/CAM. Laguna has a .cps for seemingly every other model except mine which produces .prg files. Autodesk recommended I simply change the file extension to .mmg, which I did. This allowed my controller to read the file, but not run it AND the file corrupted my controller: it deleted nearly all machine parameters and added strange values, like xSpeedOfFast became 60 Trillion! It also deleted all of my tool coordinates and the reset took two days (yes, I am a novice.

    I would REALLY like a functioning post processor. Laguna has not returned my calls in more than a week and Autodesk still believes their solution works,and so far has not returned my emails about further testing.

    Any information helps! Thank you all in advance for sharing your wealth of knowledge!
    How did Autodesk tell you to change the file extension from .prg to .mmg ?
    Did you do it by just changing the extension on the nc file or did you/they make the change in the Post Processor so that the PP outputs with a .mmg file extension??

    It should be done by editing the Post Processor in Notepad, Wordpad or similar Text Editor and finding the place where it has "prg" for the extension, change that to "mmg" and save the file, don`t do a "save as", just a Save !!

    Regards
    Rob

  5. #5
    Registered
    Join Date
    Jun 2008
    Posts
    1824

    Re: A working post processor from Fusion 360 to .mmg?

    P.S. Here is the Laguna Post edited to output with the .mmg extension.
    I have tested the PP in my Predator Text Editor using the "Compare" facility with it set to both .prg and .mmg extensions and the code is exactly the same
    in both extension formats so if the extension is correct then the code should be accepted and run in the control.

    If you are not sure how to copy/paste the PP file into your PP library let us know, best to put it in your "Personal" library as it won`t get overwritten by any Fusion updates in there

    Regards
    Rob

  6. #6
    Member
    Join Date
    Apr 2015
    Posts
    305

    Re: A working post processor from Fusion 360 to .mmg?

    If still want it. I need output which you want from a Fusion.

    m.skotak@cadcam-softcz,cz
    Alphacam post and VBA macros, Autodesk HSM post.
    www.cadcam-softcz.cz

  7. #7
    Member
    Join Date
    Oct 2019
    Posts
    11

    Re: A working post processor from Fusion 360 to .mmg?

    Quote Originally Posted by The Engine Guy View Post
    How did Autodesk tell you to change the file extension from .prg to .mmg ?
    Did you do it by just changing the extension on the nc file or did you/they make the change in the Post Processor so that the PP outputs with a .mmg file extension??

    It should be done by editing the Post Processor in Notepad, Wordpad or similar Text Editor and finding the place where it has "prg" for the extension, change that to "mmg" and save the file, don`t do a "save as", just a Save !!

    Regards
    Rob
    Hi Rob! My account is working again randomly so here goes again: I did try changing the extension in the .cps file and that is when **** hit the fan--all my machine coordinates and tool coordinates were deleted, though my controller was able to preview the tool paths. Below is the new post and here is the issue: the code looks fine but in the post output window in Fusion, the old .cps file will change the NC extension value but the the new one won't--it stays as default .nc and exports and error log.

    See Attached: Screenshot of the Old .cps: Far Left, Screenshot of the new .cps: Middle (both have same extension value), Fusion Post Output with unchanged NC value: Right:

  8. #8
    Member
    Join Date
    Oct 2019
    Posts
    11

    Re: A working post processor from Fusion 360 to .mmg?

    This site won't let me upload the .cps files so here is the new file, in-full:

    /**
    *** This post was customized to work with Laguna Tools by NexGenCAM LLC ***
    If you are using this post and would like additional changes and updates to better align this post with your programming and machining needs, please contact NexGenCAM in one of the following ways: support@nexgencam.com , call 888.310.2674, or post your needed changes to this site https://nexgen.desk.com/customer/portal/emails/new?b_id=12678







    */


    description = "Laguna CNC";
    vendorUrl = "NexGenCAM.com && myCAMpost.com"
    vendorUrl = "http://www.lagunatools.com/cnc";
    legal = "Copyright (C) 2019 NexGenCAM, LLC | All Rights Reserved";
    certificationLevel = 2;
    minimumRevision = 40783;

    longDescription = " Post for LAGUNA SmartShop M with ATC";


    extension = "MMG";
    programNameIsInteger = false;
    setCodePage("ascii");

    capabilities = CAPABILITY_MILLING;
    tolerance = spatial(0.002, MM);

    minimumChordLength = spatial(0.25, MM);
    minimumCircularRadius = spatial(0.01, MM);
    maximumCircularRadius = spatial(1000, MM);
    minimumCircularSweep = toRad(0.01);
    maximumCircularSweep = toRad(90);
    allowHelicalMoves = false;
    allowedCircularPlanes = (1 << PLANE_XY); // allow XY plane only



    // user-defined properties
    properties = {
    writeTools: true, // writes the tools
    showSequenceNumbers: true, // show sequence numbers
    sequenceNumberStart: 10, // first sequence number
    sequenceNumberIncrement: 1, // increment for sequence numbers
    optionalStop: false, // optional stop
    separateWordsWithSpace: true, // specifies that the words should be separated with a white space
    useRadius: false, // specifies that arcs should be output using the radius (R word) instead of the I, J, and K words
    showNotes: false // specifies that operation notes should be output.
    };

    // user-defined property definitions
    propertyDefinitions = {
    writeTools: {title:"Write tool list", description:"Output a tool list in the header of the code.", group:0, type:"boolean"},
    showSequenceNumbers: {title:"Use sequence numbers", description:"Use sequence numbers for each block of outputted code.", group:1, type:"boolean"},
    sequenceNumberStart: {title:"Start sequence number", description:"The number at which to start the sequence numbers.", group:1, type:"integer"},
    sequenceNumberIncrement: {title:"Sequence number increment", description:"The amount by which the sequence number is incremented by in each block.", group:1, type:"integer"},
    optionalStop: {title:"Optional stop", description:"Outputs optional stop code during when necessary in the code.", type:"boolean"},
    separateWordsWithSpace: {title:"Separate words with space", description:"Adds spaces between words if 'yes' is selected.", type:"boolean"},
    useRadius: {title:"Radius arcs", description:"If yes is selected, arcs are outputted using radius values rather than IJK.", type:"boolean"},
    showNotes: {title:"Show notes", description:"Writes operation notes as comments in the outputted code.", type:"boolean"}
    };

    var singleLineCoolant = false; // specifies to output multiple coolant codes in one line rather than in separate lines
    // samples:
    // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89}
    // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]}
    var coolants = [
    {id: COOLANT_FLOOD, on: 8},
    {id: COOLANT_MIST},
    {id: COOLANT_THROUGH_TOOL},
    {id: COOLANT_AIR},
    {id: COOLANT_AIR_THROUGH_TOOL},
    {id: COOLANT_SUCTION},
    {id: COOLANT_FLOOD_MIST},
    {id: COOLANT_FLOOD_THROUGH_TOOL},
    {id: COOLANT_OFF, off: 9}
    ];

    var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-:";

    var gFormat = createFormat({prefix:"G", width:2, zeropad:true, decimals:1});
    var mFormat = createFormat({prefix:"M", width:2, zeropad:true, decimals:1});
    var hFormat = createFormat({prefix:"H", width:2, zeropad:true, decimals:1});
    var dFormat = createFormat({prefix:"D", width:2, zeropad:true, decimals:1});

    var xyzFormat = createFormat({decimalsunit == MM ? 3 : 4), forceDecimal:true, trim:false});
    var ijkFormat = createFormat({decimals:6, forceDecimal:true}); // unitless
    var rFormat = xyzFormat; // radius
    var abcFormat = createFormat({decimals:3, forceDecimal:true, scaleEG});
    var feedFormat = createFormat({decimalsunit == MM ? 0 : 1), forceDecimal:true});
    var toolFormat = createFormat({decimals:0});
    var rpmFormat = createFormat({decimals:0});
    var secFormat = createFormat({decimals:3}); // seconds - range 0.001-99999.999
    var taperFormat = createFormat({decimals:1, scaleEG});

    var xOutput = createVariable({prefix:"X"}, xyzFormat);
    var yOutput = createVariable({prefix:"Y"}, xyzFormat);
    var zOutput = createVariable({onchange:function () {retracted = false;}, prefix:"Z"}, xyzFormat);
    var aOutput = createVariable({prefix:"A"}, abcFormat);
    var bOutput = createVariable({prefix:"B"}, abcFormat);
    var cOutput = createVariable({prefix:"C"}, abcFormat);
    var feedOutput = createVariable({prefix:"F"}, feedFormat);
    var sOutput = createVariable({prefix:"S", force:true}, rpmFormat);
    var dOutput = createVariable({}, dFormat);

    // circular output
    var iOutput = createReferenceVariable({prefix:"I"}, xyzFormat);
    var jOutput = createReferenceVariable({prefix:"J"}, xyzFormat);
    var kOutput = createReferenceVariable({prefix:"K"}, xyzFormat);

    var gMotionModal = createModal({force:true}, gFormat); // modal group 1 // G0-G3, ...
    var gPlaneModal = createModal({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19
    var gAbsIncModal = createModal({}, gFormat); // modal group 3 // G90-91
    var gFeedModeModal = createModal({force:true}, gFormat); // modal group 5 // G94-95
    var gUnitModal = createModal({force:true}, gFormat); // modal group 6 // G70-71
    var gCycleModal = createModal({force:true}, gFormat); // modal group 9 // G81, ...
    var gRetractModal = createModal({force:true}, gFormat); // modal group 10 // G98-99
    var gRotationModal = createModal({}, gFormat); // modal group 16 // G68-G69

    // fixed settings
    var firstFeedParameter = 500;
    var useMultiAxisFeatures = false;
    var forceMultiAxisIndexing = false; // force multi-axis indexing for 3D programs
    var cancelTiltFirst = false; // cancel G68.2 with G69 prior to G54-G59 WCS block
    var useABCPrepositioning = false; // position ABC axes prior to G68.2 block

    var WARNING_WORK_OFFSET = 0;

    // collected state
    var sequenceNumber;
    var currentWorkOffset;
    var optionalSection = false;
    var forceSpindleSpeed = false;
    var activeMovements; // do not use by default
    var currentFeedId;
    var retracted = false; // specifies that the tool has been retracted to the safe plane


    /**
    Writes the specified block.
    */
    function writeBlock() {
    var text = formatWords(arguments);
    if (!text) {
    return;
    }
    if (properties.showSequenceNumbers) {
    if (optionalSection) {
    if (text) {
    writeWords("/", "N" + sequenceNumber, text);
    }
    } else {
    writeWords2("N" + sequenceNumber, arguments);
    }
    sequenceNumber += properties.sequenceNumberIncrement;
    } else {
    if (optionalSection) {
    writeWords2("/", arguments);
    } else {
    writeWords(arguments);
    }
    }
    }

    /**
    Writes the specified optional block.
    */
    function writeOptionalBlock() {
    if (properties.showSequenceNumbers) {
    var words = formatWords(arguments);
    if (words) {
    writeWords("/", "N" + sequenceNumber, words);
    sequenceNumber += properties.sequenceNumberIncrement;
    }
    } else {
    writeWords2("/", arguments);
    }
    }

    function formatComment(text) {
    return "(" + filterText(String(text).toUpperCase(), permittedCommentChars).replace(/[()]/g, "") + ")";
    }

    /**
    Output a comment.
    */
    function writeComment(text) {
    writeln(formatComment(text));
    }

    function onOpen() {
    if (properties.useRadius) {
    maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC
    }
    gRotationModal.format(69); // Default to G69 Rotation Off

    if (false) { // note: setup your machine here
    var aAxis = createAxis({coordinate:0, table:false, axis:[1, 0, 0], range:[-360, 360], preference:1});
    var cAxis = createAxis({coordinate:2, table:false, axis:[0, 0, 1], range:[-360, 360], preference:1});
    machineConfiguration = new MachineConfiguration(aAxis, cAxis);

    setMachineConfiguration(machineConfiguration);
    optimizeMachineAngles2(0); // TCP mode
    }

    if (!machineConfiguration.isMachineCoordinate(0)) {
    aOutput.disable();
    }
    if (!machineConfiguration.isMachineCoordinate(1)) {
    bOutput.disable();
    }
    if (!machineConfiguration.isMachineCoordinate(2)) {
    cOutput.disable();
    }

    if (!properties.separateWordsWithSpace) {
    setWordSeparator("");
    }

    sequenceNumber = properties.sequenceNumberStart;

    var partName = hasGlobalParameter("document-path") ? FileSystem.getFilename(getGlobalParameter("documen t-path")) : "";


    var workpiece = getWorkpiece();
    var delta = Vector.diff(workpiece.upper, workpiece.lower);

    writeComment("Program name: " + programName);
    writeComment("Machine: " + "Laguna SmartShop M ATC");
    writeComment("Program comment: " + programComment);
    writeComment("Material Size");
    writeComment("X=" + xyzFormat.format(delta.x) + " " + "Y=" + xyzFormat.format(delta.y) + " " + "Z=" + xyzFormat.format(delta.z));
    /* writeComment("File Name: " + partName); */

    // dump tool information
    if (properties.writeTools) {
    var zRanges = {};
    if (is3D()) {
    var numberOfSections = getNumberOfSections();
    for (var i = 0; i < numberOfSections; ++i) {
    var section = getSection(i);
    var zRange = section.getGlobalZRange();
    var tool = section.getTool();
    if (zRanges[tool.number]) {
    zRanges[tool.number].expandToRange(zRange);
    } else {
    zRanges[tool.number] = zRange;
    }
    }
    }

    var tools = getToolTable();
    if (tools.getNumberOfTools() > 0) {
    for (var i = 0; i < tools.getNumberOfTools(); ++i) {
    var tool = tools.getTool(i);
    var comment = "T" + toolFormat.format(tool.number) + " " +
    "D=" + xyzFormat.format(tool.diameter) + " " +
    localize("CR") + "=" + xyzFormat.format(tool.cornerRadius);
    if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) {
    comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg");
    }
    if (zRanges[tool.number]) {
    comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum());
    }
    comment += " - " + getToolTypeName(tool.type);
    writeComment(comment);
    }
    }
    }

    if (false) {
    // check for duplicate tool number
    for (var i = 0; i < getNumberOfSections(); ++i) {
    var sectioni = getSection(i);
    var tooli = sectioni.getTool();
    for (var j = i + 1; j < getNumberOfSections(); ++j) {
    var sectionj = getSection(j);
    var toolj = sectionj.getTool();
    if (tooli.number == toolj.number) {
    if (xyzFormat.areDifferent(tooli.diameter, toolj.diameter) ||
    xyzFormat.areDifferent(tooli.cornerRadius, toolj.cornerRadius) ||
    abcFormat.areDifferent(tooli.taperAngle, toolj.taperAngle) ||
    (tooli.numberOfFlutes != toolj.numberOfFlutes)) {
    error(
    subst(
    localize("Using the same tool number for different cutter geometry for operation '%1' and '%2'."),
    sectioni.hasParameter("operation-comment") ? sectioni.getParameter("operation-comment") : ("#" + (i + 1)),
    sectionj.hasParameter("operation-comment") ? sectionj.getParameter("operation-comment") : ("#" + (j + 1))
    )
    );
    return;
    }
    }
    }
    }
    }

    if ((getNumberOfSections() > 0) && (getSection(0).workOffset == 0)) {
    for (var i = 0; i < getNumberOfSections(); ++i) {
    if (getSection(i).workOffset > 0) {
    error(localize("Using multiple work offsets is not possible if the initial work offset is 0."));
    return;
    }
    }
    }


    gPlaneModal.format(17);
    gAbsIncModal.format(90);








    }

    function onComment(message) {
    var comments = String(message).split(";");
    for (comment in comments) {
    writeComment(comments[comment]);
    }
    }

    /** Force output of X, Y, and Z. */
    function forceXYZ() {
    xOutput.reset();
    yOutput.reset();
    zOutput.reset();
    }

    /** Force output of A, B, and C. */
    function forceABC() {
    aOutput.reset();
    bOutput.reset();
    cOutput.reset();
    }

    function forceFeed() {
    currentFeedId = undefined;
    feedOutput.reset();
    }

    /** Force output of X, Y, Z, A, B, C, and F on next output. */
    function forceAny() {
    forceXYZ();
    forceABC();
    forceFeed();
    }



    function FeedContext(id, description, feed) {
    this.id = id;
    this.description = description;
    this.feed = feed;
    }

    function getFeed(f) {
    if (activeMovements) {
    var feedContext = activeMovements[movement];
    if (feedContext != undefined) {
    if (!feedFormat.areDifferent(feedContext.feed, f)) {
    if (feedContext.id == currentFeedId) {
    return ""; // nothing has changed
    }
    forceFeed();
    currentFeedId = feedContext.id;
    return "F#" + (firstFeedParameter + feedContext.id);
    }
    }
    currentFeedId = undefined; // force Q feed next time
    }
    return feedOutput.format(f); // use feed value
    }

    function initializeActiveFeeds() {
    activeMovements = new Array();
    var movements = currentSection.getMovements();

    var id = 0;
    var activeFeeds = new Array();
    if (hasParameter("operation:tool_feedCutting")) {
    if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) {
    var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_CUTTING] = feedContext;
    activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext;
    activeMovements[MOVEMENT_EXTENDED] = feedContext;
    }
    ++id;
    if (movements & (1 << MOVEMENT_PREDRILL)) {
    feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting"));
    activeMovements[MOVEMENT_PREDRILL] = feedContext;
    activeFeeds.push(feedContext);
    }
    ++id;
    }

    if (hasParameter("operation:finishFeedrate")) {
    if (movements & (1 << MOVEMENT_FINISH_CUTTING)) {
    var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext;
    }
    ++id;
    } else if (hasParameter("operation:tool_feedCutting")) {
    if (movements & (1 << MOVEMENT_FINISH_CUTTING)) {
    var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext;
    }
    ++id;
    }

    if (hasParameter("operation:tool_feedEntry")) {
    if (movements & (1 << MOVEMENT_LEAD_IN)) {
    var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_LEAD_IN] = feedContext;
    }
    ++id;
    }

    if (hasParameter("operation:tool_feedExit")) {
    if (movements & (1 << MOVEMENT_LEAD_OUT)) {
    var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_LEAD_OUT] = feedContext;
    }
    ++id;
    }

    if (hasParameter("operation:noEngagementFeedrate")) {
    if (movements & (1 << MOVEMENT_LINK_DIRECT)) {
    var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_LINK_DIRECT] = feedContext;
    }
    ++id;
    } else if (hasParameter("operation:tool_feedCutting") &&
    hasParameter("operation:tool_feedEntry") &&
    hasParameter("operation:tool_feedExit")) {
    if (movements & (1 << MOVEMENT_LINK_DIRECT)) {
    var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting" ), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit")));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_LINK_DIRECT] = feedContext;
    }
    ++id;
    }

    if (hasParameter("operation:reducedFeedrate")) {
    if (movements & (1 << MOVEMENT_REDUCED)) {
    var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_REDUCED] = feedContext;
    }
    ++id;
    }

    if (hasParameter("operation:tool_feedRamp")) {
    if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) {
    var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_RAMP] = feedContext;
    activeMovements[MOVEMENT_RAMP_HELIX] = feedContext;
    activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext;
    activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext;
    }
    ++id;
    }
    if (hasParameter("operation:tool_feedPlunge")) {
    if (movements & (1 << MOVEMENT_PLUNGE)) {
    var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge"));
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_PLUNGE] = feedContext;
    }
    ++id;
    }
    if (true) { // high feed
    if (movements & (1 << MOVEMENT_HIGH_FEED)) {
    var feedContext = new FeedContext(id, localize("High Feed"), this.highFeedrate);
    activeFeeds.push(feedContext);
    activeMovements[MOVEMENT_HIGH_FEED] = feedContext;
    }
    ++id;
    }

    for (var i = 0; i < activeFeeds.length; ++i) {
    var feedContext = activeFeeds[i];
    writeBlock("#" + (firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed), formatComment(feedContext.description));
    }
    }

    var currentWorkPlaneABC = undefined;

    function forceWorkPlane() {
    currentWorkPlaneABC = undefined;
    }

    function cancelWorkPlane() {
    writeBlock(gRotationModal.format(69)); // cancel frame
    forceWorkPlane();
    }

    function setWorkPlane(abc) {
    if (!forceMultiAxisIndexing && is3D() && !machineConfiguration.isMultiAxisConfiguration()) {
    return; // ignore
    }

    if (!((currentWorkPlaneABC == undefined) ||
    abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) ||
    abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) ||
    abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z))) {
    return; // no change
    }

    onCommand(COMMAND_UNLOCK_MULTI_AXIS);
    if (!retracted) {
    writeRetract(Z);
    }

    if (useMultiAxisFeatures) {
    if (cancelTiltFirst) {
    cancelWorkPlane();
    }
    if (machineConfiguration.isMultiAxisConfiguration() && useABCPrepositioning) {
    var angles = abc.isNonZero() ? getWorkPlaneMachineABC(currentSection.workPlane, false, false) : abc;
    gMotionModal.reset();
    writeBlock(
    gMotionModal.format(0),
    conditional(machineConfiguration.isMachineCoordina te(0), "A" + abcFormat.format(angles.x)),
    conditional(machineConfiguration.isMachineCoordina te(1), "B" + abcFormat.format(angles.y)),
    conditional(machineConfiguration.isMachineCoordina te(2), "C" + abcFormat.format(angles.z))
    );
    }
    if (abc.isNonZero()) {
    gRotationModal.reset();
    writeBlock(gRotationModal.format(68.2), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0), "Z" + xyzFormat.format(0), "I" + abcFormat.format(abc.x), "J" + abcFormat.format(abc.y), "K" + abcFormat.format(abc.z)); // set frame
    writeBlock(gFormat.format(53.1)); // turn machine
    } else {
    if (!cancelTiltFirst) {
    cancelWorkPlane();
    }
    }
    } else {
    gMotionModal.reset();
    writeBlock(
    gMotionModal.format(0),
    conditional(machineConfiguration.isMachineCoordina te(0), "A" + abcFormat.format(abc.x)),
    conditional(machineConfiguration.isMachineCoordina te(1), "B" + abcFormat.format(abc.y)),
    conditional(machineConfiguration.isMachineCoordina te(2), "C" + abcFormat.format(abc.z))
    );
    }

    onCommand(COMMAND_LOCK_MULTI_AXIS);

    currentWorkPlaneABC = abc;
    }

    var closestABC = false; // choose closest machine angles
    var currentMachineABC;

    function getWorkPlaneMachineABC(workPlane, _setWorkPlane, rotate) {
    var W = workPlane; // map to global frame

    var abc = machineConfiguration.getABC(W);
    if (closestABC) {
    if (currentMachineABC) {
    abc = machineConfiguration.remapToABC(abc, currentMachineABC);
    } else {
    abc = machineConfiguration.getPreferredABC(abc);
    }
    } else {
    abc = machineConfiguration.getPreferredABC(abc);
    }

    try {
    abc = machineConfiguration.remapABC(abc);
    if (_setWorkPlane) {
    currentMachineABC = abc;
    }
    } catch (e) {
    error(
    localize("Machine angles not supported") + ":"
    + conditional(machineConfiguration.isMachineCoordina te(0), " A" + abcFormat.format(abc.x))
    + conditional(machineConfiguration.isMachineCoordina te(1), " B" + abcFormat.format(abc.y))
    + conditional(machineConfiguration.isMachineCoordina te(2), " C" + abcFormat.format(abc.z))
    );
    }

    var direction = machineConfiguration.getDirection(abc);
    if (!isSameDirection(direction, W.forward)) {
    error(localize("Orientation not supported."));
    }

    if (!machineConfiguration.isABCSupported(abc)) {
    error(
    localize("Work plane is not supported") + ":"
    + conditional(machineConfiguration.isMachineCoordina te(0), " A" + abcFormat.format(abc.x))
    + conditional(machineConfiguration.isMachineCoordina te(1), " B" + abcFormat.format(abc.y))
    + conditional(machineConfiguration.isMachineCoordina te(2), " C" + abcFormat.format(abc.z))
    );
    }

    if (rotate) {
    var tcp = false;
    if (tcp) {
    setRotation(W); // TCP mode
    } else {
    var O = machineConfiguration.getOrientation(abc);
    var R = machineConfiguration.getRemainingOrientation(abc, W);
    setRotation(R);
    }
    }

    return abc;
    }

    function isProbeOperation() {
    return hasParameter("operation-strategy") && (getParameter("operation-strategy") == "probe");
    }

    function onSection() {
    var forceToolAndRetract = optionalSection && !currentSection.isOptional();
    optionalSection = currentSection.isOptional();

    var insertToolCall = forceToolAndRetract || isFirstSection() ||
    currentSection.getForceToolChange && currentSection.getForceToolChange() ||
    (tool.number != getPreviousSection().getTool().number);

    retracted = false;
    var newWorkOffset = isFirstSection() ||
    (getPreviousSection().workOffset != currentSection.workOffset); // work offset changes
    var newWorkPlane = isFirstSection() ||
    !isSameDirection(getPreviousSection().getGlobalFin alToolAxis(), currentSection.getGlobalInitialToolAxis()) ||
    (currentSection.isOptimizedForMachine() && getPreviousSection().isOptimizedForMachine() &&
    Vector.diff(getPreviousSection().getFinalToolAxisA BC(), currentSection.getInitialToolAxisABC()).length > 1e-4) ||
    (!machineConfiguration.isMultiAxisConfiguration() && currentSection.isMultiAxis()) ||
    (!getPreviousSection().isMultiAxis() && currentSection.isMultiAxis() ||
    getPreviousSection().isMultiAxis() && !currentSection.isMultiAxis()); // force newWorkPlane between indexing and simultaneous operations


    writeln("");

    if (hasParameter("operation-comment")) {
    var comment = getParameter("operation-comment");
    if (comment) {
    writeComment(comment);
    }
    }

    if (insertToolCall || newWorkOffset || newWorkPlane) {

    // stop spindle before retract during tool change
    if (insertToolCall && !isFirstSection()) {
    onCommand(COMMAND_STOP_SPINDLE);
    }

    // retract to safe plane
    /* writeRetract(Z); */
    currentWorkOffset = undefined;
    forceXYZ();
    }










    if (properties.showNotes && hasParameter("notes")) {
    var notes = getParameter("notes");
    if (notes) {
    var lines = String(notes).split("\n");
    var r1 = new RegExp("^[\\s]+", "g");
    var r2 = new RegExp("[\\s]+$", "g");
    for (line in lines) {
    var comment = lines[line].replace(r1, "").replace(r2, "");
    if (comment) {
    writeComment(comment);
    }
    }
    }
    }

    // wcs
    var workOffset = currentSection.workOffset;
    if (workOffset == 0) {
    warningOnce(localize("Work offset has not been specified. Using G54 as WCS."), WARNING_WORK_OFFSET);
    workOffset = 1;
    }
    if (workOffset != currentWorkOffset) {
    if (cancelTiltFirst) {
    cancelWorkPlane();
    }
    forceWorkPlane();
    }
    if (workOffset > 0) {
    if (workOffset > 6) {
    error(localize("Work offset out of range."));
    } else {
    if (workOffset != currentWorkOffset) {
    writeBlock(gFormat.format(53 + workOffset)); // G54->G59
    currentWorkOffset = workOffset;
    }
    }
    }

    if (insertToolCall) {
    forceWorkPlane();

    setCoolant(COOLANT_OFF);

    if (!isFirstSection() && properties.optionalStop) {
    onCommand(COMMAND_OPTIONAL_STOP);
    }
    /* writeRetract(X, "M5");
    writeRetract(Y); */
    // writeComment("We could do M0 here to halt if supported");
    // writeComment("Manual tool change");

    if (tool.number > 99) {
    warning(localize("Tool number exceeds maximum value."));
    }
    writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6));
    /* writeBlock("D" + toolFormat.format(tool.number)); */
    if (tool.comment) {
    writeComment(tool.comment);
    }
    var showToolZMin = false;
    if (showToolZMin) {
    if (is3D()) {
    var numberOfSections = getNumberOfSections();
    var zRange = currentSection.getGlobalZRange();
    var number = tool.number;
    for (var i = currentSection.getId() + 1; i < numberOfSections; ++i) {
    var section = getSection(i);
    if (section.getTool().number != number) {
    break;
    }
    zRange.expandToRange(section.getGlobalZRange());
    }
    writeComment(localize("ZMIN") + "=" + zRange.getMinimum());
    }
    }

    /*
    if (properties.preloadTool) {
    var nextTool = getNextTool(tool.number);
    if (nextTool) {
    writeBlock("T" + toolFormat.format(nextTool.number));
    } else {
    // preload first tool
    var section = getSection(0);
    var firstToolNumber = section.getTool().number;
    if (tool.number != firstToolNumber) {
    writeBlock("T" + toolFormat.format(firstToolNumber));
    }
    }
    }
    */
    }
























    if (insertToolCall ||
    forceSpindleSpeed ||
    isFirstSection() ||
    (rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent())) ||
    (tool.clockwise != getPreviousSection().getTool().clockwise)) {
    forceSpindleSpeed = false;

    if (spindleSpeed < 1) {
    error(localize("Spindle speed out of range."));
    return;
    }
    if (spindleSpeed > 99999) {
    warning(localize("Spindle speed exceeds maximum value."));
    }
    writeBlock(
    sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)
    );


    if (forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) {
    // writeBlock(mFormat.format(xxx)); // shortest path traverse
    }

    }

    forceXYZ();

    if (forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) { // use 5-axis indexing for multi-axis mode
    // set working plane after datum shift

    if (currentSection.isMultiAxis()) {
    forceWorkPlane();
    cancelTransformation();
    } else {
    var abc = new Vector(0, 0, 0);
    if (useMultiAxisFeatures) {
    var euler = currentSection.workPlane.getEuler2(EULER_ZXZ_R);
    abc = new Vector(euler.x, euler.y, euler.z);
    cancelTransformation();
    } else {
    abc = getWorkPlaneMachineABC(currentSection.workPlane, true, true);
    }
    setWorkPlane(abc);
    }
    } else { // pure 3D
    var remaining = currentSection.workPlane;
    if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) {
    error(localize("Tool orientation is not supported."));
    return;
    }
    setRotation(remaining);
    }

    // set coolant after we have positioned at Z
    // setCoolant(tool.coolant);

    forceAny();
    gMotionModal.reset();

    var initialPosition = getFramePosition(currentSection.getInitialPosition ());
    if (!retracted && !insertToolCall) {
    if (getCurrentPosition().z < initialPosition.z) {
    writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z));
    }
    }

    if (insertToolCall || retracted || (!isFirstSection() && getPreviousSection().isMultiAxis())) {
    var lengthOffset = tool.lengthOffset;
    if (lengthOffset > 99) {
    error(localize("Length offset out of range."));
    return;
    }

    gMotionModal.reset();
    writeBlock(gPlaneModal.format(17));

    // assumes a Head configuration uses TCP on a Fanuc controller
    var offsetCode = 43;
    if (currentSection.isMultiAxis()) {
    if (machineConfiguration.isMultiAxisConfiguration() && (currentSection.getOptimizedTCPMode() == 0)) {
    offsetCode = 43.4;
    } else if (!machineConfiguration.isMultiAxisConfiguration()) {
    offsetCode = 43.5;
    }
    }

    if (!machineConfiguration.isHeadConfiguration()) {
    writeBlock(
    gAbsIncModal.format(90),
    gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y)
    );
    writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z));
    } else {
    writeBlock(
    gAbsIncModal.format(90),
    gMotionModal.format(0),
    gFormat.format(offsetCode),
    xOutput.format(initialPosition.x),
    yOutput.format(initialPosition.y),
    zOutput.format(initialPosition.z), hFormat.format(lengthOffset)
    );
    }

    gMotionModal.reset();
    } else {
    writeBlock(
    gAbsIncModal.format(90),
    gMotionModal.format(0),
    xOutput.format(initialPosition.x),
    yOutput.format(initialPosition.y)
    );
    }


    /*
    if (properties.useParametricFeed &&
    hasParameter("operation-strategy") &&
    (getParameter("operation-strategy") != "drill") && // legacy
    !(currentSection.hasAnyCycle && currentSection.hasAnyCycle())) {
    if (!insertToolCall &&
    activeMovements &&
    (getCurrentSectionId() > 0) &&
    ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) {
    // use the current feeds
    } else {
    initializeActiveFeeds();
    }
    } else {
    activeMovements = undefined;
    }
    */
    }

    function onDwell(seconds) {
    if (seconds > 99999.999) {
    warning(localize("Dwelling time is out of range."));
    }
    writeBlock(/*gFeedModeModal.format(94),*/ gFormat.format(4), secFormat.format(seconds));
    }

    function onSpindleSpeed(spindleSpeed) {
    writeBlock(sOutput.format(spindleSpeed));
    }

    function onCycle() {
    writeBlock(gPlaneModal.format(17));
    }

    function getCommonCycle(x, y, z, r) {
    forceXYZ(); // force xyz on first drill hole of any cycle
    return [xOutput.format(x), yOutput.format(y),
    zOutput.format(z),
    "R" + xyzFormat.format(r)];
    }

    function onCyclePoint(x, y, z) {
    // this control does not support drilling canned cycles G81-86
    expandCyclePoint(x, y, z);
    }

    var pendingRadiusCompensation = -1;

    function onRadiusCompensation() {
    pendingRadiusCompensation = radiusCompensation;
    }

    function onRapid(_x, _y, _z) {
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    if (x || y || z) {
    if (pendingRadiusCompensation >= 0) {
    error(localize("Radius compensation mode cannot be changed at rapid traversal."));
    return;
    }
    writeBlock(gMotionModal.format(0), x, y, z);
    forceFeed();
    }
    }

    function onLinear(_x, _y, _z, feed) {
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    var f = getFeed(feed);
    if (x || y || z) {
    if (pendingRadiusCompensation >= 0) {
    pendingRadiusCompensation = -1;
    var d = tool.diameterOffset;
    if (d > 99) {
    warning(localize("The diameter offset exceeds the maximum value."));
    }
    writeBlock(gPlaneModal.format(17));
    switch (radiusCompensation) {
    case RADIUS_COMPENSATION_LEFT:
    dOutput.reset();
    writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, dOutput.format(d), f);
    break;
    case RADIUS_COMPENSATION_RIGHT:
    dOutput.reset();
    writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, dOutput.format(d), f);
    break;
    default:
    writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f);
    }
    } else {
    writeBlock(gMotionModal.format(1), x, y, z, f);
    }
    } else if (f) {
    if (getNextRecord().isMotion()) { // try not to output feed without motion
    forceFeed(); // force feed on next line
    } else {
    writeBlock(gMotionModal.format(1), f);
    }
    }
    }

    function onRapid5D(_x, _y, _z, _a, _b, _c) {
    if (pendingRadiusCompensation >= 0) {
    error(localize("Radius compensation mode cannot be changed at rapid traversal."));
    return;
    }
    if (currentSection.isOptimizedForMachine()) {
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    var a = aOutput.format(_a);
    var b = bOutput.format(_b);
    var c = cOutput.format(_c);
    writeBlock(gMotionModal.format(0), x, y, z, a, b, c);
    } else {
    forceXYZ();
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    var i = ijkFormat.format(_a);
    var j = ijkFormat.format(_b);
    var k = ijkFormat.format(_c);
    writeBlock(gMotionModal.format(0), x, y, z, "I" + i, "J" + j, "K" + k);
    }
    forceFeed();
    }

    function onLinear5D(_x, _y, _z, _a, _b, _c, feed) {
    if (pendingRadiusCompensation >= 0) {
    error(localize("Radius compensation cannot be activated/deactivated for 5-axis move."));
    return;
    }

    if (currentSection.isOptimizedForMachine()) {
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    var a = aOutput.format(_a);
    var b = bOutput.format(_b);
    var c = cOutput.format(_c);
    var f = getFeed(feed);
    if (x || y || z || a || b || c) {
    writeBlock(gMotionModal.format(1), x, y, z, a, b, c, f);
    } else if (f) {
    if (getNextRecord().isMotion()) { // try not to output feed without motion
    forceFeed(); // force feed on next line
    } else {
    writeBlock(gMotionModal.format(1), f);
    }
    }
    } else {
    forceXYZ();
    var x = xOutput.format(_x);
    var y = yOutput.format(_y);
    var z = zOutput.format(_z);
    var i = ijkFormat.format(_a);
    var j = ijkFormat.format(_b);
    var k = ijkFormat.format(_c);
    var f = getFeed(feed);
    if (x || y || z || i || j || k) {
    writeBlock(gMotionModal.format(1), x, y, z, "I" + i, "J" + j, "K" + k, f);
    } else if (f) {
    if (getNextRecord().isMotion()) { // try not to output feed without motion
    forceFeed(); // force feed on next line
    } else {
    writeBlock(gMotionModal.format(1), f);
    }
    }
    }
    }

    function onCircular(clockwise, cx, cy, cz, x, y, z, feed) {
    if (pendingRadiusCompensation >= 0) {
    error(localize("Radius compensation cannot be activated/deactivated for a circular move."));
    return;
    }

    var start = getCurrentPosition();

    if (isFullCircle()) {
    if (properties.useRadius || isHelical()) { // radius mode does not support full arcs
    linearize(tolerance);
    return;
    }
    switch (getCircularPlane()) {
    case PLANE_XY:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed));
    break;
    case PLANE_ZX:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed));
    break;
    case PLANE_YZ:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed));
    break;
    default:
    linearize(tolerance);
    }
    } else if (!properties.useRadius) {
    switch (getCircularPlane()) {
    case PLANE_XY:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed));
    break;
    case PLANE_ZX:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed));
    break;
    case PLANE_YZ:
    writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed));
    break;
    default:
    linearize(tolerance);
    }
    } else { // use radius mode
    var r = getCircularRadius();
    if (toDeg(getCircularSweep()) > (180 + 1e-9)) {
    r = -r; // allow up to <360 deg arcs
    }
    switch (getCircularPlane()) {
    case PLANE_XY:
    writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed));
    break;
    case PLANE_ZX:
    writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed));
    break;
    case PLANE_YZ:
    writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed));
    break;
    default:
    linearize(tolerance);
    }
    }
    }

    var currentCoolantMode = COOLANT_OFF;
    var coolantOff = undefined;

    function setCoolant(coolant) {
    var coolantCodes = getCoolantCodes(coolant);
    if (Array.isArray(coolantCodes)) {
    if (singleLineCoolant) {
    writeBlock(coolantCodes.join(getWordSeparator()));
    } else {
    for (var c in coolantCodes) {
    writeBlock(coolantCodes[c]);
    }
    }
    return undefined;
    }
    return coolantCodes;
    }

    function getCoolantCodes(coolant) {
    var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line
    if (!coolants) {
    error(localize("Coolants have not been defined."));
    }
    if (isProbeOperation()) { // avoid coolant output for probing
    coolant = COOLANT_OFF;
    }
    if (coolant == currentCoolantMode) {
    return undefined; // coolant is already active
    }
    if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined)) {
    if (Array.isArray(coolantOff)) {
    for (var i in coolantOff) {
    multipleCoolantBlocks.push(mFormat.format(coolantO ff[i]));
    }
    } else {
    multipleCoolantBlocks.push(mFormat.format(coolantO ff));
    }
    }

    var m;
    var coolantCodes = {};
    for (var c in coolants) { // find required coolant codes into the coolants array
    if (coolants[c].id == coolant) {
    coolantCodes.on = coolants[c].on;
    if (coolants[c].off != undefined) {
    coolantCodes.off = coolants[c].off;
    break;
    } else {
    for (var i in coolants) {
    if (coolants[i].id == COOLANT_OFF) {
    coolantCodes.off = coolants[i].off;
    break;
    }
    }
    }
    }
    }
    if (coolant == COOLANT_OFF) {
    m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified
    } else {
    coolantOff = coolantCodes.off;
    m = coolantCodes.on;
    }

    if (!m) {
    onUnsupportedCoolant(coolant);
    m = 9;
    } else {
    if (Array.isArray(m)) {
    for (var i in m) {
    multipleCoolantBlocks.push(mFormat.format(m[i]));
    }
    } else {
    multipleCoolantBlocks.push(mFormat.format(m));
    }
    currentCoolantMode = coolant;
    return multipleCoolantBlocks; // return the single formatted coolant value
    }
    return undefined;
    }

    var mapCommand = {
    COMMAND_STOP:0,
    COMMAND_OPTIONAL_STOP:1,
    COMMAND_END:2,
    COMMAND_SPINDLE_CLOCKWISE:3,
    COMMAND_SPINDLE_COUNTERCLOCKWISE:4,
    COMMAND_STOP_SPINDLE:5,
    COMMAND_ORIENTATE_SPINDLE:19
    };

    function onCommand(command) {
    switch (command) {
    case COMMAND_STOP:
    writeBlock(mFormat.format(0));
    forceSpindleSpeed = true;
    return;
    case COMMAND_START_SPINDLE:
    onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE);
    return;
    case COMMAND_LOCK_MULTI_AXIS:
    return;
    case COMMAND_UNLOCK_MULTI_AXIS:
    return;
    case COMMAND_START_CHIP_TRANSPORT:
    return;
    case COMMAND_STOP_CHIP_TRANSPORT:
    return;
    case COMMAND_BREAK_CONTROL:
    return;
    case COMMAND_TOOL_MEASURE:
    return;
    }

    var stringId = getCommandStringId(command);
    var mcode = mapCommand[stringId];
    if (mcode != undefined) {
    writeBlock(mFormat.format(mcode));
    } else {
    onUnsupportedCommand(command);
    }
    }

    function onSectionEnd() {
    writeBlock(gPlaneModal.format(17));
    if (!isLastSection() && (getNextSection().getTool().coolant != tool.coolant)) {
    setCoolant(COOLANT_OFF);
    }
    if (((getCurrentSectionId() + 1) >= getNumberOfSections()) ||
    (tool.number != getNextSection().getTool().number)) {
    onCommand(COMMAND_BREAK_CONTROL);
    }

    forceAny();
    }

    /** Output block to do safe retract and/or move to home position. */
    function writeRetract() {
    if (arguments.length == 0) {
    error(localize("No axis specified for writeRetract()."));
    return;
    }
    var words = []; // store all retracted axes in an array
    for (var i = 0; i < arguments.length; ++i) {
    let instances = 0; // checks for duplicate retract calls
    for (var j = 0; j < arguments.length; ++j) {
    if (arguments[i] == arguments[j]) {
    ++instances;
    }
    }
    if (instances > 1) { // error if there are multiple retract calls for the same axis
    error(localize("Cannot retract the same axis twice in one line"));
    return;
    }
    switch (arguments[i]) {
    case X:
    words.push("X" + xyzFormat.format(machineConfiguration.hasHomePosit ionX() ? machineConfiguration.getHomePositionX() : 0));
    break;
    case Y:
    words.push("Y" + xyzFormat.format(machineConfiguration.hasHomePosit ionY() ? machineConfiguration.getHomePositionY() : 0));
    break;
    case Z:
    writeBlock("D0");
    writeBlock(gMotionModal.format(0), zOutput.format(0));
    retracted = true; // specifies that the tool has been retracted to the safe plane
    break;
    case "M5":
    words.push(mFormat.format(5));
    break;
    default:
    error(localize("Bad axis specified for writeRetract()."));
    return;
    }
    }
    if (words.length > 0) {
    gMotionModal.reset();
    writeBlock(gFormat.format(53));
    currentWorkOffset = undefined;
    writeBlock(gMotionModal.format(0), words); // retract
    }
    zOutput.reset();
    }

    function onClose() {
    writeln("");
    optionalSection = false;

    /* writeRetract(Z);
    writeRetract(X, "M5");
    writeRetract(Y); */
    onImpliedCommand(COMMAND_END);
    onCommand(COMMAND_STOP_SPINDLE);
    writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
    writeln("%");
    }

  9. #9
    Member
    Join Date
    Oct 2019
    Posts
    11

    Re: A working post processor from Fusion 360 to .mmg?

    Quote Originally Posted by Maroslav4 View Post
    If still want it. I need output which you want from a Fusion.

    m.skotak@cadcam-softcz,cz
    .mmg, plz! See below for Laguna's full .cps that still doesn't work!

  10. #10
    Registered
    Join Date
    Jun 2008
    Posts
    1824

    Re: A working post processor from Fusion 360 to .mmg?

    Hi, sorry but I am not sure exactly what you are trying to do, you are mentioning a .nc file and I don`t see that extension used anywhere, did you not open the file
    I posted earlier and try out the PP in the Zip file?? That PP does output the G code file with the .mmg extension so I am not seeing what the problem is??

    If you want to upload files that are not native to the CNC Zone then put them in a Zip file and they will then upload as I did.

    Here is the code as output with the .mmg extension that I generated here, I have put it in a Zip file for you, just open the Zip file and then copy/paste the
    .mmg file to somewhere on your PC, if it is the correct extension format then your control should accept and run the code.

    Regards
    Rob

  11. #11
    Member
    Join Date
    Oct 2019
    Posts
    11

    Re: A working post processor from Fusion 360 to .mmg?

    Quote Originally Posted by The Engine Guy View Post
    Hi, sorry but I am not sure exactly what you are trying to do, you are mentioning a .nc file and I don`t see that extension used anywhere, did you not open the file
    I posted earlier and try out the PP in the Zip file?? That PP does output the G code file with the .mmg extension so I am not seeing what the problem is??

    If you want to upload files that are not native to the CNC Zone then put them in a Zip file and they will then upload as I did.

    Here is the code as output with the .mmg extension that I generated here, I have put it in a Zip file for you, just open the Zip file and then copy/paste the
    .mmg file to somewhere on your PC, if it is the correct extension format then your control should accept and run the code.

    Regards
    Rob
    Hi--sorry to be confusing. The jist is that I need a special post to operate my machine. A company called nexgencam created one for me because the one that the cnc company gave me (Laguna Tools) didn't work properly and caused a crazy problem in my RichAuto B-57E controller. The new file won't even export proper files from Fusion 360 (.nc is a form value in Fusion 360 that should take its value from the extension = "MMG"; line in the .cps file, but the new processor does not do this and I cannot make it do this, for some reason

  12. #12
    Member
    Join Date
    Oct 2019
    Posts
    11

    Re: A working post processor from Fusion 360 to .mmg?

    Quote Originally Posted by KannaKraft View Post
    Hi--sorry to be confusing. The jist is that I need a special post to operate my machine. A company called nexgencam created one for me because the one that the cnc company gave me (Laguna Tools) didn't work properly and caused a crazy problem in my RichAuto B-57E controller. The new file won't even export proper files from Fusion 360 (.nc is a form value in Fusion 360 that should take its value from the extension = "MMG"; line in the .cps file, but the new processor does not do this and I cannot make it do this, for some reason
    It SHOULD output with the .mmg extension but it doesn't. It doesn't output at all--just runs an error log, I believe, because of whatever is causing it to not fill the Numerical Controller field in Fusion 360. Don't know the cause of this though

  13. #13
    Registered
    Join Date
    Jun 2008
    Posts
    1824

    Re: A working post processor from Fusion 360 to .mmg?

    OK, which PP are we talking about?

    The one I uploaded for you to try out earlier or some other one?

    Have you opened the 9292 Zip file I uploaded for you on my last post? If not why not ? It is proper nc code with the .mmg extension you want.

    So, you are saying that when you try to Post ie generate code all you get is an error page from Fusion, no code is shown?

    Can`t tell anything from your screen shot, it is way too small to read.

    Lets be logical about this, does the 9292 code I sent you on my last post actually load and run in your machine ??

    If yes then it is possible that you have something in your Machine Configuration in Fusion that is not set correctly.

    Try the code and let us know if it works or not, that code was generated by the PP I uploaded for you earlier, I will attach it here again for you.

    Regards
    Rob

  14. #14
    Registered
    Join Date
    Jun 2008
    Posts
    1824

    Re: A working post processor from Fusion 360 to .mmg?

    Here is an image of the Posting Dialog where I have highlighted it showing that the extension is indeed .mmg

    Does it not show as this in your Fusion Posting Dialog ??

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •