RC Servo Acceleration & Deacceleration

My theory is that smoother servo movements can be achieved by ramping up/down servo speeds at the beginning/end of servo rotations. I’m experimenting with a BRAT walker right now, but I think the fundamental concept of smoothing servo movements to prevent jerking at abrupt start due to reaction and end due to momentum would be applicable to a lot of different things.

I understand that hobby servos don’t have speed control per-se, but arbitrary rotation speed can be achieved by having a microcontroller handle the pulses directly. This is what the SSC-32 does.

The SSC-32 is a great product and super convenient. If it had an extra position command parameter that in addition to speed, also handled an “acceleration period”, then life would be easy. However, it does not and I imagine adding such a capability to the SSC-32 would not be trivial even by someone that knew what they were doing at the SSC-32 firmware level. (Definitely not me.)

As a first step experiment to solve this problem, I’ve tried programming at a high level on a PC and sending multiple position/speed commands to the SSC-32 for controlling servo acceleration. (I’m doing this with 115kbps serial over Bluetooth using BlueSMIRF connected to SSC-32). I wasn’t sure if the serial connection would be fast enough for this to even partly work, but it turns out that it does kind-of work for servo acceleration. I can visibly see the servo accelerate before reaching the requested speed. It’s not great though as the acceleration is not always uniform especially as things get faster, most likely due to the latency of wireless serial connections. Even without latency though, this is a brute force approach and I’m not sure that the pulse resolution would ever be enough for really smooth acceleration due to having a non-real-time PC controller in the loop.

(Fyi, the algorithm is to give SSC-32 position/speed commands whenever the PC determines that current speed has changed since the last command was sent. Importantly, the position given to SSC-32 is always the desired end position. Only the speed parameter changes. The PC/serial link is not fast enough to try and give stepped positions across the entire movement at any reasonable speed.)

Even if that worked satisfactorily though, deacceleration is more of a problem because there is no feedback loop. The PC does not know when the servo is reaching the end position. It could calculate/interpolate for the servo position and try handling deacceleration the same way as acceleration, but most likely the PC estimations would rarely match the actual servo positions, and so would not be precise enough to be useful given the small time periods that deacceleration would need to take place in.

So… anyone still reading at this point? :laughing: If so, anyone have suggestions or think this is a worthwhile exercise?

Only idea I can come up with at this point is to remove the SSC-32 and instead use a custom BasicAtom or Propellor based servo controller. (I think the BasicAtom could handle this, though not positive yet. I think using BasicAtom depends on whether or not subsequent HSERVO command cancels previous command. I’m also not sure how many servos the BasicAtom could handle with this additional logic.) I haven’t worked with either of them yet, but both look doable by someone like me with enough determination and time. (I’m good at higher level programming, okay with lower level (non-assembly) programming, complete idiot with electronics.)

Any thoughts appreciate.

Acceleration and deceleration has been implemented in RIOS for our arms. The difference is noticeable, but not dramatic. The SSC-32 and PC control program does indeed make this type of control possible. In fact there would no advantage to trying it with other control schemes. The reason I feel confident in saying that is it’s the limitation of the servo itself that prevents good accel and decel response curves.

Accel and decel is normally much more important with larger assemblies. But that point aside I think the servo control method itself prevents this from working in a very responsive way. Unless you slow movements down considerably there just isn’t enough control nodes to make the process noticeable. The servo can only react to a change in it’s speed after it receives a new position pulse. That happens 50 times a second. I think that is too coarse of resolution. Also the servo normally needs to receive a few consecutive servo pulses before it actually starts to respond to them. I’m not a math wiz, so I can’t provide a detailed time vs. response chart, but my gut tells me it’s not going to be a dramatic improvement.

Thank you. Very helpful.

I looked at the screenshots for the RIOS, but didn’t see anything obvious specific to this. Is the accel/deaccel built-in to every arm movement? Just curious.

In any case, it sounds like you’re saying you are able to have the PC send IO commands to the SSC32 at 50hz or better. If I’m not able to do that then I should rethink my PC programming (or verify if it’s actually the Bluetooth that’s causing the latency).

I had considered that 50 updates per second would be the max resolution for hobby servo, but I still thought that would be enough to discern some positive effect. My basic assumption was that most controlled (slower) robotic movements could average a 1+ second duration in total movement, and so assuming .25 seconds spent accelerating, that would be ~10-12 steps available. That’s a total assumption though, and maybe 1+ seconds per movement is unrealistic and/or too slow in reality.

