Can the Fusion API call center of mass information?

Can the Fusion API call center of mass information?

MichaelAubry
Autodesk Autodesk
5,009 Views
14 Replies
Message 1 of 15

Can the Fusion API call center of mass information?

MichaelAubry
Autodesk
Autodesk

Hi Everyone,

 

Can we pull center of mass info in the api? I’d like to make a script to place a point based on the center of mass values. This will be super useful for anyone who needs to balance designs.

 

Thanks!

Mike

 

Center of Mass.jpg

Michael Aubry
Autodesk Fusion 360 Evangelist
0 Likes
Accepted solutions (2)
5,010 Views
14 Replies
Replies (14)
Message 2 of 15

liujac
Alumni
Alumni

Hi Mike,

 

Yes, we do support these properties on PyhsicalProperties object. There is a sample about this. 

http://fusion360.autodesk.com/learning/learning.html?guid=GUID-534772A3-99BE-487F-A01E-20B5420CC93F

 

Thank,

Jack

0 Likes
Message 3 of 15

MichaelAubry
Autodesk
Autodesk

Thanks Jack!

 

I think I'm super close.  I can't figure out how to get the center of mass to input to construction points. I assume the center of mass I'm retrieving is a point. Is this correct? Any ideas about what I'm doing wrong? Thank you,

 

#Author-MAubry
#Description-Creates a point for the center of mass of a component

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

#Mike Aubry
#This script gets the center of mass for a top level component
# and shows where it is by making a static, non-updating construction point

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

# Get all components in the active design.
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
title = 'Create Center of Mass Point'


if not design:
ui.messageBox('No active Fusion design', title)
return

# Get the root component of the active design
rootComp = design.rootComponent

# Get physical properties from component (high accuracy)
physicalProperties = rootComp.getPhysicalProperties(adsk.fusion.CalculationAccuracy.HighCalculationAccuracy);

# Get center of mass from physical properties
cog = physicalProperties.centerOfMass

# Get construction points
constructionPoints = rootComp.constructionPoints

# Create construction point input
pointInput = constructionPoints.createInput()

# Create construction point by point
pointInput.setByPoint(cog)
constructionPoints.add(pointInput)

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

 

Michael Aubry
Autodesk Fusion 360 Evangelist
0 Likes
Message 4 of 15

sebmorales
Contributor
Contributor

I don't understand why it is not working. I as well have been following the example but can't get it to work. I think it has to do with the difference between a 3Dpoint (the cog in this case) and a point object. 

 

Anyway, I changed a couple of things and now the script will take you 80% there. You will need to manually click on the construction menu and select "point through three planes"

 

 

import adsk.core, adsk.fusion, adsk.cam, traceback
app = adsk.core.Application.get()
if app:
    ui = app.userInterface

def run(context):
	try:
		activeDoc = adsk.core.Application.get().activeDocument
		design = activeDoc.design
		rootComp = design.rootComponent

		physicalProperties = rootComp.getPhysicalProperties(adsk.fusion.CalculationAccuracy.HighCalculationAccuracy)
		cog = physicalProperties.centerOfMass

		planes=rootComp.constructionPlanes
		planeX=planes.createInput()
		planeX.setByOffset(rootComp.xYConstructionPlane,adsk.core.ValueInput.createByReal(cog.z))
		planeY=planes.createInput()
		planeY.setByOffset(rootComp.xZConstructionPlane,adsk.core.ValueInput.createByReal(cog.y))
		planeZ=planes.createInput()
		planeZ.setByOffset(rootComp.yZConstructionPlane,adsk.core.ValueInput.createByReal(cog.x))
		planes.add(planeX)
		planes.add(planeY)
		planes.add(planeZ)


		# Get construction points
		constructionPoints = rootComp.constructionPoints
		pointInput = constructionPoints.createInput()
		pointInput.setByThreePlanes(planeX,planeY,planeZ)
		constructionPoints.add(pointInput)

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

COG.png

Message 5 of 15

ekinsb
Alumni
Alumni
Accepted solution

As Sebastian's code is pointing out, Fusion doesn't support creating a construction point at any location in space.  Construction points are always associated to other geometry.  The exception to this is when you're not capturing design history or when your working in a base feature.  The code below creates a point at the center of gravity and uses a base feature to be able to position it at any location.  I wanted to have the program create the point the first time you run it and them reposition it to the current COG each time you run it after that but I ran into a bug when I try to reposition it.  I've logged it so we should have it fixed soon.  I worked around it for now by deleting the existing point and re-creating it each time.  The downside to this is if you build anything in relation to that point the relationship will be broken.  Here's the code I ended up with.  It has the workaround of deleting the point which results in the section of code that's currently crashing to never be called.  Once the fix is made the delete code can be removed and then it should work as expected.

 

