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.
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 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 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):
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).
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.
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:
For some other image painting tests see this post.
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.
Parameters
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:- Constant color for all lights - same over time. Use Knob 1 to set the fixed color.
- Unique color for all lights - same over time. Use Knob 1 to shift the colors along the line of lights.
- 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.
- Random colors for all lights - same over time.
- 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.
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:
Conclusion
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.