Tag Archives: cutsim

Threading and OpenGL, test 2

Here's a simple test program using LibQGLViewer (screen capture with xvidcap). The vertex array and the index array that OpenGL draws (using glDrawElements) are held in a GLData class which holds a mutex. The Viewer class locks the mutex while drawing, and the worker-thread locks the mutex while updating the data. Here the worker task re-positions the original vertex position, signals the Viewer to draw, and then sleeps for 40 ms. When we don't rotate or zoom with the mouse the frame-rate should thus be 25 Hz. Rotating or zooming causes more frequent re-draws and a higher frame-rate.

To gain any real benefit on a multi-core machine I think the worker thread needs to work on a 'dirty' copy of the data, and we only lock the mutex for a minimal time while swapping in the updated data for the real data. Anyone have any good example code for this? Both a case where the worker produces new data at a slow rate (slower than Viewer re-draws), and at a faster rate should be handled.

Here's an UML(ish) diagram drawn with dia:

Code.

Cutsim driven by g-code

Based on Mark Pictor's cam-occ work I've been able to use the emc2 g-code interpreter 'rs274' binary that gets built during an emc2-build. It reads g-code files and outputs 'canonical' motion commands (see e.g. "The NIST RS274/NGC Interpreter - Version 3"). I'm positioning the tool at densely sampled points along each move, and subtracting it from the stock (see Yau and Yau) . The stock model is a distance field stored in an adaptive octree (see Frisken and Frisken).

This is very experimental: There's one kind of stock and one kind of tool, namely spherical!, The stock and tool sizes and colors are hard-coded, There's only one thread which means the UI becomes unresponsive and greyed-out during about 57s of processing. It's slow, 57s for a fairly simple 20-line g-code file. We assume hard-coded paths for the 'rs274' binary and the emc2 tooltable-file.

Octree operations

I've looked at set-operations (union, difference, intersection) for octrees again. Previously I tried it with linear-octrees and visualization with python and VTK. Now I'm using a traditional pointer-based octree data-structure, and drawing with OpenGL VBOs. With the addition of a g-code interpreter, a user-interface, and an isosurface extraction algorithm (such as marching-cubes) this should converge towards a milling/turning/3d-printing cutting-simulation sometime soon...

References: Frisken2000 and Frisken2006.

Octree animation

Update: this figure shows the numbering of vertices(red), edges(green), and faces(blue). The arrows show the direction of the X-(red), Y-(green), and Z-axes(blue).


Here the sides of the cube are not generated with Marching-Cubes, they are just extracted directly from the octree. Nodes are subdivided whenever the signed distance-field of the cutter indicates that the surface is contained within the node, i.e. the distance-field evaluates to both positive and negative at the eight fourvertices of a node. This apparently leads to transient holes in the surface when the cutter is just about to enter a coarse node which hasn't been subdivided very far yet. It should be possible to adjust the subdivision criterion so that the octree 'anticipates' the cutter slightly and subdivides ahead of the actual cutter surface.

Cutsim progress

The speed of the new cutting-simulation code makes it possible to run it at a higher resolution than before. That makes the surfaces look smooth and nice. Alas, some problems still remain with holes in the fabric of reality mystically appearing and disappearing .

There is an edge-flipping paper by Kobbelt et al. from 2001 which improves the jagged/aliased look of sharp edges.

Update: Kobbelt provides a LGPLv2 licensed sample-implementation of the algorithm here: http://www-i8.informatik.rwth-aachen.de/index.php?id=17

OpenCAMLib machining simulation, v.2

This is my second attempt at a machining simulation where a moving milling tool cuts away voxels from the stock material. To save space an octree data structure is used to store the voxels, and to produce a nice looking surface you store the signed distance to the exact surface in each vertex of the octree. You then use marching-cubes to extract triangles for a distance=0 isosurface in order to draw the stock.

Unlike my first attempt, this works well enough to warrant further experiments (on the to-do list are: differently shaped tools, colouring triangles based on which tool cut the voxel, lathe operations, material removal-rate, etc.). It should be straightforward to hook this up to the EMC2 G-code interpreter so that any G-code, not just densely sampled CL-points from OCL, can be simulated. You could also flip the sign of all the numbers, and simulate an additive process, like 3D printing (reprap / makerbot).

This approach to machining simulation is described in a 2005 paper by Yau, Tsou, and Tong.

Octree with Marching Cubes

Update 3: this leads slowly towards a better and faster cutting simulation. Here's an example with Tux:

Update2: this looks slightly better now (a ball translated in a few steps towards the right). Image and c++ code by fellow OCLer Jiang from China.

