Fusion 360 Lines Created Via API Are Not Limited To Sketch Plane

Cube on Sketch

Today’s performance tip helps avoid creating unnecessary planes and sketches when creating objects using the Fusion 360 API. First, some background: when sketching lines in Fusion 360 must be done in the context of a sketch object. This sketch object is in turn created to be aligned with a plane. It may be one of the default planes that intersect the origin (XZ plane, XY plane, or YZ plane) or a construction plane.

When sketching with the interactive UI, the user’s sketch entities are constrained to the plane of the sketch. For example, if a sketch was created on the XY plane, then all sketch entities would have a Z coordinate of zero. This makes sense to keep the data organized and easy to understand by the human looking at a 2D computer monitor.

When creating entities with the API, though, they are apparently not constrained. The first clue came from looking at the SketchLines.addByTwoPoints API – its two parameters are Point3D objects. A little experimentation confirmed the API would gladly accept 3D coordinates that lie outside the sketch plane. The example screenshot on this page is the result of drawing an one-centimeter cube on a sketch aligned to the XY plane. Only four of the eight corners (and four of the 12 edges) lie on the plane, but the API happily accepted all the information for a 3D cube.

This is very useful when creating geometries via code. Humans need to see points on a sketch stay in a plane for them to be workable on a 2D monitor screen, otherwise things get too confusing. But code doesn’t care about appearance on a screen. So go ahead – let code create complex 3D entities on a single sketch. Skipping the unnecessary planes and sketches will generate fewer API objects. Reducing object management overhead and allowing faster performance.

Accelerate Fusion 360 API Object Creation With DirectDesignType

64Cylinders

Exploring the capabilities of the Fusion 360 API will involve experiments creating objects via script. Since it’s all code, it’s easy to repeat a process many times, a natural allure of using scripts to automate repetitive tasks. The downside is that Fusion 360 (as of time of writing) has problems resulting in slow response.

The sample code below creates an array of small cylinders one at a time. (This is not the most efficient method to create an array of cylinders but merely an illustration of the problem.) The size of the array can be adjusted by changing the value of arraySize before running the script. For a 4×4 array, the results are almost instantaneous. On a modern Core i5, slowdowns can be observed in an 8×8 array. The first few cylinders are fast, but as additional cylinders appear, each new cylinder takes longer than the last.

Fusion 360 performs a lot of bookkeeping overhead to track these operations. While the majority are outside our control, we do have control over the most expensive overhead: the timeline. It is useful when we are working with hand-created designs, but unnecessary for script – if we want to change anything, we’d update the script and run it again. In the user interface, we can click on the gear in the lower right hand side and select “Do not capture Design History”. To do the same thing in script, we can set the type of the design object to DirectDesignType. (Uncomment line in sample code below.)

This mitigates but does not solve the problem. While it is now practical to generate far larger number of objects, there is still a noticeable slowdown as the object counts go up. According to this forum post, this issue has been logged as a defect for the development team. Perhaps a future release of Fusion 360 will create the last object as quickly as it created the first.

import adsk.core, adsk.fusion, adsk.cam, traceback

arraySize = 8 # Will extrude arraySize^2 objects

def run(context):
  ui = None
  try:
    app = adsk.core.Application.get()
    ui = app.userInterface

    app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)

    # adsk.fusion.Design.cast(app.activeProduct).designType = adsk.fusion.DesignTypes.DirectDesignType # Uncomment to turn off tracking timeline

    rootComp = adsk.fusion.Design.cast(app.activeProduct).rootComponent
    sketch = rootComp.sketches.add(rootComp.xYConstructionPlane)
    extrudeDistance = adsk.core.ValueInput.createByReal(1)

    rangeX = range(1-arraySize, arraySize, 2)
    rangeY = range(1-arraySize, arraySize, 2)

    for nowX in rangeX:
      for nowY in rangeY:
        sketch.sketchCurves.sketchCircles.addByCenterRadius(
          adsk.core.Point3D.create(nowX, nowY, 0), 0.5)

        rootComp.features.extrudeFeatures.addSimple(
          sketch.profiles[-1],
          extrudeDistance,
          adsk.fusion.FeatureOperations.NewBodyFeatureOperation)

        adsk.doEvents()

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

This code is also available on Github.

Fusion 360 Script Engine Uses Python Version 3

One of the differences between Python 2 and 3 was changing print from a statement to a function. This means a Python beginner like myself immediately runs into the breaking change trying to print “Hello World!” to the console. (print "Hello World!" versus print("Hello World!")) It sets the tone pretty clearly up front: when working with Python, developers need to know which version they’re writing for.

Which is why I was very puzzled when I searched for this information in the Autodesk documentation and came up empty-handed. The most obvious place in my mind would be the “Python Specific Issues” page of the user’s manual, but it wasn’t mentioned there. Searching various other combinations of terms – on and off Autodesk’s web site – failed to find a straightforward answer. Given the relatively young age of Fusion 360’s Python scripting support, I would expect them to use Python 3 but I wanted confirmation.

Well, if I can’t find it in documentation, there’s always looking at the code itself. And a tiny baby step beyond the simple boilerplate script generated by Fusion 360. It’s not quite printing “Hello World” but it’s almost that simple.

