Assining points to CAM drilling operation through sketch

Assining points to CAM drilling operation through sketch

diana.petrova
Enthusiast Enthusiast
2,712 Views
23 Replies
Message 1 of 24

Assining points to CAM drilling operation through sketch

diana.petrova
Enthusiast
Enthusiast

Hello, Fusion Community!

 

So, I'm CAM engineer and have little practical experience with programming. I'm trying to automate one of the CAM operations our team is doing very often. So basicaly there is a sketch with circles (as in picture), the holes have to be drilled in the centre points of those circles. Currently there is a template file for the operations (Spot drilling->Drilling D1->Drilling D2), but all the points must be sellected manually, which is troublesome when there are over 100 point.

dianapetrova_0-1653840489933.png

Currently, with script I'm able to import operations from template to the active setup and add points from sketch to lists, but I'm struggling to assign the list of points to this parameter selected in blue and also I'm not sure if I'm accessing it correctly, as in code section below.

dianapetrova_2-1653841059847.png

 

for op in operat:
                oppoints = op.parameters.itemByName("holePoints")
                ui.messageBox(str(oppoints.isEditable))

 

 

Where 'operat' is an "Operation object". However, it shows that  this parameter is not editable.

 

Does it mean tha this parameter is not allowed to be edited from script and what I want to do is imposible to achieve? Or there is some logic problem?

 

P.S. I'll add the full code in comment

 

 

0 Likes
Accepted solutions (1)
2,713 Views
23 Replies
Replies (23)
Message 2 of 24

diana.petrova
Enthusiast
Enthusiast
from xml.dom.minidom import Document
from xml.etree.ElementTree import ProcessingInstruction
import adsk.core, adsk.fusion, adsk.cam, traceback,os

def isclose(a,b, diff)
    return abs(a-b) <= diff

def run(context)
    ui = None
    try:
        app = adsk.core.Application.get()
        doc = app.activeDocument
        ui  = app.userInterface
 
#Beginning of template input section        
        products = doc.products
        cam = adsk.cam.CAM.cast(products.itemByProductType("CAMProductType"))
        if app.activeProduct.productType == "CAMProductType":
            ui.messageBox("Recommend to select EMPTY setup to create operations.")
            #ui.messageBox("We are in CAM application.")
            setups = cam.setups
            #ui.messageBox(str(setups.count))
            for set in cam.setups:
                if set.isActive:
                    asetup=set
                    #ui.messageBox("Active setup detected " + asetup.name)
            inpt = ui.inputBox("Input machine name: (TM or VF) ","Template selection","TM")
            #ui.messageBox(str(inpt[1]))
           
            if inpt[0] == "TM" or inpt[0] == "tm":
              templateFilename = "C:\\Users\\diana\\AppData\\Roaming\\Autodesk\\CAM360\\templates\\Toorik.f3dhsm-template"
              #ui.messageBox("TM-2P selected")
            elif inpt[0] == "VF" or inpt[0] == "vf":
              templateFilename = "C:\\Users\\diana\\AppData\\Roaming\\Autodesk\\CAM360\\templates\\Toorik_Suur.f3dhsm-template"
              #ui.messageBox("VF5SS selected")
            else:
               ui.messageBox("Invalid user input")        
                   
            if not os.path.exists(templateFilename)
                ui.messageBox("The template '" + templateFilename + "' does not exist")
            else:
                #ui.messageBox("The template '" + templateFilename + "' exists")  
                asetup.createFromTemplate(templateFilename)
            operat = asetup.allOperations
#End of template input section
 
 


#Beginning of sketch selection section
            ui.messageBox("Now select a sketch")
            chooseSketch = ui.selectEntity("Select a sketch", "Sketches")
       
            if chooseSketch.isValid == True:
                sketch = chooseSketch.entity
                holes = sketch.sketchCurves.sketchCircles
                n = holes.count
                d8points = []
                d10points = []

                #for hole in holes:
                for i, hole in enumerate(holes)

                    if isclose(hole.radius, 0.5, 0.001)
                        d10points.append(hole.centerSketchPoint)
                        #ui.messageBox("Hole with diameter 10 " + str(i) + " added succsessfully")
                    elif isclose(hole.radius, 0.4, 0.001)
                        d8points.append(hole.centerSketchPoint)
                        #ui.messageBox("Hole with diameter 8 " + str(i) + " added succsessfully")
                    else:
                        ui.messageBox("Comparison fail")    

                    #ui.messageBox("Point " + str(i) + " added succsessfully")
                ui.messageBox("D10:  " + str(len(d10points)) + " D8: " + str(len(d8points)))        
               
                           
                #ui.messageBox("All good" )
               
            else:
                ui.messageBox("Point detection failed")
#End of sketch selection section
 

