acceleration slidermovement in timelapse, algorithm problem

Hi

I made a camera slider with stepper (programmed in Arduino :wink: ) implementing different usage scenario's.
(camera moving for video, stepping for focusstack shots and timelapse, etc)

Implementing acceleration/deceleration of the slider during a timelapse is causing me headache though and it looks like I'm stuck..

Until now I was not able to find the correct algorithm to calculate the number of pictures to take during acceleration and the constant move part.

The number of exposures is fixed.
The distance in which the acceleration/deceleration is taking place is also fixed. This is also true for the total slider distance.

In timelapse acceleration/speed of the slider is accomplished by varying the distance between each shot/frame and not the speed in which the slider actually moves.

In this example I forget the deceleration part. So: use incrementing distance between shots in the first part and then continues using a fixed interval distance until the slider end is reached.

WHITHOUT ACCELERATION (ONLY A CONSTANT SPEED/MOVE )
amount of frames (shots) 70
total distance 40cm => 32400 steps (believe me.. :wink: )

algorithm:
frame interval distance 32400 / 71 = 456steps

nofShotsAccel= 0
nofShotsConst= 70

make shot
move slider 456 steps
wait delay time between shots
repeat until all done.
final shot.

WITH ACCELERATION
My objective is: the slider starts moving slowly until the max speed is reached at 15cm.
We are in a timelapse so the slider first makes little moves and then endup with the
largest move at 15cm, which should also be the constant distance to use until the 40cm is reached.

(no good..) algorithm:
acceleration distance 15cm => 12150 steps

frame interval distance 32400 / 71 = 456steps
nofShotsAccel= 12150/456 = 26
nofShotsConst= 70- 26= 44

make shot
if shotcnt <= 26 dist= CubicEasIn( shotcnt/nofShotsAccel) * 12150
else dist= 456 steps
move slider dist steps
delay until time between shots elapse
repeat until all done.
final shot.

The big problem here is:
Acceleration starts with little moves and then accelerates until the distance is reached. Because of using little steps at the beginning bigger steps at the end of the acceleration are needed.
And of course they will exceed the constant step size used after the acceleration (456steps) to compensate the steps which are smaller.
In the final clip this will result in a nice start but ending at a very fast and then will drop to the slower constant distance after the accelerating part.

All distances during acceleration should always be smaller than the constant stepsize.
The only way to accomplish this is making more frames during the acceleration part. (=>more smaller steps until 15cm is reached)
Because the total amount of frames is fixed (70) and more shots are needed during acceleration less shots will be taken during the constant move (40-15cm).
But this implies a bigger constant distance... So this distance depends on the number of shots taken during acceleration. The number of shots used during acceleration depends on this distance though...

There just has to be an algorithm to find the optimum but I couldn't find it yet.

So the question is:
how to calculate the number of shots to take during acceleration in such way it's max interval distance will never exceed the interval distance during the constant move cycle.
Of course I also have to deal with a deceleration part which start at the end of constant move/speed part

Anyone is able to put me in the correct direction..?


In CubicEasIn( t ) t is 0..1 and will generate an accelerating multiplication factor 0..1 corresponding the frame taken.
So it starts at distance (012150) and ends at it's max (112150)

Just a dumb idea.. What happens if you shoot at constant time intervalls instead of constant distances?

What would happen if you calculate a small step size and an increment. For example 100 and 50. The first move is 100 the next is 150, the next is 200 etc. When you get to the mid point (16,200) reverse the maths. Or you could "decelerate" at a different rate.

It would be equally easy to use multiplication to calculate the next movement interval.

It would be easy (and quick) to run through the maths without moving anything to ensure that it fits, and to make adjustments if necessary.

