Can Fusion 360 do this?

srijal97
Explorer

Can Fusion 360 do this?

srijal97
Explorer
Explorer

Hello!

 

I am working on a version of the Dtto Modular Robot, and I have the assembly parts created in Fusion 360 (which I just started learning) as well as actual modules. Now my project requires me to create various maneuvers with the modules which are basically to set the hinge servos at specific angles step by step to create motion or a particular shape.

 

Doing this requires visualization of all the servos and manually type in the code for the angles required which becomes confusing when multiple servos move at the same time so I thought about some GUI or interface which could allow me to just move the modules on a computer screen and the servos' angles should automatically generate from that. I looked around and found out that the Fusion 360 API allows you to create and change joint properties using python scripts and was wondering if there was some way to move the robot modules in Fusion 360 using a mouse on the main GUI and getting the joint positions in a script as variables with the press of some key or in real-time probably? 

 

If this is done, I can connect with the robot serially using Bluetooth and directly send commands for it to move using Python. Does this seem like a job to be done on Fusion 360? If yes, it would be great if you could guide me what exactly I am looking for in the scripts. If not, any suggestions for other software/ideas are welcome. 

 

Thank you for your time,

- Srijal

0 Likes
Reply
Accepted solutions (1)
1,427 Views
7 Replies
Replies (7)

ekinsb
Alumni
Alumni

The API doesn't currently support any events to notify you when the model has changed in some way so I believe the best you can do will be to manually move and reposition the model and then run your script that queries the joints and gets their current position, which you can then use to manipulate the robot.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
1 Like

dinocoglitore
Advocate
Advocate

Hi srijal97, can you see if this is what are you looking for ?

https://gallery.autodesk.com/fusion360/projects/robot-arm---rv-m1---mitsubishi

 

Dino

1 Like

srijal97
Explorer
Explorer

Oh yes, that's what I need...varying those sliders will change the model angle and the same could be taken and sent to the actual bot. Could you give me a basic idea of how this is made?

0 Likes

dinocoglitore
Advocate
Advocate
Accepted solution

Hi srijal97 , This is the code I used to manage the joints of my model.

You have to adapt it to your needs.

 

Please if it is useful for you and if you think to use it, mention me in your code.

Many thanks

Dino

 

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

# Global list to keep all event handlers in scope.
# This is only needed with Python.
handlers = []
commandId = 'CommandInputTest'
xTarget = None
yTarget = None
zTarget = None
xOrigin = None
yOrigin = None
zOrigin = None
xRelPos = None 
yRelPos = None
zRelPos = None
occOrigin  = None
occTarget = None
ui = None

degree = None

def relativemeasure():
    global occOrigin
    global occTarget
    global xOrigin
    global yOrigin
    global zOrigin
    global xTarget
    global yTarget
    global zTarget
    global xRelPos
    global yRelPos
    global zRelPos
    
    try:
        app = adsk.core.Application.get()
        # Examine the current document
        ui = app.userInterface    
        design = adsk.fusion.Design.cast(app.activeProduct)
        
        # Get the root component of the active design.
        rootComp = design.rootComponent
        occurrences = rootComp.occurrences
 
        countOccurrences = occurrences.count
       
        for i in range(0, countOccurrences):        
            if occurrences.item(i).name == 'Target:1':
                found=i
                break
                
        occTarget = rootComp.allOccurrences.item(found)
        # trova le ccordinate dell'origine del componente Target tramite l'item
        trans = occTarget.transform
        xTarget = trans.translation.x
        yTarget = trans.translation.y
        zTarget = trans.translation.z

        
        for i in range(0, countOccurrences):        
            if occurrences.item(i).name == 'Origin:1':
                found=i
                break
                
        occOrigin = rootComp.allOccurrences.item(found)
        # trova le ccordinate dell'origine del componente Origin tramite l'item
        trans = occOrigin.transform
        xOrigin = trans.translation.x
        yOrigin = trans.translation.y
        zOrigin = trans.translation.z
        
        # calcola la posizione relativa di Target rispetto ad Origin        
        xRelPos = xTarget-xOrigin
        yRelPos = yTarget-yOrigin
        zRelPos = zTarget-zOrigin

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


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

        # Get the CommandDefinitions collection.
        cmdDefs = ui.commandDefinitions
        
        # Create a button command definition.
        buttonSample = cmdDefs.addButtonDefinition('SliderJoint', 
                                                   'Drive joints with sliders', 
                                                   'Drive Joints with sliders',
                                                   './Resources/SliderJoint')
        
        # Connect to the command created event.
        sampleCommandCreated = SampleCommandCreatedEventHandler()
        buttonSample.commandCreated.add(sampleCommandCreated)
        handlers.append(sampleCommandCreated)
        
        # Get the ADD-INS panel in the model workspace. 
        addInsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel')
        
        # Add the button to the bottom of the panel.
        buttonControl = addInsPanel.controls.addCommand(buttonSample)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


