Monday, February 24, 2014

Surface Rough and Surface Finish Toolpath Setup

This post documents the process of setting up a 3-axis surface roughing and surface finishing of sheet material using Mastercam.

Setting up the machine and stock, as well as backplotting and simulation, is exactly the same as is shown in the Mastercam Toolpath Setup post. This post will cover adding a surface roughing and surface finish toolpoaths.

Surface Roughing Toolpath

Surface roughing toolpaths typically use larger tools, multiple stepovers, and multiple step downs to quickly remove larger volumes of stock and leave an even amount of stock for finishing. The roughing toolpaths you choose for your part depend on the shape of the part, shape of the stock, and machining situation.
Check out the Mastercam help file for details on the various roughing strategies shown below. This post will use the Parallel toolpath.


You'll be asked to select the surfaces to cut to via the selection dialog:

  • Drive: The surfaces, solid faces, solid bodies, or CAD files that will be cut.
  • Check: The surfaces, solid faces, or solid bodies that you want the tool to avoid. 
  • Containment: A closed chain of curves that limit tool motion. 

 Click the arrow under Drive and choose the surfaces to cut. Once selected exit the dialog.

As with other toolpaths you need to choose a tool. For small MDF panel surfacing projects a good choice is a 1/2" downshear rougher.

Once selected change the tab over to the Surface parameters options.

Here you set the Retract and Feed Plane settings. Retract sets the height that the tool moves up to before the next tool pass. Select the check box to activate the retract plane, then click the button and select a point on the geometry or enter a value. This option is off by default. The retract height should be set above the feed plane. If you do not enter a Clearance height (clearance sets the height at which the tool moves to and from the part), the tool will move to the retract height between operations.

Next set the Stock to leave on drive surfaces. This will leave the extra amount that the finishing pass removes. Leaving 1/8" or 1/4" is fine for MDF. This lets the smoother finishing pass clean down to the actual drive surface height.

Next change the tab to set the Rough parallel parameters.

The Maximum stepover controls how far the tool moves over for each cut in XY, and the Maximum stepdown controls how much material is removed in Z for each cut. You can safely use 80% of your too width for the step over provided you are not stepping down to much in each pass. When surfacing MDF I like to step down no more than twice the tool width, and step over about 50% of the tool width on each pass.

Use the Plunge control parameters to control where the tool is allowed to make plunges. Use the buttons to set cut depths, control motion between adjacent surfaces, and motion on surface edges.

Change the Cutting method to Zigzag. Under Plunge control select the Allow multiple plunges along cut. This makes multiple entry moves along the part. This will significantly speed up the cutting time.

Check both the Allow negative Z motion along the surface and Allow positive Z motion along the surface. This will maximize the speed of the roughing as the tools we are using can cut while plunging and while retracting.

Surface Finishing Toolpath

Surface finishing toolpaths typically finish a part down to the drive geometry (or to the stock to leave amount if one is specified). These are usually using a small stepover and don't cut very deep. To surface a 3D form a typical stepover is 0.05". The typical amount of material being removed might be 0.25" or 0.125".

To add this toolpath right-click in the Toolpath group and choose a Surface Finish toolpath. In this example I'm using Parallel.

You'll be asked to select the Drive surfaces as in roughing.

Next you'll be asked to select a tool. For surfacing choose a ball end mill. Choose the largest tool that can still get everywhere into your parts form. Using a larger tool gives a shallower scallop making for a cleaner surface. In this example I'm using a 1/2" ball end mill.

Next move to the Surface parameters tab.

Here you set the Retract and Feed plane values as above. Make sure the Stock to leave on drive is set to 0.0 so it mills all the way to your surface.

Next move to the Finish parameters tab.

Finish parallel toolpaths cut the drive geometry using linear zigzag or one-way motion. In this example we'll set the Cutting method to Zigzag. 

The Maximum stepover controls how far the tool moves over for each cut in XY. Using a smaller value will result in a smoother surface but take more time. For a 1/2" ball bit I like a value of around 0.05" as the stepover. 

Simulation

Make sure to carefully simulate your roughing and finishing cuts. 
Control of Simulation is the same as was shown in the Mastercam Toolpath Setup post. 

3D Contour Toolpath (Waste Trim)

If you want the router to trim the waste from your panels you can use a 3D Contour toolpath to do so.
Note: Since the toolpath will need to cut entirely through the material, doing this will compromise your form for future vacuum forming of panels. Therefore, make sure you have an extra form for trimming, or have enough panels already cut!

Right-click in the toolpath list and choose Router toolpath > Contour from the menu.