#Beginning of operation modification section
           
            for op in operat:
                oppoints = op.parameters.itemByName("holePoints")
                ui.messageBox(str(oppoints.isEditable))
               
            """
            for op in operat:
                if op.name == "Spot":
                    oppoints = op.parameters.itemByName ("holePoints")
                    ui.messageBox(str(oppoints.isValid)+" "+ str(oppoints.objectType)+ "" )
                    for p in d10points:
                        oppoints += p.
               
                for p in d10points:
                if op.name == "Spot":
                    ui.messageBox("Spot operation detected")
                    spoints =[]
                    spoints.append(d10points)
                    spoints.append(d8points)
                    ui.messageBox("There are "+ str(spoints.count)+ " points in operation" + op.name)
                   
                    operatpoints = spoints
                    ui.messageBox("There are "+ str(operatpoints.count)+ " points in operation" + op.name)
                   
               
                elif op.name == "D5.9":
                    ui.messageBox("D5.9 operation detected")
                    op.parameters.holePoints.append(d10points)
                elif op.name == "D8.02":
                    ui.messageBox("D8.02 operation detected")
                    op.parameters.holePoints.append(d8points)
                """    

        else:
                ui.messageBox("You need to be in CAM application!")

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes
Message 3 of 24

diana.petrova
Enthusiast
Enthusiast

Still want an answer  to my question...

0 Likes
Message 4 of 24

diana.petrova
Enthusiast
Enthusiast

Is there anyone who might at least give me an answer that what I'm doing is impossible or something?

0 Likes
Message 5 of 24

kandennti
Mentor
Mentor

Hi @diana.petrova .

 

I don't think the Fusion360 CAM API supports specifying shapes, etc.

In the case of PowerMill(Autodesk), most of the GUI operations can be reproduced using macros.

0 Likes
Message 6 of 24

diana.petrova
Enthusiast
Enthusiast

@kandennti 

Why though?

In my understanding, what I want to do should have similar logic as automated extrusion, only difference is that sketch geometry is inserted into CAM operation menu instead of extrusion menu. Why it is allowed for extrusion and not allowed for CAM operation?

0 Likes
Message 7 of 24

kandennti
Mentor
Mentor

@diana.petrova .

 

I don't know why, as I am just a user.

 

The only way to achieve what is not provided by the API is to use text commands.

 

1.png
To do this, the Operation needs to be selected, as shown in the image, but I have not been able to figure out how to even make it a selection.

0 Likes
Message 8 of 24

Jorge_Jaramillo
Collaborator
Collaborator
Accepted solution

Hi @diana.petrova ,

 

The CAD parameter to set the holes to be drilled is holeFaces (which you can set via the API) instead of holePoints.

 

These are the changes I made to your code to get it to work:

1. Select a body instead of a sketch:

ui.messageBox("Now select a body:")
# chooseSketch = ui.selectEntity("Select a sketch", "Sketches")
chooseBody: adsk.fusion.BRepBody = ui.selectEntity("Select a sketch", "SolidBodies")

 

2. Look for cylindrical faces in the body, filter them by diameter value and create a collection of faces:

import math
DIAMETER = 0.8
#  ...
face: adsk.fusion.BRepFace
facesCol: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
if chooseBody.isValid:
    for face in chooseBody.entity.faces:
        app.log(f'face:  {face.area=} {face.geometry.surfaceType=}')
        if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
            # face is cylindrical
            diam = 0
            for edge in face.edges:
                # more than ONE edge is returned: internal and external
                # ==>> check that both have the same diameter
                # if their diamenters are different from each other, it is a CONE, not a cyclinder
                if edge.geometry.curveType == adsk.core.Curve3DTypes.Circle3DCurveType:
                    diam = edge.length / math.pi
                app.log(f'  edge: {edge.geometry.curveType=} {edge.length=} {diam=}')
            if abs(diam - DIAMETER) < 0.001:
                # select cylindrical faces which diameter is equal to DIAMETER +/- 0.001
                facesCol.add(face)
else:
    ui.messageBox('Not body selected')
# if chooseSketch.isValid == True:
#     sketch = chooseSketch.entity
#     holes = sketch.sketchCurves.sketchCircles
#  ...

Change DIAMETER value to set what you want to select; or create a second collection as you did in you code

 

3. Finally assign faces collection to holeFaces paremeter and generate tools paths:

for op in operat:
    holeFaces = op.parameters.itemByName("holeFaces")
    val: adsk.cam.CadObjectParameterValue
    val = holeFaces.value
    val._set_value(facesCol)
cam.generateAllToolpaths(True)

 

Another option could be to select just 1 cylindrical face as I did before, and set selectSameDiameter parameter to TRUE, and let Fusion 360 select all holes of the same diameter as the one you provided.

 

It worked for me.  Here you have two examples with 10mm and 8mm diameter selection:

Captura de pantalla 2022-07-27 211206.png  Captura de pantalla 2022-07-27 211101.png

 

Hope this help you.  Let me know if it works for you.

 

Regards,

Jorge

Message 9 of 24

kandennti
Mentor
Mentor