And even at that, given your thoughts and observations it appears I’m most likely wrong on how much affect it would have too. It sounds like 10-12 steps might not be enough to make this worthwhile for any realistic speeds. Maybe I should buy an arm and the RIOS program and experiment for myself, hey? :wink:

Do you know if this is true for digital servos as well? I would expect that digital servos would be more precise but I don’t really know.

The screen caps are probably from the original release. We haven’t had the time to update them. I believe the function is something that can be enabled or disabled.

You can send commands to the SSC-32 as fast as you want. But it makes absolutely no sense to send them as fast as 50hz. Doing so eliminates the inherent advantage of the SSC-32’s speed or timed moves. In other words if you are updating the destination position as fast as the servo pulses are generated you may as well just generate the required pulses directly.

Here is how it works. You send a destination position and slow it down. If you do nothing more the servo will move slowly to the desired position. However if you send an updated command while it’s moving with a faster speed it will speed up. you can do this a few times to create the acceleration. Then half way to the destination you send the same destination but at a slower speed, repeat this a few times and viola accel and decel. I guess it probably works as well as it can given the hardware limitation of the servo itself.

Digital servos hold position better than analog, but they still have the bottleneck of 50hz control pulses. Don’t take my posts the wrong way. Accel and decel is doable with standard speed serial coms from a host puter and the SSC-32, I’m just saying the result is not as dramatic as it could be if the speed of the servo control scheme were faster.

you can plot and compute acceleration, travel, and deceleration trajectories for servo movements on the PC and then send the endpoints as timed movements to the ssc-32. pretty simple. perhaps the bigger challenge might be the limits of a PC with respect to both timing precision and the extremely asychronous nature of how serial ports are implemented. Whether you use sleep() commands or timer events to control the time between sending updated movement commands to the ssc-32 the timer resolution on a PC is around 18ms. If you are waiting a second or more between sending updates this granulatity gets absorbed, the longer the delay the better, but when you are trying to do things on only a couple of hundred mS intervals it can become significant. This gets compounded with the harsh reality that just because you wrote something to the serial port at a given time there could be many tens of miliseconds before hardware begins actually transmitting the data to the ssc-32. the amount of time it takes the string to transmit in an embedded controller would be a constant that could be calculated back out but that doesn’t work quite as well on a PC.

trying to implement this using HSERVO on a BAP might be more interesting. If you can keep to integer computations it might be fast enough. You could tie the servo output line to another pin configured as an input and use that to synchronize changes to the hservo command, waiting until the current pulse completes before changing the duration of the next. could be fun to play with.

one thing that will be difficult to predict will be how the servo reacts once the pulse train starts to change. internally the servo is executing a PID type loop of some sort of course and its response will likely be impacted by whatever load is present when the input starts to change. I would suspect that too small of a change would result in a jogging response from the servo, too large of a change defeats the attempt at limiting the acceleration. With a constant load you may be able to determine experimentally what the limits are. If you start to consider how the position of the arm changes and the effect the gravity vector has on the load of each joint the calculations could get pretty dynamic pretty quickly. I think even trying to code something like this for a BAP in BASIC, regardless of whether it can do the computations fast enough, would be really difficult to write / read and god forbid have to debug. :open_mouth:

ah. I didn’t quite get earlier that the resolution wrt to accel/deaccel even when using RIOS is lower than 50hz. I understand the basic concepts of accel/deaccel using the controller though.

Saying my main point earlier another way… IF a PC could reliably send updates at 50hz then it could control accel/deaccel at the maximum resolution of a servo. (And agreed, the speed/time commands of the SSC-32 would then be unused/unnecessary, although the controller would still be required to handle the low-level pwm signal timing.)

This statement is of much value. This discussion will no doubt save me a lot of time in wasted experimentation. Thanks again.

Agreed. I had originally assumed this would be the real limiter as to resolution/precision. I was hoping to see some servo movement accel/deaccel using just PC though. Per Jim, sounds like it is possible to some extent. I know I’ve seen it on the acceleration side for 1+ second movements. Not sure I can do it on the deaccel side though.

As you’ve hinted, I think the ideal setup for this is to have a host PC that does nothing more than send macro position commands, and have an embedded servo controller that can handle the actual pulses with acceleration/deacceleration. Per discussion above, I think the maximum accel/deaccel steps per second *should *then be ~50hz excepting any of the servo latencies that Robot Dude mentioned.

That’s a good point. I didn’t quite follow everything you said, but I get the gist of it. I wonder if digital servos would have that problem? Based on what I know of how they work, it *seems *like they would not (assuming the load was within the servo’s capabilities).