The Chaining dialog will appear and you select the chain to cut. Careful setup in Rhino to create a single closed curve will make this setup process easier in Mastercam.

After you select the Chain the Contour toolpath dialog will appear. First select the tool. I'm using a 1/4" straight downshear.

Next go to the Linking Parameters branch. Set your Retract, Feed plane, and Top of stock values.

Next go to the Cut Parameters branch. Make sure the Contour type is set to 3D. You'll also need to set the Compensation direction to right or left. After you simulate you can easily tell if you need to switch the setting if it is cutting on the wrong side of the line.

You may also want to set a small Break Through amount using that branch. Here you can set a low value to cut through the material to make sure it is fully free from the waste.

You can then backplot or simulate to make sure the Contour is cutting as expected.





Sunday, February 16, 2014

Rhino 3dm File Load / Draw / Bake

As part of getting an interactive preview into the Super Matter Tools UI I've been developing some proof-of-concept code to read Rhino 3dm files, load the objects into memory (without creating Rhino geometry), and draw them using a fast "display conduit". Further, I've worked on posing those objects (transforming them), and then "baking" them into actual Rhino geometry so they can be used to render animations.

This is similar to how Grasshopper lets users preview geometry and manipulate it without creating Rhino objects. Then, when things are set, baking them.

Here are a few screen captures of the code running (the full source code is listed at the end of this post):

A Kuka KR100HAL90 robot mesh, drawn shaded using the display conduit. The bounding box for the objects is expanded by 5% and drawn as well. For an overview of the Display Conduit in Rhino see this post: Display Conduit Introduction for RhinoCommon.

 The material diffuse color is changed to green and drawn again:

 The robot is rotated 90 degrees in Z, material is changed, and drawn:

The mesh is "baked", converting them to Rhino objects: 

This allows for drawing using the nicer rendering modes available - in this case Artistic:


The full python test code:

import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
import System
import System.Drawing

def Main():
    # The 3dm file to open and read
    pathname = "C:\\KR100HAL90.3dm"
    # Open it and get the objects
    drawObjs = Load3DMFile(pathname)
 
    # Make the display conduit object for drawing
    dc = DisplayConduit(drawObjs)
 
    # Draw
    dc.xform = rs.XformIdentity()
    dc.Enabled = True
    rs.Redraw()
    rs.GetPoint("Click to continue...") # Wait...
 
    # Change the material color and draw again
    dc.material.Diffuse = System.Drawing.Color.Green
    rs.Redraw()
    rs.GetPoint("Click to rotate...") # Wait...
 
    # Rotate (and change color again)
    cplane = rs.ViewCPlane()
    dc.xform = rs.XformRotation2(90.0, cplane[3], cplane[0])
    dc.drawObjsBBox.Transform(dc.xform) # Update the bounding box to the rotated state
    dc.material.Diffuse = System.Drawing.Color.Yellow
    rs.Redraw()
    rs.GetPoint("Click to Bake Meshes...") # Wait
 
    # Convert the mesh to Rhino objects
    meshList = BakeMeshes(dc.drawObjs, dc.xform)
    if meshList:
        print "Meshes created: %d" % len(meshList)
    rs.Redraw()
 
    # Stop drawing
    dc.Enabled = False
    rs.Redraw()

# Read the 3dm file and return a list of the objects within it
def Load3DMFile(pathname):
    f3dm = Rhino.FileIO.File3dm.Read(pathname)
    if (f3dm):
        objs = f3dm.Objects
        return objs

# Convert the list of objects passed to Rhino geometry. Then transform
# them with the transformation matrix passed
def BakeMeshes(drawObjs, xform):
    meshList = []
    for item in drawObjs:
        if item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh:
            mesh = item.Geometry
            verts = mesh.Vertices
            faces = mesh.Faces
            rhinoMesh = scriptcontext.doc.Objects.AddMesh(mesh)
            meshList.append(rhinoMesh)
    if (meshList):
        rs.TransformObjects(meshList, xform)
    return meshList

