Wednesday, February 22, 2017

More Robot Driven Light Paintings

I created some new light painting. This is an extension of the work I originally posted about here. Using some new path code and a battery pack to power the lights gave me more freedom of movement. The photographs were taken by my Taubman College colleague Asa Peller.

These images give you a sense of the space the robot moves within:

Here's a screen capture of the simulation of the robot. The robot follows a path curve. The path curve is divided into a certain number of points. For each point the tool remains tangent to the curve at that point. By changing the number of points you can dramatically change the nature of the motion generated.

It's a pretty close match between the simulated path and the actual robot path. But the spline interpolation is different between NURBS and what Kuka is doing with the Spline Movement motion type so they are not an exact match. It's always interesting to see the images produced by the robot.

Monday, February 20, 2017

ZBrush Portrait Sculpt Produced on 3D Printers

I finished a digital portrait sculpture and decided to realize it with 3D printing. I produced several reliefs prints and one full 3D print.

Sculpting Process

Here are some pictures of the digital sculpting process. I'm using a Windows laptop with ZBrush software. I can move around the model freely on a mobile stand.

I currently use a Wacom Intuos tablet (after using a Wacom Cintiq for years). I prefer this - it's cooler on the hand and much more of a relaxed position for my arm. And I can go for several hours without plugging in. Plus my hand is on the keyboard for shortcuts and Shift/Ctrl/Alt key combos which are essential in ZBrush.

Preparation for Fabrication

Here's the finished ZBrush model ready to prepare for routing and printing. At this point the hair, eyes, and face/shoulders are all separate objects. Doing that makes it much easier to sculpt. But they need to be one mesh to mill. The polygon count in ZBrush is 4.3 million faces. The polygon count needs to be reduced - a lot. Both DecimationMaster and ZRemesher were crashing in ZBrush. Very unusual. So I did it in Rhino using the ReduceMesh command. This is actually not nearly as good. But it was adequate.

Here's a comparison 4,300,000 faces on the left versus 360,000 on the right:

I had to fix a few really tiny naked edges and two non-manifold edges. This is fairly easy using Rhino's mesh tools (mainly DeleteFace and PatchSingleFace). I have to say - having a 3D Connexion mouse (I have the cheapest one) makes viewing and understand what to eliminate much easier. That's because you can twist the viewport so much more readily to see what's happening. In these detail cases you have to move the model while looking to understand it.

3D Printed Reliefs

Once fixed and solid I scaled 1D to push into a relatively high relief. Then I BooleanUnion a box onto the back. Here's the result - 9" high, 6" wide, 1.5" deep: 

Here's a three-quarter relief. Similar technique except rotating the 3D model first, then scaling along the axes of the CPlane. This is lower, about 1.3" thick total. 

Here's a side relief. Lower still - about 1.1" thick total.

The prints were done on a Stratasys Dimension 1200e, the one on the left. This is a ABS printer which requires support material.

The support material needs to be dissolved from the 3D print. It is soaked in a warm detergent bath for a few hours to do so.

Below you can see most of the darker support material is gone. A little remains on the edges - back into the tank. Also of note in this photo - that one was printed with the back plate flat on the printer bed. So the layers of the print look like contours across the face. Zoom in - you'll see this is a terrible idea. The print comes out just fine when printed vertically (face forward, not up).

Here's a comparison with the model, computer model, and 3D print.

In the Round 3D Print

The full 3D print was done on the printer below - a Stratasys uPrint. The printer took about 15 hours to complete the job:

Here's the finished print mounted on a Walnut base:

Sunday, January 29, 2017

Ruled and Developable Surfaces and Forms for Fabrication

This post discusses ruled and developable surfaces and their use in digital fabrication. It defines the terms, discusses the generation and layout of parts, and methods of assembly to combine back into 3D form. It also shows methods of analyzing forms to determine if they are ruled and developable.

If you'd like to examine and experiment with the surfaces shown below you can download the Rhino file here.

Ruled Surfaces

A ruled surface is generated by sweeping a straight line through space. For every point on a ruled surface there is at least one straight line which lies on the surface. Examples are cylinders, lofts between two rotated circles, curves extruded along a straight line, or straight lines swept along a curve.