# Event handler for the commandCreated event.
class SampleCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):

        global degree
        global degree1
        global degree2
        global degree3
        global degree4
        global commandId
        global inputs        
        
        eventArgs = adsk.core.CommandCreatedEventArgs.cast(args)
        cmd = eventArgs.command

        
        # Get the CommandInputs collection to create new command inputs.            
        inputs = cmd.commandInputs

        # relativemeasure()
        
        # Create readonly textbox input
        title='Slider Joint'
        inputs.addTextBoxCommandInput(commandId + '_textBox', title ,'', 1, True)

        # Create Slider
        # app = adsk.core.Application.get()
        # des = adsk.fusion.Design.cast(app.activeProduct)
        
        # Create integer slider input with one slider
        degree = inputs.addIntegerSliderCommandInput(commandId + '_intSlider', 'Waist Slider', -150, 150);
        degree1 = inputs.addIntegerSliderCommandInput(commandId + '_intSlider1', 'Shoulder Slider', -90, 30);
        degree2 = inputs.addIntegerSliderCommandInput(commandId + '_intSlider2', 'Elbow Slider', -100, 110);
        degree3 = inputs.addIntegerSliderCommandInput(commandId + '_intSlider3', 'Wrist Pitch Slider', -90, 90);
        degree4 = inputs.addIntegerSliderCommandInput(commandId + '_intSlider4', 'Wrist Roll Slider', -179, 179);
       
        # Connect to the execute event.
        onExecute = SampleCommandExecuteHandler()
        cmd.execute.add(onExecute)
        handlers.append(onExecute)

        # cmd.isRepeatable = False
        onExecutePreview = SampleCommandExecuteHandler()
        cmd.executePreview.add(onExecutePreview)
        handlers.append(onExecutePreview)
 
# Event handler for the execute event.
class SampleCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):

        global degree
        global degree1
        global degree2
        global degree3
        global degree4
        global inputs
        
        eventArgs = adsk.core.CommandEventArgs.cast(args)
        # Get the values from the command inputs. 
        inputs = eventArgs.command.commandInputs

        # Code to react to the event.
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # ui.messageBox('In command execute event handler: degree= '+str(degree))
        
        root = app.activeProduct.rootComponent



        degree = inputs.itemById(commandId+'_intSlider').valueOne        
        degree1 = inputs.itemById(commandId+'_intSlider1').valueOne        
        degree2 = inputs.itemById(commandId+'_intSlider2').valueOne        
        degree3 = inputs.itemById(commandId+'_intSlider3').valueOne        
        degree4 = inputs.itemById(commandId+'_intSlider4').valueOne        

        

        joint = root.joints[0]  
        revoluteMotion = adsk.fusion.RevoluteJointMotion.cast(joint.jointMotion)
        revoluteMotion.rotationValue = 3.1415926 * 2 * degree / 360

        joint1 = root.joints[1]  
        revoluteMotion = adsk.fusion.RevoluteJointMotion.cast(joint1.jointMotion)
        revoluteMotion.rotationValue = 3.1415926 * 2 * degree1 / 360

        joint2 = root.joints[2]  
        revoluteMotion = adsk.fusion.RevoluteJointMotion.cast(joint2.jointMotion)
        revoluteMotion.rotationValue = 3.1415926 * 2 * degree2 / 360

        joint3 = root.joints[3]  
        revoluteMotion = adsk.fusion.RevoluteJointMotion.cast(joint3.jointMotion)
        revoluteMotion.rotationValue = 3.1415926 * 2 * degree3 / 360

        joint4 = root.joints[4]  
        revoluteMotion = adsk.fusion.RevoluteJointMotion.cast(joint4.jointMotion)
        revoluteMotion.rotationValue = 3.1415926 * 2 * degree4 / 360

def stop(context):
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        # Clean up the UI.
        cmdDef = ui.commandDefinitions.itemById('SliderJoint')
        if cmdDef:
            cmdDef.deleteMe()
            
        addinsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel')
        cntrl = addinsPanel.controls.itemById('SliderJoint')
        if cntrl:
            cntrl.deleteMe()
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))	
1 Like

srijal97
Explorer
Explorer

Thank you so much! 

 

This is all very new to me and it'll take some time to understand all the details, but your code would definitely help. My project is open-source, and I'll make sure to mention you and your model in the code as well as the documentation I'm making.

 

Thanks again,

- Srijal

0 Likes

dinocoglitore
Advocate
Advocate

You’re welcome.

I hope it will help you.

I wrote this code at the beginning of my experience with Fusion Api, almost one year ago.

Maybe you’ll find some mistakes or bugs.

If there is something that you don’t understand in my code let me know it, I will try to remember how I wrote it.

Dino

 

0 Likes

srijal97
Explorer
Explorer

Okay sure, I'll check it in detail in a few days.

 

Thanks,

- Srijal

0 Likes