# Display Conduit class to draw in the viewports
class DisplayConduit(Rhino.Display.DisplayConduit):
    def __init__(self, objs):
        # Store the objects we are to draw
        self.drawObjs = objs
        # Store the transformation to apply - initially none
        self.xform = Rhino.Geometry.Transform.Identity
     
        # Get the bounding box for all the objects passed
        self.drawObjsBBox = Rhino.Geometry.BoundingBox(Rhino.Geometry.Point3d(-1,-1,-1), Rhino.Geometry.Point3d(1,1,1))
        for item in self.drawObjs:
            bbox = item.Geometry.GetBoundingBox(False)
            if (bbox):
                self.drawObjsBBox.Union(bbox)
     
        # Expand the bbox by 5% of the diagonal length for use in zoom extents
        amount = self.drawObjsBBox.Diagonal.Length*0.05
        self.drawObjsBBox.Inflate(amount)
     
        # Init the material to draw with
        self.material = Rhino.Display.DisplayMaterial()
        self.material.Diffuse = System.Drawing.Color.OrangeRed # Kuka robot color!
        self.material.Shine = 0.8
 
    # Called to quickly return the bounding box for the scene including our objects
    def CalculateBoundingBox(self, calculateBoundingBoxEventArgs):
        calculateBoundingBoxEventArgs.IncludeBoundingBox(self.drawObjsBBox)
 
    # Called to quickly return the zoom extents bounding box including our objects
    def CalculateBoundingBoxZoomExtents(self, calculateBoundingBoxEventArgs):
        calculateBoundingBoxEventArgs.IncludeBoundingBox(self.drawObjsBBox)
 
    # Called to draw the objects to the viewport. This is done before any Rhino
    # objects which will be drawn over ours.
    def PreDrawObjects(self, drawEventArgs):
        drawEventArgs.Display.DrawBox(self.drawObjsBBox, System.Drawing.Color.White)
        drawEventArgs.Display.PushModelTransform(self.xform) # Apply the transform
        for item in self.drawObjs:
            if item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Curve:
                drawEventArgs.Display.DrawCurve(item.Geometry, System.Drawing.Color.Green)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Brep:
                drawEventArgs.Display.DrawBrepWires(item.Geometry, System.Drawing.Color.Red)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh:
                #drawEventArgs.Display.DrawMeshWires(item.Geometry, System.Drawing.Color.Blue)
                drawEventArgs.Display.DrawMeshShaded(item.Geometry, self.material)
            elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Point:
                drawEventArgs.Display.DrawPoint(item.Geometry.Location, System.Drawing.Color.White)
        drawEventArgs.Display.PopModelTransform() # Remove the transformation

# Run it...
if (__name__ == "__main__"):
    Main()

Sunday, February 2, 2014

CNC Corner Fix Utility

I created a Rhino Python script to quickly draw the geometry to allow the CNC router to clear out material in corners.

Download Here
(Note: This a Windows only plug-in. It will not work with Rhino for the Mac.)

To run the script load it into the Rhino Python editor. From Rhino type EditPythonScript. This launches the Python editor.

Choose the Open icon and load the CornerFix12.py script. Select Run Script from the fly-out menu shown.

The user interface is shown below.

Choose if you want to clean the corner material with a Router bit or a Drill bit. You can use a drill bit with a small diameter to make the least visible mark. Choose Router if you don't want to change tools and just cut the contour into the corner.

Choose the diameter of the bit you wish to use. Then set the Shift Cut %. For the least visible cut use the default of 99%. This will just barely cover the corner. If you change it to 0% the arc will be centered over the previous intersection point. Here are a few example of a router path to visualize the difference (the polylines intersect on the grid intersection points):

Click the Select Lines button. Select the two line segments leading into an inside corner. The arc will be drawn. Note: The program always draws to the inside corner - there is no reason to add arcs to outside corners because they can be cut without them. If you are using a drill bit a center point is drawn as well as the circle. Not trimming of the corner is done.

There is an extra 0.001" added to the width of the arc and lines drawn when routing. This allows CAM software toolpaths to enter the arc. Without this, particularly in Mastercam, the corner arc will be skipped.

Note you can fully operate Rhino as the script runs. This lets you explode, undo, join, whatever... as you fix up the corners. To quit the program just close the interface.

Important Safety Note

If you make the corner curve very small (as is shown above) you run the risk of burning the material. That's because the router bit is not moving much as it clears the corner material. This leaves the bit spinning in place (or almost so) and heats it way up. Therefore be careful when using the circle setting. It's better to drill the holes (for the smallest amount of material removed from the corner) or use a larger circle so the bit will continue to move as it clears out the corner. That is, use a diameter larger than the bit.

Here's an example of the burn that can occur - this is doing some pocketing (before the finish pass was cut):

In this case, there were so many corners cut this way, the bit go so hot that the spoil board beneath the material caught fire. That's never good.

Current Limitations:
  • The program works on degree 1 curves only (polylines). 
  • The polylines need to be open. So if you have a closed polyline explode it first, then use the tool. 
  • The polylines need to intersect at a point or cross over one anther. If they don't fillet them with a radius of 0 first. Then select the lines.