Doubly-Ruled Surfaces

A surface is doubly ruled if for every point on the surface there are two different lines that lie on the surface. An example of this is a hyperboloid, shown below. One of these can be generated by simply lofting two circles which have start points (curve seams) which are not aligned but rather are rotated relative to one another.

The loft is hyperbolic - saddle shaped - doubly curved in different directions:

The curvature circles (Rhino Curvature command) show the principal curvature at any point. Here you can see the circles curve in opposite directions. A later section of this post discusses the use of the Curvature command in more detail. 

Here you can see the two straight lines for every point:

Developable Surfaces

A special type of ruled surface is said to be developable. A developable surface can be unrolled onto a flat plane without tearing or stretching it. That is no distortion will be introduced when it is laid flat on the plane.

The Rhino command UnrollSrf is used to flatten a surface or polysurface with curvature in one direction onto a plane. In the image below you can see an unrolled cylinder, cone, truncated cone and extrusion. In these simple cases I think it's easy to visualize how those surfaces can be unrolled.

Some examples of ruled, developable surfaces are cylinders, cones, truncated cones, and curved shapes that are extruded along a straight line.

Curvature of Surfaces 

Principal Curvatures

The Curvature command shows the Principal Curvature for a surface. The principal curvatures measure the maximum and minimum bending of a surface at each point.

When the principal curvatures are positive that means they curvature is in the same direction (both positive or both negative). This means the curvature is bowl-shaped.

When the principal curvatures are in opposite directions (one positive and one negative) the result is a negative value as below. This means the surface is saddle-shaped.

When the principal curvatures are zero it means the surface is flat in one direction.

The principal curvatures are used to compute the Gaussian and Mean curvatures of the surface.

Gaussian Curvature

The Gaussian curvature of a surface at a point is the product of the principal curvatures at that point. The tangent plane of any point with positive Gaussian curvature touches the surface at a single point, whereas the tangent plane of any point with negative Gaussian curvature cuts the surface.

Positive Gaussian Curvature: A positive Gaussian curvature value means the surface is bowl-like. This surface is synclastic.

Negative Gaussian Curvature: A negative value means the surface is saddle-like. This type of surface is referred to as anticlastic.

Zero Gaussian Curvature: A zero value means the surface is flat in at least one direction. (Planes, cylinders, and cones have zero Gaussian curvature).

Curvature Terminology Summary

Below is a summary of the terminology used above:
  • Principal Curvature: The maximum and minimum curvature at a point on the surface. 
  • Gaussian Curvature: The product of the principal curvature values at a point. 
  • Synclastic Surface: A synclastic surface is one where the Gaussian curvature is positive everywhere. A point at which the Gaussian curvature is positive is called an elliptic point.
  • Anticlastic Surface: An anticlastic surface is one where the Gaussian curvature is negative everywhere. The surface is saddle shaped. 
  • Developable Surface: A developable surface is a surface with zero Gaussian curvature. That is, it is a "surface" that can be flattened onto a plane without distortion (i.e. "stretching" or "compressing").

Rhino Commands and Grasshopper Components for Creating Ruled Surfaces

There are many ways to create ruled surfaces in Rhino. The key is using straight lines as input to the commands. Here are a few examples:

Some of these commands are discussed below:
  • ExtrudeCrvToPoint: This command will generate conical forms which are ruled. It works because the curve is extruded up to a single point. Thus there's always a straight line from the curve to that point, and thus the surface is ruled. 
  • Sweep1: This command will generate a surface by moving a curve along a rail curve. If either of the curves is a straight line the surface will be ruled. 
  • Sweep2: A surface is generated by moving a curve between 2 rails. If the rails are straight lines, or the contour curves are, the surface will be ruled. 
  • Loft: When you loft between two curves you can generate a ruled surface. 
  • EdgeSrf: This command will generate a surface between 2, 3 or 4 open curves. If the input edges are straight lines a ruled surface results. 

UnRolling for Fabrication

It's a common practice to want to unroll forms, cut them from sheet material, then re-assemble them back into a 3D object. One method of doing this involves tabbing the edges of the surfaces.