If the total number of steps is small (perhaps 100 or 150 - i.e. so you don't use too much SRAM) you could fill an array with all the interval values and move the motor based on the values in the array. You could store several pre-determined sets of array values in PROGMEM.

...R

@nilton61

time intervals are only relevant for the clip length. Every second has a fps number of frames. (25fps in Europe)

Here I'm talking about the speed the slider moves in the clip. Now the sliderposition at the time a shot is made is important.

@Robin2
The cliplength is max. 30min. This implies 306025= 45000 frames (positions...) at 25fps. Even worse at fps 60.. An array can get pretty massive for this. However, a clip of 5secs or so counts only 125frames. So the amount of positions(frames) can differ a lot. that's why I think you really need a kind of formula/algorithm to calculate this.

It's no problem to do some math to cycle through all positions to find the optimum balance.
The problem is to find the algorithm to do so, though.

This might help you. The AccelStepper library is built on it.

fredvr:
The problem is to find the algorithm to do so, though.

That's why I suggested some.

...R

@nilton61
Hi Nilton thanks but in a timelapse situation stepper speed is not relevant!
Basically I am already using the accelstepper for rotating my stepper... In the timelapse scenario however I'm moving the stepper from position to position as fast as I can and then wait at that position until it's time to take the shot! After that move quickly to the next position and so on.

The positions where the slider sits at the point the exposures are made are responsible for the final slider speed in the clip. So when a shot is made the slider doesn't move at all! Moving the slider when taking a shot might even blur the picture.. :wink: Time is more or less purely relevant for clip duration in timelapse, not for simulating slider speed.

@Robin2
Sorry Robin. What I ment was not a disqualification of your help.. :wink: I'm happy with every help I can get and I really appreciate yours!
I'm going to play with your idea and see if I can work something out with that. the use of arrays will be a problem though because of the size it might need.
My feeling is I'm making a basic theoretical mistake in approaching this problem somewhere.

fredvr:
I'm going to play with your idea and see if I can work something out with that. the use of arrays will be a problem though because of the size it might need.

In my original post the ideas for algorithms were entirely separate from the idea of an array.

And I specifically mentioned that the array would only be an option if there was only a small number of steps - I was taking care to anticipate what you said subsequently.

...R

So, do i understand you correctly as this is what you want to achieve?

  • You want to take pictures that have the same shoot positions as if you where shooting at a constant frame rate during a acceleration/constant speed/deaccelleration (trapetzoid profile) movement
  • You want to stop the slider at each shoot position

@robin2

In my original post the ideas for algorithms were entirely separate from the idea of an array

That is what I understood

  1. I'm going to play with your idea and see if I can work something out with that.
  2. the use of arrays will be a problem though because of the size it might need.

So I'm not focussing on using an array

I'm working on your idea to stop at the midpoint and reverse the math and see if I can get closer that way.

@nilton61
Ooops, not sure if I understand what you're saying... :o but this is what I want to achieve:

  • timelaps: create a video clip with a duration of nn secs of an event which has a much longer duration
  • move the camera position in the clip using acceleration, constant speed and decelerate

You need a lot of individual pictures (samples) to generate a video clip of nn secs

  • amount of pictures needed => nn secs clip duration / frames per second ( => 25 in my situation)
  • delay between each picture => event duration / amount of pictures

To get the effect of camera motion in the clip, the camera needs to be at a different position in every shot. In de case of accel/decel the distance interval between shots needs to vary.

fredvr:
I'm working on your idea to stop at the midpoint and reverse the math and see if I can get closer that way.

I would use a spreadsheet to experiment with this type of thing - instant feedback.

...R

I believe this is what you want to do, but not quite sure:

//defined values
int framerate = 25;//fps
int frames = 70;//number of frames
int distance = 1000;//arbitrary units
double singleRampTime = 1.0;//acceleration or deacceleration in seconds
//helper values
double timeFrame;//total time
double rampTime;//seconds
double cSpeedTime;//constant speed time in seconds
double cSpeed;//constant speed in units/sec
double acc;//Acceleration in units/sec/sec
double rDist;//ramp distance in units
double cSDist;//constant speed distance in units
int rFrames;//Ramp up or ramp down frames
int cSpeedFrames;//constant speed frames

void setup(){
    Serial.begin(115200);
    preCalc();
}//setup()

void loop(){
  Serial.println("Enter framenumber");
  while(!Serial.available());//wait for input
  int f = Serial.parseInt();//get framenumber from user
  Serial.print("frame munber:");
  Serial.println(f);
  Serial.print("is at distance:");
  Serial.print(aFrameDist(f));
  Serial.println(" units from start");
  Serial.print("and at distance:");
  Serial.print(relFrameDist(f));
  Serial.println(" From previous frame pos");
  while(Serial.available()) Serial.read();
}//loop()

void preCalc(){//calculate helper values
  timeFrame = frameTime(frames);
  Serial.print("timeFrame:");
  Serial.println(timeFrame);
  rampTime = 2*singleRampTime;
  Serial.print("rampTime:");
  Serial.println(rampTime);  
  cSpeedTime = timeFrame-rampTime;
  Serial.print("cSpeedTime:");
  Serial.println(cSpeedTime);
  cSpeed = distance/(cSpeedTime+singleRampTime);
  Serial.print("cSpeed:");
  Serial.println(cSpeed);
  acc = cSpeed/singleRampTime;
  Serial.print("acc:");
  Serial.println(acc);
  rFrames = singleRampTime*framerate;
  Serial.print("rFrames:");
  Serial.println(rFrames);
  cSpeedFrames = cSpeedTime*framerate;
  Serial.print("cSpeedFrames:");
  Serial.println(cSpeedFrames);
  rDist = rampDist(rFrames);
  Serial.print("rDist:");
  Serial.println(rDist);
  cSDist = cSpeedDist(cSpeedFrames);
  Serial.print("cSDist:");
  Serial.println(cSDist);
}//preCalc()

double aFrameDist(int f){//calculates absolute distance to frame f
  if(f<=rFrames)//frame is in acceleration ramp
    return rampDist(f);
  else if(f<=(rFrames+cSpeedFrames))//frame is in constant speed
    return rDist+cSpeedDist(f-rFrames);
  else//frame is in deacceleration
    return distance-rampDist(frames-f);
}//aFrameDist(f)

double rampDist(int f){//calcultes ramp distance for frame f
  return acc*frameTime(f)*frameTime(f)/2;
}//rampDist(f)

double cSpeedDist(int f){
  return cSpeed*frameTime(f);
}//cSpeedDist()

double relFrameDist(int f){//calculates distance from lat frame pos
  return aFrameDist(f)-aFrameDist(f-1);
}//relFrameDist()

double frameTime(double f){//calculates time for frame f
  return f/framerate;
}//()

i made a speadsheet with the same calculations attached in the zip file

frame position.zip (2.39 KB)

Guys I really appreciate your help!

@robin2
I often make use of excel for this type of things. When I try to check algorithms or some more complex program flow or do some optimisations I make use of Codelight (free and very simple to use C++ env) which has a perfect debugger and fast compiler. There I can simulate the flow and it's pretty easy to port the code and add hardware specific elements later in Arduino.
In CodeLite I write stuff like array content and output like this to a textfile which I import in Excel.

@nilton61
Woow you did make it a complete project yourself..! :slight_smile:

Thanks a lot for your work. I will have a close and serious look at your work but 'unfortunately' from today I have of a little vacation and not able to work on it before the weekend..


Could have a quick look at your excel en played a bit with it

  • looks like you are still involving the time element in this..
    time between frames is only relevant for the speed of the video and completely irrelevant for the camera movement where this is all about!
  • I put all frames in a row and I'm afraid it's not giving the result you tried to achieve..

I added a new TAB to the sheet which shows better what I want and where we differ and that's how I implemented it arduino at this moment.
It looks like nice this way but as you can see the total ramp up distance is short. 104 for optimal ramp curve and 300 for required distance.
(See updated excel and graph)
The extra TAB in the xls (fred-experimental) shows the frame numbers (55 ramp and 41 constant frames, instead of 26 and 67) which has the correct result IMHO. But this is just achieved by experimental changing values and not using math...

frame position1.zip (20 KB)