First I imported the Python sys module for querying system parameters.

import sys

Then I changed the boilerplate message box output string to include the version number.

ui.messageBox("We're running on Python " + str(sys.version_info.major), "Version detection")

Executing the script confirms the scripting engine is running Python 3.

F360Python3

Once the web search engines index this post, people who have this question in the future will know the answer just by reading the title of this post on the search results. They won’t even need to click on the link to read this page.

(This really simple bit of code is almost not worth committing to Github… but it’s a slow day so it was pushed up to be publicly available.)

Fusion 360 Scripting: Learning Resources Overview

fusion-360-logo31I don’t know how much Autodesk expects their Fusion 360 users to write their own custom scripts, but Autodesk have certainly made enough information available free online for anybody to give it a try. Broadly, they are divided into three categories:

  1. Why“: the Fusion 360 API User’s Manual describes the overall concepts of how the API is designed and laid out. It is written to be the starting point before the programmer dives into actual code.
  2. What“: the Fusion 360 API Reference Manual documents the specific nuts and bolts of how a script communicates with Fusion 360. This is where developers go to find the small but important details necessary to write good Fusion 360 code.
  3. How“: Autodesk provides sample code so we can see some already-written scripts and get a feel of how they work. Some people may prefer to start with the code before (or possibly ‘instead of’) going to the concepts described in the user’s manual. But every learner will need to cross-reference the sample code against the reference manual to understand everything a sample does.

I appreciated the foundation laid out by the user’s manual. It left me feeling confident that I could march into the scripts and be properly oriented to understand what I’m seeing and how to find answers when I need them. Whether this confidence is misplaced or not is too early to tell at the moment.

One thing that I found interesting: Autodesk provides sample code of different styles across multiple venues. There’s a fairly large set of samples alongside the manuals on Autodesk’s own help website, but there is in addition a Github account “AutodeskFusion360” where script code is published. Some are samples, some are hackathon projects, and some are scripts that they’re released to solve some problems that customers have raised in the forums.

Together they cover a pretty wide spectrum of code to learn from, from simplified educational code snippets to complete scripts intended to run on user workstations.

Building with Acrylic: Thickness Variation

Thickness failIn the previous post, the laser cutter kerf was successfully compensated, admittedly in a way that left plenty of room for improvement in the future. This post will look at a different challenge of building with acrylic: variation in thickness of acrylic sheets. So far experience showed different sheets of “6 mm” acrylic can actually be anywhere from 5.31 mm to 6.03 mm.

Since most laser-cut acrylic projects are 2D in nature, any variation in acrylic sheet thickness usually goes completely unnoticed. But when building 3D structures out of multiple interlocking pieces, the thickness dimension has a significant impact.

Fortunately for us, while thickness can vary across different sheets, the thickness is relatively consistent within a single sheet. There may be some variation from one corner of a 4′ x 8′ sheet of acrylic to another, but once cut into smaller pieces that can fit in a laser cutter, the thickness can be reasonably treated as constant.

This allows us to treat thickness as a parameter in a Fusion 360 CAD file. Any slots cut for acrylic pieces will need to reference the parameter. So that when it comes time to generate the cutting profile, the thickness parameter can be updated with the thickness of the actual sheet of acrylic, and Fusion 360 will automatically recompute all the slot widths to match.

Which brings us to the attached picture illustrating human error: the assembly on the left is built up to the proper dimensions. In contrast the assembly on the right was too thin. I made the mistake of measuring on one sheet and cutting on a different sheet that turned out to be 0.29 mm thinner. 0.29 mm is a small difference, but when the assembly is built by stacking seven pieces together, it results in a significant dimensional error of over 2 mm.

Building With Acrylic: Kerf Compensation

After learning my 3D printer’s inability to hold dimensional tolerance, I went back to practicing building with acrylic. Laser cutter kerf may be annoying but it is at least consistent. Now that I know my choice is between a consistent kerf or an inconsistent extrusion width, I choose to deal with consistency.

A bit of Google confirms laser cutter kerf compensation is a fairly common problem people have sought to deal with. What’s less common are actual practicable solutions for designing 3D structures intended to be built up from laser-cut pieces of acrylic. While 2D work on a laser cutter is common, construction for 3D structures appears to be less so.

A laser cutter workflow usually ends in a series of vector graphics commands. Common formats are DXF, DWG, SVG, and PDF. All are good for describing lines, but they only describe where to cut. They don’t contain information on which side of the line is the desired output. So while it is possible for an automated script to offset all lines, it doesn’t know which direction is “inside” vs “outside” in order to perform the proper offset for kerf compensation calculation.

The CAD software (Fusion 360) knows this information, so I thought it’s an obvious place for such mechanism to exist. Google knew of people who have devised some very clever workarounds to make it happen, but not an actual feature in the CAD software itself. Before I started using other people’s workarounds, I thought I’d try to do it manually first, adding to the kerf amount to the dimensions of individual components to CAD.

The result was very encouraging, the laser cut pieces came out at the desired dimensions and pieces fit together with their edges well aligned. This validated my manual process but added mystery. What I did was tedious for a human, simple for a computer, but for some reason the software doesn’t do it. Perhaps I will find out why as I continue learning about laser-cut acrylic construction.

Successful kerf