Skip to content

Gestures

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

Gestures

Introduction

A gesture is a whole canned performance: leg movement, a face on the LED matrix, and a sound, choreographed together and played by one call.

Gestures::play(Gesture::Victory);

Gestures is the smallest facade in OttoFlow -- one function -- but it is the fastest way to make a robot feel alive. Where Legs gives you a step and Mouth gives you a face, a gesture gives you a reaction.

The choreography itself lives in OttoDIYLib; OttoFlow gives it named constants and the same guard rules as every other movement call.

Playing a gesture

Gestures::play(Gesture::Happy);
Gestures::play(Gesture::Love);
Gestures::play(Gesture::Sleeping);

There is one function and one argument. Gestures take no period, no amplitude, and no repeat count -- each is a fixed performance, and that is the point: you are choosing a reaction, not composing one.

To build your own, combine the layers directly:

Mouth::show(Icon::Heart);
Voice::play(Sound::Cuddly);
Legs::swing(2, 900, 25);

The thirteen

Happy, SuperHappy, Sad, Sleeping, Fart, Confused, Love, Angry, Fretful, Magic, Wave, Victory, Fail.

The Icon, Sound and Gesture Reference describes what each one actually does on the robot, with durations. Read it before picking one -- several are longer than you would guess, and two do not move at all.

Blocking and self-resetting

Every gesture blocks for roughly 0.5 to 3 seconds. Nothing else in your loop() runs meanwhile: no sensor is read, no Bluetooth command is handled. Gesture::Wave and Gesture::Fail are the long ones, at about four seconds each.

Every gesture also self-resets. It returns the legs to the centre pose and leaves a happy face on the matrix, whatever it did in between. That is convenient -- you never have to tidy up after one -- but it means a gesture will overwrite a face you just set:

Mouth::show(Icon::Heart);
Gestures::play(Gesture::Happy);   // ends showing its own face, not the heart
Mouth::show(Icon::Heart);         // show it again afterwards

Three that surprise people

  • Wave does not wave. It scrolls a wave pattern across the LED mouth -- a screen animation, no limb involved. The physical greeting is Arms::waveRight().
  • Magic does not move either. Like Wave, it is mouth and sound only.
  • Fail goes limp on purpose. Partway through, it detaches the servos with a long low groan, so the robot flops before recovering. On a table, that flop can topple it -- expected behaviour, not a bug.

Gestures and disabled movement

Gestures move the legs, so they obey the same guard as everything else: while Legs::disable() or Motion::disable() is in force, a gesture performs nothing at all rather than the face and sound without the movement.

That is deliberate. A half-played gesture on the bench would look like a bug, and a gesture that fired its sound while the body stayed still would teach you the wrong thing about your robot.

Magic and Wave are the exceptions -- having no body movement, they play normally while movement is disabled.

Giving a sketch personality

Gestures are at their best as reactions to a sensor:

void loop() {
  if (Eyes::closerThanCm(10)) Gestures::play(Gesture::Confused);
  if (Touch::wasTapped())     Gestures::play(Gesture::Happy);
  if (LightSensor::isDarkerThanPercent(15)) Gestures::play(Gesture::Sleeping);
}

Two habits keep this from going wrong:

  • Trigger on an edge, not a level. Touch::wasTapped() fires once; Touch::isTouched() would restart the gesture on every loop for as long as the finger rests there.
  • Remember the blocking time. A three-second gesture is three seconds of not looking. Put the slow ones behind deliberate triggers, not behind a continuously true condition.

Going lower: playGesture

LegServos::playGesture(Gesture::Victory);

The module call is what the facade forwards to, one to one. Use it in generic code that already works in LegServos terms; use Gestures::play() in sketches, where the shorter name reads better.

Neither layer lets you alter a gesture's choreography -- that lives inside OttoDIYLib. To change one, build your own from Mouth, Voice and Legs, or reach the raw driver through The Driver.

Clone this wiki locally