The Rhino Polyhedra plug-in allows you to create an amazing variety of polyhedra. Those that can be generated as solids have planar faces. They can therefore be unrolled using the UnrollSrf command.

It is possible to take surfaces which aren't developable and make an approximation of them which are developable. Here's an example - a sphere - clearly not developable:

Un-Folding Mesh Forms

Meshes are composed of quads and triangles. These meshes can be unrolled. A free program to do this is Pepakura Designer. It takes 3D mesh models and will let you designate the seams where the model splits apart to unroll flat. It will also generate the tabs so you can secure them back together. This is a remarkable, easy to use program well worth checking out.

Here's an example of a Rhino Polyhedra, exported as a meshed OBJ, then loaded and unrolled in Pepakura.

Using the free version you can export the result to a PDF file (which will have the graphics in a vector format). You can then import the PDF into Rhino and modify the layers, linetypes, scale, etc. to get it ready for cutting out). 

If you purchase a commercial version of Pepakura you can export directly.

Programatically Unrolling

The UnrollSrf command can be used by a Python script or Grasshopper definition to unroll as part of a program.

A handy way to assemble unrolled forms is by tabbing the edges of the unrolled surfaces. These tabs can be made to interlock so the cut pieces can be reassembled. In this example a Grasshopper definition was used to generate a 3D form by sweeping a curve along a polygon rail. The rail is a triangle and thus the straight edges make a ruled, developable surface. The definition generates tabs along the edges.

The parts are cut on a CNC knife cutter. In this case several forms were cut from the same sheet of material - 0.03" thick PETG plastic.

The tabs lock the parts together and also ensure that the curvature remains true to the original form.

Here are the cut parts, with the plastic overlay removed, assembled by interlocking the tabs:

Hot Wire Cutting of Ruled Surfaces

Another application for ruled surface geometry is driving a robot with a hot wire cutter. The heated wire vaporizes the foam as it slowly moves through it. Because the wire is a straight line the resulting surfaces are inherently ruled.

Since we create the surfaces to drive the robot we do so by developing ruled surfaces in Rhino.

See this post - Hot Wire Foam Cutting Using the Robot - for an example of hot wire cutting a variety of ruled surfaces in expanded polystyrene foam with the robot.

Monday, January 16, 2017

Robotic Painting with a Line of Lights

This post documents a method of generating light paintings using a robot moving a linear array of lights through space. The robot moves a simple stick tool which contains 60 lights stretched along its 1 meter length. Each light can be individually controlled, any one of 16 million colors, and that color can vary over time.

The image is recorded using a camera which keeps the shutter open during the entire motion of the robot. Everything happens in a very dark room so the great majority of the light collected comes from the lights only. The result is a single image showing the entire path of the line of lights.

Grasshopper Definition

The robot motion is controlled by a simple Grasshopper definition using the plug-in Kuka|prc. The motion is driven by an input curve and a few parameters described below.

There are two parts to the definition. One simulates and generates the robot code. You work with this part of the definition to assure that the robot can reach the entire curve without hitting joint rotation limits and that the tool does not collide with the robot table.

The other part of the definition is used to simulate the light effect prior to running on the robot. This is important because it is impossible to visualize the path of the lights as they rotate traveling along the input curve.

See the post Working with Planes in Kuka | prc for information on various methods of dividing curves and driving the robot.


The adjustable parameters are as follows:
  • Curve: The curve the robot follows. The robot face plate and tool rotate so the line of lights is always perpendicular to the curve at every point. It's this twisting motion of the line which generates the visual interest. 
  • Curve Divisions: The entire length of the curve is divided into the specified number of segments. By varying this parameter you can get a great variety of outputs. In general, the most interesting results are obtained using low values. 
  • Tool Length: This is fixed for the Taubman College tool which is 1 Meter long. 
  • Lights on Tool: To simulate accurately you need to tell Grasshopper how many lights will be illuminated on the stick. This can be either 15, 30 or 60. The actual number of lights used is set on the tool itself. 

The Curve obviously has a major impact. But it's surprising that using different curves with low division counts you can get some amazing effects. Here are a few sample curves drawn in Rhino:

