Skip to content
Ahmed Dabak edited this page Jul 25, 2026 · 1 revision

Motion

Introduction

Motion is the master switch for every servo Otto has -- the four leg and foot servos and, on a Humanoid build, the two arm servos.

Motion::disable();   // detach everything
Motion::enable();    // drive everything again
bool any = Motion::isEnabled();

It exists so that "the robot must not move" is a single call rather than a checklist you can get half right. Forgetting one group is exactly how a robot walks off a table while you are testing something else.

The one call for "do not move"

The two lines that make a half-built robot safe to hold:

void setup() {
  OttoFlow::start();
  Motion::disable();   // detach every servo: legs and arms
  Voice::mute();       // and no sounds
}

Your real loop() can now run untouched. See Bench Testing for the full bring-up workflow this belongs to.

Warning Motion::disable() in setup() is undone the moment you type legs on or motion on in the Serial Console. That is how you opt in to movement for a single test -- but the robot can move from that point on.

What disabled actually means

Disabling detaches the servos. Three consequences follow, and all three are useful:

  • The servo stops being driven, so it draws almost no current and makes no noise. A detached robot is quiet enough to sit next to and cool enough to hold.
  • The joints go limp. You can pose a leg by hand to check clearances or judge a horn angle -- impossible while a servo is holding position.
  • Every movement call becomes a silent no-op. Not an error, not a warning, not an action queued for later. Legs::walkForward(2) simply returns.

That last point is the one that shapes sketches: the same source runs on the bench and on the floor, with no #ifdefs and no branches. It is a deliberate framework-wide rule -- see Architecture.

Detaching also means the servos stop holding. A robot standing under its own power will sag or topple when you disable movement, so disable it lying down or in your hand, not standing on a shelf.

Motion, Legs and Arms

Three switches, at two levels of breadth:

Call Affects
Motion::disable() / enable() All servos, legs and arms
Legs::disable() / enable() The four leg and foot servos
Arms::relax() / hold() The two arm servos

Use Motion for safety and bench work. Use the narrower two when you deliberately want one group live and the other parked -- testing an arm wave while the legs stay still, for instance.

The vocabulary differs on purpose: legs enable, arms relax and hold. Arms are optional hardware that may not exist on a given build, and "relax" describes what actually happens to a limb you can then move by hand.

isEnabled reports any group, not all

bool any = Motion::isEnabled();

This returns true when either group is active -- the legs or the arms. It answers "can this robot move at all right now", which is the safety question, not "is everything attached".

So after Legs::disable() on a Humanoid build, Motion::isEnabled() is still true, because the arms are still driven. When you need to know about one group specifically, ask it directly:

if (Legs::isEnabled())  { /* the legs are attached */ }
if (Arms::isActive())   { /* the arms are attached */ }

Enabling again

Motion::enable();

This re-attaches the legs always, and the arms only if this build has them -- that is, only when arms.enabled is set in the configuration. On a classic biped it attaches the legs and does nothing else, with no error.

Servos jump to their last commanded position the instant they are attached, which can be a sharp movement if you posed the robot by hand while it was limp. Centring first makes the transition predictable:

Motion::enable();
Legs::center();
Arms::center();

From the serial console

> motion on
> motion off
> legs on
> arms off

motion on|off is the console's equivalent of these calls, and legs and arms are the per-group switches. Nothing in the console moves a servo until you have enabled its group -- see Serial Console.

A one-call bench mode -- OttoFlow::benchMode() -- bundling this with muted sound and a clear indicator on the matrix is on the Roadmap.

Clone this wiki locally