…correcting myself (and maybe this is what Robot Dude was hinting at above)… it’s not technically correct to say that there could be ~50 accel/deaccel changes per second. The servo always moves at full speed. More technically correct would be to say that the requested position of the servo could be changed at ~50hz in increments according to the servo’s resolution (with the minimum change being 1us) and motor speed.

That then indirectly maps to the available servo resolution around *simulating * accel/deaccel.

Servos apparently do accelerate and deaccelerate internally depending on how close they are to setpoint. The below link has some info.

seattlerobotics.org/encoder/ … 3003C.html

Hi there,

a good start is the RIOS V1.05 user manual page 17 :
lynxmotion.com/images/data/rios02h.pdf

let’s focus on the interpolation slider and on the acceleration/deceleration graphics, the default interpolation is 33,33 Hz and the default acc/dec effect is 50% and enabled.

how it works ?

interpolation first, if the interpolation rate is too slow or if the destination position is too close to the current one…no acceleration is applicable.
just imagine going from position 900 to 1500 with a single command or going from position 900 to 901.
so it needs several commands to achieve an acc or dec and a sufficient distance to travel for the servo.

the bigger rate is the interpolation, the best accuracy and efficiency is the acc/dec.

the bigger is the travel to go, the better is the acc/dec curve and effect

of course, the bigger is the interpolation rate, the bigger is the bandwidh use

the “effect” now :

i was wanting to keep the global time constant for a travel, from effect = 0% to effect = 100%
0% is a linear transformation, so no effect.
100% is a pure sine transformation.
and 50% for example is returning half of the sine transformation (like the picture on manual page 17)

a sine transformation gives a position to go for each position on the time line.

the first step is to compute (or arbitrary define) the global time for a travel :
example 960ms

the second step is to compute the travel distance (abs(Startposition - EndPosition))
example going from position 700 to 2000 = a 1300 travel

then you have to compute how many commands to send to the SSC-32
according to the interpolation rate selected :
example 33,33hz = one command every 30ms so a 960ms travel time needs 960/30 = 32 commands to send

then you need to send to the sine transformation routine 32 times the value of the movement step in %
so call the routine with 1/32 * 1 (=0.0313) the first time
1/32 * 2 (=0.0625) then 1/32 * 3 (=0.0938) etc… to 1/3232 (um 1)
the sine transformation routine will return the corresponding sine value :
function is (here sin is working with degrees) => (1 - SIN(TheMovementStepInPcent
180 + 90))/2 * EffectInPcent + TheMovementStepInPcent*(1-EffectInPcent)

using EffectInPcent = 1 (100% effect) and TheMovementStepInPcent = 0.0313 (3.13% of the travel time (the first step)) it will return 0.00240763666390154 (0.24%)
meaning "go to 0.24% of the travel distance during the first 3.13% of the travel time
Meaning “go to position 1300*0.00240763666390+700 = 703 in 30ms”
(1300 is the travel distance, 700 is the start position)
it could be translated in “#0P703T30”(CR) …if using servo #0

then you need to send the step 2 30ms later

calling the sine transformation function with 1/32 * 2 (=0.0625)
will return :
(1 - SIN(TheMovementStepInPcent180 + 90))/2 * EffectInPcent + TheMovementStepInPcent(1-EffectInPcent)
=> (1 - SIN(0.0625180 + 90))/2 * 1 + 0.0625(1-1)
using degrees for sin eh ! gives 0.00960735979838478
Meaning “go to position 1300*0.00960735979838478+700 = 712 in 30ms”
it could be translated in “#0P712T30”(CR) …if using servo #0

etc…

then step 31 => 1/32 * 31 (=0.96875):

(1 - SIN(TheMovementStepInPcent180 + 90))/2 * EffectInPcent + TheMovementStepInPcent(1-EffectInPcent)
=> (1 - SIN(0.96875180 + 90))/2 * 1 + 0.96875(1-1)
gives 0.997592363336098
Meaning “go to position 1300*0.997592363336098+700 = 1997 in 30ms”
it could be translated in “#0P1997T30”(CR) …if using servo #0

and at last

step 32 => 1/3232 (= 1)
(1 - SIN(TheMovementStepInPcent
180 + 90))/2 * EffectInPcent + TheMovementStepInPcent*(1-EffectInPcent)
=> (1 - SIN(1180 + 90))/2 * 1 + 1(1-1)
gives 1
Meaning “go to position 1300*1+700 = 2000 in 30ms”
it could be translated in “#0P2000T30”(CR) …if using servo #0