@Jorge_Jaramillo .

 

I was surprised.
I did not know about "adsk.cam.CadObjectParameterValue."

0 Likes
Message 10 of 24

Jorge_Jaramillo
Collaborator
Collaborator

Hi @kandennti ,

 

I wonder why it is not included in the API specification.

 

Regards,

Jorge

0 Likes
Message 11 of 24

diana.petrova
Enthusiast
Enthusiast

@Jorge_Jaramillo

It took me a while to actually test this, but with your help it finally worked.

The last part was especially usefull, even though I don't underastand completely, why it should be done like this. And it worked perfectly with "holePoints" and reading points from sketch. So now I have the code which does exactly what I wanted.

Thanks a lot for your reply.

Message 12 of 24

diana.petrova
Enthusiast
Enthusiast

Hey.

With the today's update the script I was actively using so far broke.

Would appreciate if you could explain the meaning of the error and what should be looked into/corrected in the code. The script file is in attachment.

dianapetrova_0-1680672457091.png

 

0 Likes
Message 13 of 24

kandennti
Mentor
Mentor

Hi @diana.petrova .

 

I haven't tried it, so I could be wrong, but how about this?

・・・
            for op in operat:
                oppoints = op.parameters.itemByName("holePoints")
                if "Spot" in op.name:
                    oppoints.value.value = APoints
                    # val: adsk.cam.CadObjectParameterValue
                    # val = oppoints.value
                    # val._set_value(APoints)
                    op.isOptional=True
                    #cam.generateToolpath(True)                                       
                elif "D5.9" in op.name:
                    oppoints.value.value = d10points
                    # val: adsk.cam.CadObjectParameterValue
                    # val = oppoints.value
                    # val._set_value(d10points)    
                    
                elif "D8.02" in op.name:
                    oppoints.value.value = d8points
                    # val: adsk.cam.CadObjectParameterValue
                    # val = oppoints.value
                    # val._set_value(d8points)  
                    cam.generateAllToolpaths(True)
                else:
                    ui.messageBox("Unexpected operation found. Selected wrong setup?")     
                    break
・・・
0 Likes
Message 14 of 24

diana.petrova
Enthusiast
Enthusiast

Tried it and get pretty much the same error.

 

dianapetrova_0-1680677332590.png

 

Message 15 of 24

kandennti
Mentor
Mentor

@diana.petrova .

 

How about a list instead of an ObjectCollection for the hole location?

・・・
                # d8points: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
                # d10points: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
                # APoints: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
                d8points = []
                d10points = []
                APoints = []

                #for hole in holes:
                for i, hole in enumerate(holes):

                    if isclose(hole.radius, 0.5, 0.001):
                        APoints.append(hole.centerSketchPoint)
                        d10points.append(hole.centerSketchPoint)
                        # APoints.add(hole.centerSketchPoint)
                        # d10points.add(hole.centerSketchPoint)
                        #ui.messageBox("Hole with diameter 10 " + str(i) + " added succsessfully")
                    elif isclose(hole.radius, 0.4, 0.001):
                        APoints.append(hole.centerSketchPoint)
                        d8points.append(hole.centerSketchPoint) 
                        # APoints.add(hole.centerSketchPoint)
                        # d8points.add(hole.centerSketchPoint) 
                        #ui.messageBox("Hole with diameter 8 " + str(i) + " added succsessfully") 
                    else:
                        ui.messageBox("Diameter comparison failed")    
・・・
0 Likes
Message 16 of 24

echatzief
Advocate
Advocate

Hi @diana.petrova I think the problem is that you did not specify the "holeMode" of the operations. I took my shot, hence I'm attaching you the reproduced script. Let me know if that helps.

@kandennti  In the method "_set_value" of CadObjectParameterValue class, you can only assign an object collection, not an array or sth else.

Message 17 of 24

diana.petrova
Enthusiast
Enthusiast

@kandenntiI think that was my initial thought of how to inset points, before I learned about CadObjectParameterValue, and it didn't insert point to the operation at all.

 

@echatziefI use diameter ranges a lot usually, but as I described in the first post holes I want to use are always in a sketch and the only option to select them for drilling operation is to select them by center points.

What you suggested might be the reason, but still not working..

What do you think, is there a conflict in those two lines?

dianapetrova_0-1680680883769.png

This time error is different:

dianapetrova_1-1680681087922.png

 

 

 

0 Likes
Message 18 of 24

echatzief
Advocate
Advocate

I'm sorry, it is "selection-points" if you want to assign points to your operations, or "selection-faces" whether you want to assign bRep faces to your ops.

Let me know.

0 Likes
Message 19 of 24

diana.petrova
Enthusiast
Enthusiast

@echatziefI want to select points, but what is a correct way to do it after these lines:

dianapetrova_0-1680682981079.png

 

Or can you provide any link where I can read about "hole_mode" and maybe I'll find an answer there. So far I cannot find one.

 

0 Likes