Please can someone point me in the right direction? I'm hoping that this is a solved problem for somebody out there.
I need a function that will limit Acceleration and Velocity, generating at each sample time a new position that meets the V A constraints. The input position is kept within bounds.
A vital design requirement is low signal latency, ideally I want a current answer for each sample.
I started by looking at motion interpolators of various kinds, e.g.
but interpolators assume that you begin with a fixed start and stop position, and from those generate a series of interpolation points (within the sample time) that will take you from start to stop, such that you reach the end position with velocity zero.
I started with code that calculated the velocity and acceleration and limited them:
deltaT = time step between points start with cur_pos = cur_vel = cur_acc = 0 max_acc and max_vel set to +ve values, don't change during runtime
PSEUDOCODE:
function LimitVA ( new_pos ) // calculate actual distance from current position dist = cur_pos - new_pos // velocity needed to get there from here vel = dist / deltaT // acceleration needed to reach that velocity acc = (cur_vel - vel ) / deltaT // Limit the acceleration to allowed values acc = limit ( acc, -max_acc, max_acc ) // calculate new velocity (using "v = u + a*t") vel = cur_vel + acc * timestep // Limit the velocity to allowed values vel = limit ( vel, -max_vel, max_vel ) // calculate new position cur_pos = cur_pos + vel * deltaT // remember velocity cur_vel = vel // result return cur_pos
Now, this version has terrible overshoot, followed by ringing. For example, using a step function as input, the output position accelerates to the end point, and is going far too fast to stop there.
So I modified the code to take into account the 'time to stop' as shown:
PSEUDOCODE:
function LimitVA ( new_pos ) // how long to stop at current velocity? time_to_stop = abs ( cur_vel / max_acc ) // where will we be then? ( s = u*t + 0.5*a*t^2 ) projected_move = cur_vel * time_to_stop + 0.5 * cur_acc * time_to_stop^2 dist = cur_pos - new_pos // change velocity to reflect possible stop position vel = ( dist - projected_move ) / deltaT acc = (cur_vel - vel ) / deltaT acc = limit ( acc, -max_acc, max_acc ) vel = cur_vel + acc * timestep vel = limit ( vel, -max_vel, max_vel ) cur_pos = cur_pos + vel * deltaT cur_vel = vel return cur_pos
Now this is better, but it is 'unstable'. For some values of 'max_vel' and 'max_acc', and for different position sequences, the output can 'hunt' around a reasonable value. Also, this code assumes that we will stop. - which may not be true. With slowly changing signals, sometimes the result is a series of steps - which I want to avoid.
Variations on the above code have not given significantly better results.
Now, I'm looking at other possibilities, which have taken me in the direction of curve fitting. But I'm not sure if I've missed something in the above.
Also, choosing a curve fitting algorithm, given the desired constraints on velocity and acceleration, looks like a non-trivial task.
So, if anyone out there has a suitable alternative, advice where I may be going wrong, or can point me at a web resource, I would be very grateful.
Thanks, TrissT