complete !

naaa!, to be complete i must talk about shakes.
using “#0PxxxxT35” instead of “#0PxxxxT30” will help to reduce shakes.
what shakes ?
to avoid shakes you must send to the SSC-32 orders each 30ms (example at 33.33hz interpolation)
but you should use a bigger Time value for the SSC-32 “T” commands likes “T35” it will help to fill gap in data flow sent to the SSC-32 if not perfectly spaced each 30ms (COM port issue).

to finish you may add an effect auto-attenuation for small travel,
some small travel are anyway auto attenuated, but some needs to be attenuated else it goes too slow at start and end and goes too fast during the middle traject…but this last is my secret hehe

I came across that link earlier too. It’s an interesting hack, but I don’t see how it relates to rc servo acceleration/deacceleration though? Perhaps I missed something?

(This probably goes without saying… of course in the real world all motors will have a short accel/deaccel period due to laws of physics …but generally at much higher rates that what we’re discussing here.)

Your RIOS software looks quite cool and complex. I’ve also used the visual servo sequencer which I believe you wrote as well. (Are they both in Delphi?) In any case, great work and thanks.

Regarding your approach… thanks for the detailed explanation. It all makes sense. From that, I understand that you are sending absolute position/time commands at ~30hz frequency (depending on the interpolation slider and how much bandwidth is available). Can you explain why you do that instead of sending just speed change commands?

For example, assuming the end position was to 2000us and the maximum speed was to be 100us, then instead of sending interpolated position/time commands at 30hz, you could send end position/speed commands at 30hz. One of the commands while accelerating would be something like:

#0 P2000 S50

then a few updates later it might be:

#0 P2000 S90

…until it eventually reached maximum speed whereby no more updates would be sent until it was time to deaccelerate/stop. (If you wanted to move the servos according to a set time instead of speed, the same could be done with the PC calculating the necessary speeds along the curve according to desired end time.)

It seems at first glance that would save bandwidth and would also prevent having to deal with the “shakes” problem you mentioned. I believe the hard part in that approach would be knowing when to deaccelerate. Perhaps that’s why you did positional interpolation?

Again at first glance though, it seems that your approach requires a fairly reliable update rate (high bandwidth) in order to be “smooth”…and assuming reliable and consistent update rate is possible, calculating time to deaccelerate should also be relatively accurate? (Or maybe not. Maybe the timing errors would always compound in that approach where as your positional interpolation only has to deal with timing errors of the surrounding updates?)

That is not really true. I have a servo modified for continous rotation and there is a variable speed band around its zero rotation point. It is part of the servo’s deceleration control to prevent overshoot of the desired position.

Hello,

with the “changing speed while going to a fixed destination” method there’s many problems :

  • you never know where exactly the servo is during the travel
    because little errors due to SSC-32 response, COM port buffer issue,
    real speed applied on servo, etc…are cumulating.
  • so how and when to decelerate ?
  • the total travel time is hard to compute due to cumulated errors
  • anyway if you decrease the update rate, you will have shakes with this method too, changing speed at a too low rate will jump from a speed to another one with a shake…
  • when sending the last decelerate command…when will it finish ? as you don’t know exactly where the servo is.
  • with this method you will have to compute an acc/dec curve to follow anyway, but you will need to use a variable update rate, start and stop needs many speed changes, the middle travel needs only a few updates because it’s quite full speed here.

About RIOS method :

  • you always know where the servo is :
    -> so you can stop it where it is for example…just stopping to send new data or using a very short new destination close to where it is to use smooth deceleration.
    -> you can change destination at any time, you just have to compute some values
  • no need to handle a variable update rate, so using a timer is easy.
  • the shakes due to gap in data flow are very easy to fix…just use a > value for “T” command…even if using a big one like T100 for an update rate = 30ms, it will result in a smoother start and a 70ms delay added to accomplish the whole travel…it’s easy to handle, now the complete travel in my example will take 960ms + 70ms = 1030ms
  • so you control the travel time and the servo position with a good accuracy
  • you can slow down the update rate, it will just send less different speed changes…causing shakes as the method you describe if rate is too low

the best is for the end :
in RIOS, i’m not using exactly this method :open_mouth:
who cares about smooth servo moves on an L5/L6 arm ?
but everyone cares about smooth arm moves eh ?