#Author-
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback
app = adsk.core.Application.get()
if app:
    ui = app.userInterface

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        
        # Get all components in the active design.
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        title = 'Create Center of Mass Point'
        
        
        if not design:
            ui.messageBox('No active Fusion design', title)
            return
        
        # Get the root component of the active design
        rootComp = design.rootComponent
        
        # Get physical properties from component (high accuracy)
        physicalProperties = rootComp.getPhysicalProperties(adsk.fusion.CalculationAccuracy.HighCalculationAccuracy)
        
        # Get center of mass from physical properties
        cog = physicalProperties.centerOfMass
        
        # Check to see if a base feature named "Center of Gravities" exists.
        baseFeature = rootComp.features.itemByName('Center of Gravities')
        if not baseFeature:
            # Create a new base feature.
            baseFeature = rootComp.features.baseFeatures.add()
            baseFeature.name = 'Center of Gravities'

            # Begin editing the base feature.
            baseFeature.startEdit()                
            
            # Create a construction point at the COG position.
            constructionPoints = rootComp.constructionPoints
            pointInput = constructionPoints.createInput()
            pointInput.setByPoint(cog)
            pointInput.targetBaseOrFormFeature = baseFeature
            constPoint = constructionPoints.add(pointInput)
            constPoint.name = 'Center of Gravity'
            
            # End the base feature edit.
            baseFeature.finishEdit()
        else:
            # Check that the "Center of Gravity construction point exists.
            cogPoint = rootComp.constructionPoints.itemByName('Center of Gravity')
            
            # Because of a problem with updating an existing point, this current deletes
            # the existing point so the code in the "else" is never executed.
            if cogPoint:
                cogPoint.deleteMe()
                cogPoint = None
            
            if not cogPoint:
                # Create the construction point.
                # Begin editing the base feature.
                baseFeature.startEdit()                
                
                # Create a construction point at the COG position.
                constructionPoints = rootComp.constructionPoints
                pointInput = constructionPoints.createInput()
                pointInput.setByPoint(cog)
                pointInput.targetBaseOrFormFeature = baseFeature
                constPoint = constructionPoints.add(pointInput)
                constPoint.name = 'Center of Gravity'
                
                # End the base feature edit.
                baseFeature.finishEdit()
            else:
                # Edit the existing construction point.
                pointDef = adsk.fusion.ConstructionPointPointDefinition.cast(cogPoint.definition)
                baseFeature.startEdit()                
                pointDef.pointEntity = cog
                baseFeature.finishEdit()
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Here's an updated version of what Sebastian wrote that creates the three construction planes to position the point.  If the point already exists, it edits the parameter values controlling the planes to reposition the point.

 

def run(context):
    try:
        app = adsk.core.Application.get()
        design = adsk.fusion.Design.cast(app.activeProduct)
        rootComp = design.rootComponent

        physicalProperties = rootComp.getPhysicalProperties(adsk.fusion.CalculationAccuracy.HighCalculationAccuracy)
        cog = physicalProperties.centerOfMass

        planes=rootComp.constructionPlanes
        constPlane = planes.itemByName('Root COG X')
        if not constPlane:
            planeXInput = planes.createInput()
            planeXInput.setByOffset(rootComp.yZConstructionPlane, adsk.core.ValueInput.createByReal(cog.x))
            planeYInput = planes.createInput()
            planeYInput.setByOffset(rootComp.xZConstructionPlane, adsk.core.ValueInput.createByReal(cog.y))
            planeZInput = planes.createInput()
            planeZInput.setByOffset(rootComp.xYConstructionPlane, adsk.core.ValueInput.createByReal(cog.z))
            planeX = constPlane = planes.add(planeXInput)
            constPlane.name = 'Root COG X'
            constPlane.isVisible = False
            planeY = constPlane = planes.add(planeYInput)
            constPlane.name = 'Root COG Y'
            constPlane.isVisible = False
            planeZ = constPlane = planes.add(planeZInput)
            constPlane.name = 'Root COG Z'
            constPlane.isVisible = False

            # Get construction points
            constructionPoints = rootComp.constructionPoints
            pointInput = constructionPoints.createInput()
            pointInput.setByThreePlanes(planeX,planeY,planeZ)
            constPoint = constructionPoints.add(pointInput)
            constPoint.name = 'Center of Gravity'
        else:
            # Update the existing parameters.
            cogConstPoint = rootComp.constructionPoints.itemByName('Center of Gravity')
            pointDef = adsk.fusion.ConstructionPointThreePlanesDefinition.cast(cogConstPoint.definition)
            planeX = pointDef.planeOne
            planeY = pointDef.planeTwo
            planeZ = pointDef.planeThree
            
            planeDef = adsk.fusion.ConstructionPlaneOffsetDefinition.cast(planeX.definition)
            planeDef.offset.value = cog.x

            planeDef = adsk.fusion.ConstructionPlaneOffsetDefinition.cast(planeY.definition)
            planeDef.offset.value = cog.y

            planeDef = adsk.fusion.ConstructionPlaneOffsetDefinition.cast(planeZ.definition)
            planeDef.offset.value = cog.z
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 6 of 15