It's of course also possible to wire in a parametric curve generated by Grasshopper.

The strip of LEDs has 60 lights per meter which is the length of the stick. The Arduino code allows you to set the number of LEDs which are illuminated. By using every every 1/12th you can have 5 lights show along the length. Using 1/4th you can have 15 as shown below:

Every other LED produces 30 and every LED is 60:

Here's are examples using the same curve with a different division count:

Here's a different curve with two different division counts:

The End Effector

The tool attached to the robot is basically a stick made of 1/2" Baltic Birch plywood. There's a small box to house the electronics. Milled into the stick are some grooves for the light strip and the wires.

The lights are NeoPixel strips made by Adafruit. Everything is driven by an Arduino.
There are a few simple controls - two push buttons, and three knobs:

Here's a video demo of the controls (description below):

Push-Button 1

Use this to change between the 5 different light effects. Press the button to change to the next mode - the sequence is as follows:
  1. Constant color for all lights - same over time. Use Knob 1 to set the fixed color. 
  2. Unique color for all lights - same over time. Use Knob 1 to shift the colors along the line of lights. 
  3. Unique color for all lights - rotates along the strip over time. Use Knob 1 to shift the colors along the lights. Use Knob 2 to set the rate of change. 
  4. Random colors for all lights - same over time. 
  5. Random colors for all lights, rotates along the strip over time. Use Knob 2 to set the rate of change. 

Push-Button 2

Use this to control the number of lights which are illuminated on the stick. As you press the button the number of lights lit will switch as follows:
  • 5 LEDs 
  • 15 LEDs 
  • 30 LEDs 
  • 60 LEDs

Knob 1

Changes the color of each light. Rotating the knob moves the lights through hue space. All the way counter-clockwise is 0, fully clockwise is 360, where:

0=Red, 60=Yellow, 120=Green, 180=Cyan, 240=Blue, 300=Magenta, 360=0=Red.

How the change effects each light depends on push button 1 (see above).

Knob 2

Use this to change the intensity (brightness) of the lights. All the way to the left is dimmest, all the way to the right - don sunglasses.

Knob 3

Use this knob to specify the rate of change of the light colors over time. Slowest is all the way counter-clockwise. Fastest is fully clockwise.

The Robot

These examples were generated on a small Kuka Agilus robot. Like all robots it has a limited reach and range of motion. There are a few controls in Grasshopper you can use to allow the robot to reach every point on the curve.

Initial Position: This is key. You need to pose the robot in a neutral position for the start of the motion. None of the joints should be near their limits and it should be roughly centered on your path. You set this in the Kuka | prc Settings, on the Advanced Page.

Middle Point Location: This is the most important tool for solving joint limit problems. If you encounter a position in the path where a joint turns red, leave the simulation slider where that joint is red, and move the middle point location a bit. Usually you can find a spot where the joint is no longer in a limit. This can be up or down, or closer or farther from the robot. Note: There are curves which are impossible to fully reach. But if your curves are not larger than the samples provided you'll probably be able to find a position which works.

Arduino Hardware and Software Details

This section describes the wiring and software setup.

Below is the prototype I built using components I had on hand to test with. A slide potentiometer for the hue selection, a cheap pot for knob 2, one nice push button and one piece of junk. These were replaced with better components in the final tool.

The NeoPixels need current. 60 pixels at full brightness need almost 4 amps. An Arduino supplies only 0.5 amps as does a 9V battery. So an external power supply is necessary. This is the one I prefer: 5V 4A (4000mA) switching power supply.

The color is computed in Hue space but needs to be provided to the LEDs as RGB values. I used some great code I found online to do this: Why every LED light should be using HSI colorspace.

The prototype used an Arduino Uno. The final version needed a smaller footprint micro-controller so I used an Arduino Micro.

The face plates are laser cut acrylic. I got the buttons here and the pots here.

My research assistant Celine Schlueter did all the soldering:


The process needs some more development but I like the initial tests of this new tool.

For some other image painting tests see this post.


I've done more work on this project. The results are here: More Robot Driven Light Paintings