Update: in a cutting simulation the stock is updated by removing voxels which fall inside the cutter. Here I'm trying it with a spherical shape positioned at (0,0), and then moved slightly along the X-axis. The white dots are corners of octree nodes, and the cyan triangles are produced by marching cubes. It works quite well, but on the border between the two cutter instances the distance-field is somehow wrong, and marching-cubes doesn't come up with the right triangles, leaving gaps instead.

Earlier I was building an octree volume-representation of a shape using a simple bool isInside(Point p) predicate function to determine which cubes are in and which are out. If instead a distance-function double distance(Point p) which is negative inside the volume, zero exactly on the surface, and positive outside, is used, then the Marching Cubes algorithm (this is a better explanation, someone should make the wikipedia page as good!) can be used to triangulate the octree. This leads to much more visually pleasing results at reasonable maximum tree-depths.

The same Hong-Tzong Yau of Taiwan who wrote a very reasonable drop-cutter paper in 2004 has more recently come out with a 2009 paper on cutting simulation using an octree and Marching Cubes.


Mowing Foam

Dan Egnor sent me this nice example of bitmap-based toolpath generation, or 'pixel mowing'. It's a slightly exaggerated topographic relief of San Francisco machined in tooling board using a very simple 'lawn mowing' toolpath generator.

The explanation of how it works below is mostly Dan's, not mine.

This is the input to the toolpath generator for one of the Z-slices.

black - material which must not be touched
green - to be removed, is safe (at least one tool radius from black)
yellow - remove if possible, is dangerous (within tool radius of black)
purple - has been cleared, is dangerous (machine limits or similar)
white - has been cleared, is safe, is not blue (below)
blue - this spot has been cleared, and is safe, but is within one tool radius of material that needs clearing (green or yellow)

Note that you don't see blue in either "before" or "after" images, it only occurs transiently. (In theory it could show up in "before" as area outside the workpiece.)

And this is the resulting toolpath. Green circles are plunges and red circles are lifts. The thick grey lines represent actual cuts, the thinner lines are rapid feeds.

The basic rule is that the tool *centroid* is only allowed to visit safe areas (green, blue, and white). Green and blue represent work to be done (safe areas that need visiting). Of course, as the tool moves, green changes to blue and white, and (some) yellow changes to purple.

The real trick is in efficiently tracking the "within tool radius of" zones (material to be cut, or material to stay away from). Every pixel keeps a count of how many pixels of each type ("nearby-blocking" or "nearby-cutting") are within one tool radius of that pixel. Whenever a value is changed ( e.g. the simulated tool moves and changes some points from "cut" to "clear"), every counter within the appropriate radius is updated.

That would be rather costly to implement directly, each simulated pixel move would require N^3 updates, if N is the diameter of the tool. Instead those counters are only kept as *differences* between each point and its neighbours. That means changing a point only requires updating the values along the *perimeter* of the radius surrounding that point, meaning that a simulated pixel move only requires N^2 updates, which makes things a lot more tractable (though it still takes the old laptop I use a couple minutes to complete the toolpaths for a 5" x 3" x 1.5" model at 1/256" resolution). Of course this means that the "color state" isn't directly accessible for a random pixel, but must be figured incrementally from neighboring values. Fortunately most operations don't access random pixels.

You would probably not want to cut metal with this kind of algorithm as there is no control over material removal rate or cutting forces, but for foam, tooling-board, or wood it should work ok.

Dan's program is written in C++ and available here (http://svn.ofb.net/svn/egnor/boring/), but it's not well documented.

We are standing by for a video of this kind of cutting!

Mowing tactics

Moving forward with the CAM coding, the sensible thing would probably be to work on mundane things like 2D offset generation, a kd-tree for faster drop-cutter searches, and zigzag-paths from 2D outlines... There's again been some talk about open-source CAM on cnczone, but not much in terms of results or actual descriptions or implementations of toolpath algorithms.

Anyway, here's something more fun than the traditional computational geometry problems I referred to above. It's lawn-mowing tactics, or how do you program the circular robot to mow the red pixels while not cutting too many of them at a time. This is a slightly improved version of my earlier trial. This one considers a number of angles in all directions for each move. From these moves the ones that cut away a suitable amount of material are selected. Additionally I've introduced a cost function for changing direction, it should be easier for the cutter to continue traveling in approximately the same direction than to do abrupt turns. In spite of this, about half-way through the cutter reverses direction...This is obviously done with a bitmap representing the grass to be mowed, but I wonder if it would be better to try to do it more exactly: represent the boundaries of the grass with lines and arcs. A variable step-length also seems like a good idea, on long straight bits the cutter should be able to move in one go as far as it goes.