What’s the difference ?
RIOS is not a Sequencer, it includes IK to compute trajectory,
RIOS is not going from a point to another (i mean using the “X,Y and Z” kind of moves), it goes from a point to another following a straight line trajectory.
so up to 4 servos must move in different way to perform this global arm move.
of course it can moves from a point to another without IK computation (“joints” kind of moves), anyway the global curved move will follow the sine acc/dec function.
so the acc/dec function is not applied on servos, it’s applied on the arm trajectory.
then the IK is computing all servos positions for each “semi key” steps according to the update rate selected (interpolation).
semi key steps are computed to keep the arm on a defined trajectory, using a too spaced interpolation rate won’t allow enough semi key steps resulting in curved arm moves.

the arm move is following a sine curve acc/dec but servos are moving following this function thru the IK.
so the servos in RIOS are sometimes accelerating twice or half the sine curve, sometimes acc then dec changing direction then acc and dec again during a same move in order to feed the global arm movement with a perfect sine curve acc and dec & a perfect trajectory control of the arm.

Interpolation is not only here to handle acc and dec, trajectory control was the first purpose of interpolation system.

so as the interpolation is at a fixed rate and as it goes to semi key steps position, the only method to add acc and dec support in RIOS was :

  • use the acc/dec function to compute the position to go on the arm trajectory line according to interpolation rate
  • give this semi key position to the IK to compute the servos positions
  • send these positions to servos at the interpolation rate using a fixed “T” value

it allows pause/play, stop at any time, accurate acc and dec, reduced shakes, variable interpolation, global speed control, variable acc/dec effect, variable shakes reduction effect (if you have a good COM port connection you can decrease the shakes reduction effect, using WIFI or Bluetooth dongle you can increase it) etc…

about the gap in dat flow, in RIOS acc/dec method :
30 ms after the first step was sent (#0P703T35),
sending #0P712T35 will auto adjust the speed to reach P712 :

  • if the servo is at 702 only it will go faster to reach 712 within the new 35ms allowed
  • if it was already at 703 it’ll continue to 712
    (if it was already at 703 for a too long time you will see shakes…just increase the T value)
    this system allow to really control where the servo is, while the speed is auto adjusting…as long as you use a little bigger T value like 35 for a 30ms rate because the speed can only auto adjust “going faster if late”

RIOS, SEQ, POWERPOD and LYNXTERM were built with “Borland C++ builder Professional”…
C++…a real programming language :wink: as long as you REALLY use OOP :mrgreen:

Thanks Laureatus for the explanation. Makes sense.

I really wish RC servos could provide positional feedback like the Dynamixels.

Yes, c++ is definitely a real language…a real hard language. :laughing: I’ve gotten use to garbage collectors, slow as they are, and so I try to avoid C++ when I can these days. I guessed Delphi because of your GUI widgets. I see now it’s just Borland. I should’ve known better… there’s probably not a lot of Delphi programmers doing complex robotic control software with servo I/O, movement interpolations, IK, etc. :wink:

Not sure I understand,

do you think Borland C++ is slow ?
if so you are wrong…anyway many of borland dll are made with Delphi, so it doesn’t make any sense to say it’s slower than Delphi.

The Borland IDE is exactly the same for Delphi or C++, GUI is the same too…the only difference is…the language syntax.

i didn’t get it about “garbage collectors”, do you mean it’s generating some garbage code when compiling ?
if so you are wrong again, BCB compiler is just one of the best there is, and this compiler was made with ??? Delphi ! :wink:

No, I’m not at all saying Borland C++ is slow or otherwise. I think you misunderstood. I agree that Borland’s C++ compiler is excellent.

Regarding the GUI, I just meant that the button and graphical styles reminded me of other Borland toolkits (as you noted).

Regarding garbage collectors, I just meant that I tend to use Java or .NET instead of C++ now. Both of those languages include built-in “garbage collectors” …meaning that they both automatically deallocate and clean-up objects/memory. No need for destructors, smart-pointers, etc. like in C++.

I was really just joking and actually trying to say I respect your technical approach. Sorry for the confusion. I’d never criticize another person’s dev environment …for fear they might then criticize mine. :laughing:

oh ok,

i plan to use C# which solve this problem too.

there’s no “problematic” memory allocation in my code, just some “new” and according “delete” commands,
There’s enough objects in Borland IDE with automatic memory allocation handle and cool way to assemble them into bigger objects to avoid dealing with annoying memory stuff and issue.

using “try catch” helps to always free memory after an error…
But yes i will use C# soon because it’s pretty cool,

C++ is not so hard to program, it worth the time spent to learn it 8)