Wednesday, February 25, 2009

Smoothstep Interpolation with Arduino


I have a friend who is crazy about timelapse photography. Lately he has been experimenting with motion control camera equipment to make his shots more dynamic . Most of his gear is built from combining off the self components in different ways. Nick is wanting more control out of his devices. So I introduced him to the world of electronics and micro controllers.

Now we are endevouring to break some new ground in timelapse (at least for us ;) The first task I have been appointed with is to come up with a way to go from no camera motion to full camera motion in the smoothest possible way.




Below is a snippet of Arduino code utilizing the smoothstep function. I very powerful formula for smoothing the interpolation from one value to another. Also check out this post for a python example video of the same formula

Check out some of Nick's beautiful timelapse work at nickgraalman.com

For more info and pics on the smoothstep method check out this link. This code is also featured on the Arduino Playground Wiki in the Code Library and Tutorials Section


///////////////////////////////////////
// Smoothstep Interpolation Example //
///////////////////////////////////////

// Dan Thompson 2009
//
// Inpired by the code and chat on this site.
// http://sol.gfxile.net/interpolation/index.html
//
// Use this code at your own risk.
//
// This sketch was written with motion controlled timelapse photography
// in mind. I have tried to make it generic enough to understand the smoothstep
// concept so that one might adapt this powerful formula in other areas as well.
//
// For the full tutorial visit http://danthompsonsblog.blogspot.com/
//
// Usage:
// 1. Upload the sketch to the Arduino.
// 2. Click on the Serial monitor to see some visual feed back of the SMOOTHSTEP function.
// 3. Scroll throught the print out to see the SMOOTHSTEP curve.
// 4. Play with the code and addapt it to your needs! ;)

#define SMOOTHSTEP(x) ((x) * (x) * (3 - 2 * (x))) //SMOOTHSTEP expression.

int j = 0; //Just an Iterator.
int i = 0; //Just another Iterator.
float A = 0.0; //Input Min Value
float B = 100.0; //Input Max Value
float X; //final smoothstepped value
float v; //smoothstep expression variable
float N = 100.0; //number of steps

void setup() {
Serial.begin(
9600); //establish serial connection for debugging
}

void loop()
{
if (j < N) // Keep looping until we hit the pre-defined max number of steps
{
v
= j / N; // Iteration divided by the number of steps.
v = SMOOTHSTEP(v); // Run the smoothstep expression on v.
X = (B * v) + (A * (1 - v)); // Run the linear interpolation expression using the current smoothstep result.
for ( i=0; i < X ; i++) // This loop could the relevant code for each time your motor steps.
{
Serial.print(
"1"); //Prints the number "1" for each step.
}
Serial.print(
" "); //Puts a space between each line of steps and their corresponding float value
Serial.println(X); // prints the soothstepped value
Serial.println("CLICK!!!"); // this could be where you trigger your timelapse shutter
j++; // Increments j by 1.
}
}

13 comments:

dail8859 said...

Dan, I have been working with Kevin for a little while now and he pointed out this post. Here is what i came up with

http://www.youtube.com/watch?v=vD_VCBO1lw4

Dan Thompson said...

Justin,

That's some seriously impressive stuff! It's great to have someone with your skill set involved with this.

What are you using to display the lines? Is it wxPython? Kevin told me about your keyframe based approach. Nice idea!

I'm guessing your next step is getting bezier curves to export out of blender. I wanted to do something similar to what you are doing using processing. I hadn't even considered doing the gui in python.

Nice work!

Dan.

p.s. do you mind if I blog you video?

dail8859 said...

Dan,
I am using pygame. See www.pygame.org

Using the python inside of blender is extremely easy to get the keyframes from the curve. And it is fairly easy to create a GUI for it inside of blender.

Feel free to do whatever you like with the video.

Tom Spiers said...

Hi

I have just recently been learning about Arduinos and the capabilities and as an Animator/Video person also with a fascination with time-lapse and effects in general I have been getting very excited about the possibilities.

So I was even more excited to find your blog as I had started to wonder, "just how hard would it be to build your own motion control camera"? And suddenly found myself reading the blog of someone who seems to have started down that path.

So I pose the question, do you think is possible currently to to build a motion control rig that could function in real time pretty much as the full size rigs like Milo's do that could carry a reasonably sized camera such as a SONY XDCAM?

Obviously I guess there some issues to do with the weight carrying ability’s of stepped motors and such but I’m thinking there are ways around this such as smaller stepper motors driving the speed of larger load carrying ones or some such thing.

In the meantime all the best with your future experiments.

Tom

Dan Thompson said...

Welcome Tom,

The short answer is, yes I believe it is possible these days to build a motion control rig, I know so because I have spoken with people who have done it. But there many ways you could configure a device such as this.

Rigs like the Milo and Genuflex are highly engineered commercial products and are designed to suit almost any application in the field.

I would recommend starting out with something small and limited functionality and then add to it as you go. That way you will learn from your mistakes as you go and hopefully not waste to much money on hardware in the process.

As for me, I am taking "The Long Way Home" ;) I am spending a lot of my time on software design and workflow first as I can not afford much of the hardware at this point in time.

It's stating the obvious but, it's all about time and money in the end. :)

Marcel said...

A head-slapping moment for me tonight.

I've got the Smoothstep code working (thanks chaps) and I used it to populate an array of interval timings that I would use to drive my uSecond based (non-blocking) stepper drive code.

Problem 1) I seem to be running out of RAM on the Arduino the moment I get to useful array sizes ≈300 integers. (I'm using an array of values to save processing time while running the steppers.)

Problem 2) Time. Contrary to popular belief, time is not linear!
I mean, a 50uSec difference when my step interval is 10,000 makes no difference, but it makes all the difference when you're running at 100uSec step intervals!!

So, back to the drawing board for me.
[m]

Unknown said...

Hi. that looks interesting! I have a sketch to control a stepper via a stopmotion software (dragon). put I only managed to ease-in/out with a ramp function.
I don't really understand all your inputs (eg. j).
Can you give me some advice to adapt it to my needs?
thanks a lot

Unknown said...

here is the code I'm using. maybe it explains my question a bit better.

http://arduino.cc/forum/index.php/topic,54546.0.html

Dan Thompson said...

Hi Julian,

I don't own Dragon or know how it's library works for that matter. Do you have any links to some docs for the arduino library. Can't promise anything but I can have a look.

Dan.

Daniel Potthast said...

Brilliant, thanks for this.

I am trying to make a simple linear interpolation script--juggling multiple dimensions for dolly, pan, tilt, and focus...also for timelapse applications.

I am good with python but a little sketchy with the C in Arduino.

Would a simple modification to the smoothstep expression keep my interpolation linear across these dimensions?

thanks

www.danielraphael.info

Daniel Potthast said...

Silly question, premature. got it from your code... what great and simple solution, my favorite kind...

dp

Nickatredbox said...
This comment has been removed by the author.
Nickatredbox said...

Really interesting stuff I too have an interest in control systems and am tinkering with an Xbee Arduino remote control system. Would like to user your elegant approach with SMOOTHSEP to make the servo output smoother between update frames. Nice work mate :)
See my tinkering here
http://kiwitricopter.blogspot.co.nz/p/control-system.html