Smooth Servo Motion For Lifelike Animatronics

Building an animatronic robot is one thing, but animating it in a lifelike fashion is a completely different challenge. Hobby servos are cheap and popular for animatronics, but just letting it move at max speed isn’t particularly lifelike. In the video after the break, [James Bruton] demonstrates how to achieve natural motion with a simple animatronic head and a few extra lines of code.

Very little natural body movement happens at a constant speed, it’s always accelerating or decelerating. When we move our heads to look at something around us, our neck muscles accelerate our head sharply in the chosen direction and then slows down gradually as it reaches its endpoint. To do this in Arduino/C code, a new intermediate position for the servo is specified for each main loop until it reaches the final position. The intermediate value is the sum of 95% of the current position, and 5% of the target position. This gives the effect of the natural motion described above. The ratios can be changed to suit the desired speed.

The delay function is usually one of the first timing mechanisms that new Arduino programmers learn about, but it’s not suited for this application, especially when you’re controlling multiple servos simultaneously. Instead, the millis function is used to keep track of the system clock in the main loop, which fires the position update commands at the specified intervals. Adafruit wrote an excellent tutorial on this method of multitasking, which [James] based his code on. Of course, this should be old news to anyone who has been doing embedded programming for a while, but it’s an excellent introduction for newcomers.

Like most of [James]’s projects, all the code and CAD files are open source and available on GitHub. His projects make regular appearances here on Hackaday, like his mono-wheel balancing robot and mechanically multiplexed flip-dot display.

10 thoughts on “Smooth Servo Motion For Lifelike Animatronics

    1. Well, the exact ratios aren’t critical. So you could just do a simple approximation, using integer multiplies and shifts. For example, using 15/16 of the current position and 1/16 of the new position would be pretty close to the values he mentioned. This would be something like:

      newPos = (15 * currPos + newPos) >> 4;

      I mean, not nothing, but all integer and likely somewhat better than floating point on arduino.

  1. It might be worth reading up on smoothstep, linear interpolation (lerp) and spherical linear interpolation (slerp) – You’ll find that they get used a lot for motion in video game engines like Unity.

  2. At 9:51 he shows a little snippet where he does:

    if(currentMillis-previousStepMillis>500) {
    previousStepMillis=currentMillis;

    }

    In practice it rarely matters, but better way is to add your step to previousStepMillis, so that you don’t have drift. With code like above, if there is 505 milliseconds between two evaluations of your code, all steps will be 5ms later. How to get rid of that drift:

    if(currentMillis-previousStepMillis>500) {
    previousStepMillis+=500;

    }

  3. FYI that exact same algorithm — x% * NewPosition + (1-x%) *OldPosition — is used extensively in charting and computation for financial calculations. It produces a simple low-pass digital filter that smooths the jittery motion of a stock into a smoother, less-noisy result. See e.g. https://www.investopedia.com/terms/e/ema.asp

    A “simple” moving average just averages the last N data points. The EMA weights the recent points more heavily, making the result respond faster to market movement.

  4. The smoothed motion looks a lot less like servos, but instead of looking organic, it looks like low pressure pneumatics, at least to me. The exponential decay at the end of the stroke is really obvious, and that’s not how flesh and blood creatures move.

    Now I’m curious about what motion profiles for humans and animals would actually look like. Do we have trapezoidal velocity curves, or rounded trapezoids, or something else?

Leave a Reply to ihdpCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.