-
Notifications
You must be signed in to change notification settings - Fork 0
Movement
- Introduction
- Walking and turning
- Small moves
- Dance moves
- Gestures
- Poses and single servos
- Enabling and disabling movement
- Understanding steps, period and amplitude
- Movement blocks
- Going lower: the LegServos module
Legs drives the four leg and foot servos: two hips, two feet. It is a facade over the LegServos module, and its whole purpose is that a sketch never contains a bare 1 or -1 for a direction.
Legs::walkForward(2);
Legs::turnLeft(1);
Legs::home();Movement is enabled after OttoFlow::start(). To keep the robot still while you work on other hardware, see Bench Testing.
Warning Put Otto on the floor, not on a table, before enabling movement. A walking Otto reaches the edge sooner than you expect.
Legs::walkForward(2); // two steps
Legs::walkBackward(2);
Legs::turnLeft(3);
Legs::turnRight(3);Each takes an optional period in milliseconds -- the duration of one movement cycle. Higher is slower:
Legs::walkForward(4, 700); // brisk
Legs::walkForward(4, 1300); // carefulDefaults are 1000 ms for walking and 2000 ms for turning. Roughly 600 to 1400 ms is the useful walking range; below that the servos cannot keep up and Otto shuffles in place.
home() returns all four servos to the rest position. It is worth calling before and after a sequence, so every behaviour starts from the same stance:
Legs::home();
Legs::walkForward(3);
Legs::home();Legs::bendLeft(); // steps = 1, periodMs = 1400
Legs::bendRight(2, 1200);
Legs::shakeLeftLeg(); // steps = 1, periodMs = 2000
Legs::shakeRightLeg(2);
Legs::jump(); // steps = 1, periodMs = 2000jump() is more of a hop, and it is demanding: it needs fresh batteries and a surface with some grip.
Each of these repeats for a number of cycles and takes an amplitude in degrees -- how large the movement is.
Legs::moonwalkLeft(3);
Legs::moonwalkRight(3, 900, 25);
Legs::crusaitoLeft(2);
Legs::crusaitoRight(2);
Legs::swing(2);
Legs::tiptoeSwing(2);
Legs::upDown(4);
Legs::jitter(2);
Legs::ascendingTurn(2);
Legs::flapForward(2);
Legs::flapBackward(2);| Move | Signature | What it looks like |
|---|---|---|
upDown |
(cycles = 1, periodMs = 1000, amplitude = 20) |
Bobbing up and down on both feet |
swing |
(cycles = 1, periodMs = 1000, amplitude = 20) |
Rocking side to side |
tiptoeSwing |
(cycles = 1, periodMs = 900, amplitude = 20) |
Rocking while up on the toes |
jitter |
(cycles = 1, periodMs = 500, amplitude = 20) |
A fast nervous shudder |
ascendingTurn |
(cycles = 1, periodMs = 900, amplitude = 50) |
Turning while rising |
moonwalkLeft / moonwalkRight
|
(cycles = 1, periodMs = 900, amplitude = 25) |
Sliding sideways |
crusaitoLeft / crusaitoRight
|
(cycles = 1, periodMs = 900, amplitude = 20) |
A leaning sway |
flapForward / flapBackward
|
(cycles = 1, periodMs = 1000, amplitude = 20) |
Feet flapping like fins |
A short routine:
Legs::home();
Legs::upDown(2, 800, 25);
Legs::moonwalkLeft(3);
Legs::moonwalkRight(3);
Legs::jitter(2, 400, 30);
Legs::home();A gesture is a whole performance: movement, a face on the matrix, and a sound, in one call.
Gestures::play(Gesture::Victory);
Gestures::play(Gesture::Love);
Gestures::play(Gesture::Sleeping);Thirteen are built in -- see the full list. Because gestures move the legs, they respect Legs::disable(): a disabled robot performs nothing rather than half of the gesture.
Gestures are the fastest way to give a sketch personality:
if (Eyes::closerThanCm(10)) Gestures::play(Gesture::Confused);
if (Touch::wasTapped()) Gestures::play(Gesture::Happy);For calibration, custom animations, or a stance of your own, address the servos directly. Angles run 0 to 180 degrees, with 90 as the centre:
Legs::positionLegLeftDegrees(90);
Legs::positionLegRightDegrees(90);
Legs::positionFootLeftDegrees(90);
Legs::positionFootRightDegrees(90);These jump to the angle immediately. To move all four together, smoothly interpolated like a keyframe, use:
Legs::positionAllDegrees(90, 90, 90, 90); // 200 ms by default
Legs::positionAllDegrees(70, 110, 90, 90, 800); // a slow leanArguments are, in order: left leg, right leg, left foot, right foot, and the duration in milliseconds.
Legs::disable(); // detach the four leg servos
Legs::enable();
bool moving = Legs::isEnabled();While disabled, the servos are detached -- no jitter, no current draw -- and every movement call is a silent no-op. Your sketch keeps running normally; the robot simply stays still.
Motion is the switch for all servos, legs and arms together. It is the single call for "the robot must not move":
Motion::disable(); // legs and arms
Motion::enable(); // re-attaches arms only if this build has them
bool any = Motion::isEnabled();Use Motion for safety and bench work; use Legs::disable() or Arms::relax() when you deliberately want one group off.
| Parameter | Unit | Meaning |
|---|---|---|
steps / cycles
|
count, fractional allowed | How many times the movement repeats. 0.5 is half a cycle |
periodMs |
milliseconds | Duration of one cycle. Higher is slower |
amplitude |
degrees | How large the movement is |
The total duration of a call is roughly steps * periodMs. Legs::walkForward(4, 1000) takes about four seconds -- during which your sketch does nothing else.
Every movement call in this version returns only when the motion has finished. While walking, Otto cannot read a sensor or respond to Bluetooth.
Design around it by moving in short bursts and checking sensors in between:
void loop() {
if (Eyes::closerThanCm(20)) {
Legs::walkBackward(1); // one step, then look again
Legs::turnLeft(1);
} else {
Legs::walkForward(1);
}
}A non-blocking engine -- startWalkingForward(), isMoving(), stop() -- is the headline item on the Roadmap. The current names were chosen so it can be added without breaking any existing sketch.
The LegServos module is the same functionality with hardware-truth names and explicit direction arguments, where 1 is forward or left and -1 is backward or right:
LegServos::walk(2, 1000, 1);
LegServos::moonwalk(3, 900, 25, -1);Prefer the facade in sketches. Reach for the module when you are writing a generic routine that computes its own direction:
int dir = obstacleOnLeft ? -1 : 1;
LegServos::turn(1, 2000, dir);Calibration lives here too -- see Calibration.
OttoFlow is licensed under GPL-3.0 and wraps OttoDIYLib. Buy the kits at ottodiy.com.
Prologue
Getting Started
The Basics
Digging Deeper
- Bench Testing
- Serial Console
- Calibration
- Bluetooth and the Otto App
- Modules
- The Driver
- Extending OttoFlow
Reference