MichaelAubry
Autodesk
Autodesk

This is so awesome! It works!

96wRMGZ - Imgur.gif

 

Sebastian and Brian, thanks so much for your help. This is so useful for anyone who needs to do balancing applications. 

 

Brian - I'm able to update the point by just rerunning the script.  Delete / recreate doesn't appear to be necessary (at least in the cases I've been trying). 

 

Very Best,

Mike

Michael Aubry
Autodesk Fusion 360 Evangelist
0 Likes
Message 7 of 15

ekinsb
Alumni
Alumni

The program is automatically deleting and re-creating so there's nothing you need to do.  It just has the bad side effect that if you associated something with the point, it will go sick because the point it's dependent on got deleted.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 8 of 15

sebmorales
Contributor
Contributor

Wow that looks beautiful! Did you cast it? 

0 Likes
Message 9 of 15

ekinsb
Alumni
Alumni
I'm not sure what you mean by "Did you cast it?".

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 10 of 15

sebmorales
Contributor
Contributor

Ohh, the comment was for MichaelAubry regarding the bird. I was asking about the fabrication method.  

 

0 Likes
Message 11 of 15

roambotics_scott
Advisor
Advisor

Incidentally  - in addition to just the center of mass point, every body / component should just automatically have a «Moments of Inertia» (or similar) group that includes (1) the center of mass as an origin point, (2) any non-degenerate moments of inertia as direction vectors, and a plane when two of the moments of inertia are degenerate (because then any linear combination of those is also an eigenvector so the choice of a particular pair isn't unique)

 

It should look something like this when turned on:

 

Capture d’écran 2016-08-13 à 09.43.42.png

 

where the center of mass is a point, the non-degenerate moment(s) are vector direction(s) like parts of an «origin» basis, and the degenerate vectors are a plane (the representation should be translated to center it at the center of mass.

 

All of those should be usable for defining geometry and relationships (like construction points, axes, and planes).

Just to extend the example of a top, this would be useful because it'd tell you not only where to put the center of rotation, but how to orient it, and how to properly balance it to avoid (or alternately induce) precession / nutation / wobbling / drift.

In an ideal top, the center of rotation would be at the center of mass with the axis of rotation aligned to a large, non-degenerate (unique) moment of inertia, and two smaller / degenerate moments of inertia would be in the plane of rotation

Message 12 of 15

roambotics_scott
Advisor
Advisor
This sort of pathology is why I strongly favour a dependency graph representation to the «timeline» representation.

It wouldn't be quite as compact*, but it'd be even more intuitive once people get it, it'd show the actual relationships in the design / not just the order someone happened to build it, it'd make it possible to easily visualize the entire dependency structure within a design**, and it'd make it clear what the consequences of changing something are.

* though you could have a «flatten/expand» toggle to switch between the two

** a long timeline is just a huge line extending far to the left/right of the screen for any non-trivial design. A dependency graph for the same design could fit within a single screen and make good use of the 2D space of the screen
Message 13 of 15

smallfavor
Collaborator
Collaborator

I would really like to find the 'tipping point' of some objects to determine the best angle for stacking them.  If I copy and paste the code listed into a python script, where should that be stored on the hard drive?  Am I correct in my thinking on the copy and paste method?

 

Thanks

 

James

 

Message 14 of 15

smallfavor
Collaborator
Collaborator
Accepted solution

Sorry Mike,  I just found the option in the inspect menu -  never mind Smiley Happy

0 Likes
Message 15 of 15

roambotics_scott
Advisor
Advisor

It'd be incredibly awesome (and relatively easy) to add in axes for non-degenerate moments of inertia and a plane when there are two degenerate axes

0 Likes