I saw Sony's new robotic dog, Aibo, on teevee and it looked pretty cool.
I'd never messed around with electric motors or any robotics stuff
before, but I could tell that there was a lot of engineering in that
thing. It'd be fun to play around with one, but if I paid $2500 for
it I might be a little reluctant to tear it down the first day I got
it. I thought it'd be more fun to try to build a dogbot instead.
ADDENDUM: Sony has used the DMCA to shut down someone's web site because
in part, it provided "the means to circumvent the copy protection protocol
of Sony's AIBO(tm) Memory Stick(tm) to allow access to Sony AIBO-ware
software". Because Sony does not want me to get fair use of their
products, I won't buy them.
I needed some sort of starting point to begin thinking about
a design, so I bought one servo - a standard part available
from any hobby shop that I thought could maybe move a leg like
one of Aibo's back and forth. I turned the servo over and over in
my hands and contemplated it, and it helped to loosen my brain.
The servo cost $11.95. It has three wires coming off it and
four mounting holes. It weighs 1.5 ounces. With 12 of them,
I was going to have over a pound of servos in the walker.
It's torque rating was 40 oz/in. I understood this to mean
that it was capable of lifting 40 ounces at the end of a lever
one inch long. Interesting - I've messed with engines for
two decades and never really understood the physics of torque
until I got this little servo and started trying to puzzle out
how to figure out ahead of time whether it could lift a robot
body or not. I twisted the lever back and forth and visualized
the push/pull rod that it might operate and thought about the
force that it would exert at different points in its rotation.
When a servo is stationary, it must consume power proportional
to the amount of torque that it's being asked to resist. This
means that when a servo is positioned such that its arm is
perpendicular to its linkage, it will consume more battery power
than when it is positioned with its arm parallel to or nearly
inline with the linkage. Might be able to reduce battery discharge
by taking that into account.
I decided on a 4-legged walker with 3 servos per leg.
This seemed pretty ambitious to me, especially
for a first robot, but I was feelin' my oats and wanted a walking
platform that I would be unlikely to outgrow anytime soon. I
knew that I could use a Palm Pilot as the controller, which I
figured would have enough portable computing power to handle
most servo controller tasks I could throw at it with room to
spare for sensor polling and room mapping.
I wanted to spend as little time on mechanical fabrication and
electronics design as possible and spend my time on the software instead.
For the mechanics, I decided to fabricate the walker out of a sheet
of Lucite, epoxy, some nuts and bolts, and the servos. For the
brains, I decided on a pair of Scott Edwards servo controllers
(http://www.seetron.com), a BASIC Stamp to convert some inputs
into RS-232, and my Palm IIIe to talk to the servos and inputs.
In terms of a robot brain, a Palm IIIe is a 16Mhz 68000 with 2 megs
of RAM, a serial port, a 160x160 LCD graphics display, and perhaps
most importantly, no shortage of compilers and development tools
available for it.
The next step was to design the legs and body. I prototyped some
legs by simply cutting them out of cardboard and loosely bolting
them together so I could see how they moved, how the clearances
worked out, and what sort of range of motion I could expect. I
was disappointed when, after staring at some cardboard legs for
a few hours, I determined that that a little 4-legged walker using
standard servos that could also climb stairs was clearly beyond
my engineering capabilities. Maybe next robot. I was elated,
however, to realize that it would be easy to mount the legs to
a body in such a way that the body might permit experimentation
with both crab and dog walking configurations without having to
detach and reattach the legs.
The body was very simple: two rectangles of Lucite separated by
four lengths of threaded rod using washers and nuts. This made for
a strong body while also permitting the distance between the two
body plates to be adjustable. This turned out to be an important
advantage later on when I added four small Lucite squares as hip
bearings and needed to increase the body plate spacing by one
quarter inch. I was also able to easily add a smaller Lucite sheet
on the threaded rods between the body panels to mount the servo
controllers and sensor board. The electronics were protected
under the top body panel and everything was visible through the
clear Lucite for a pretty cool-looking robot. Total design,
fabrication, and assembly time until the bot powered up and stood
up on its own was two weeks. Alpha Geek Power! Feels good!
Gimmee more!
Then things slowed down - a lot - as I started to think about ways
to control the servos. I knew that the software to control a
12-servo 4-legged robot would probably not be trivial, but I hadn't
realized just how open-ended a problem it could be. I spent several
days just thinking about a few problems involving balance, determining
the positions of foot placement, figuring out which foot could be
lifted without falling over, whether a foot was even touching the
floor, how to go about moving a limb while it's in contact with
the floor... and I started to feel pretty stupid. It began to dawn
on me how graduate students can spend years on this stuff.
All I wanted was to see my robot walk around the room.
I decided to start with two basic software components: A simple
language that would let me predefine coordinated movements of
multiple servos, and something that could read those definitions,
slice them up into things to be done within a little frame of time,
and send them out to the servos.
To make the static movement description language a little nicer
to work with, I decided to have only one spot where I define the
servo's physical movement ranges and then to use a percentage of
range value to describe a servo position. This had several
advantages:
1. Retracting a servo to 0% would be the same regardless of whether
the servo was on the left or right side or mounted horizontally or
vertically. Moving a servo to 50% would always move it to the
center of its physical range, freeing me from having to remember
or look up the range values for a particular servo as I developed
the preprogrammed movement primitives.
2. Predefined movements would always generate physical servo position
values within their ranges.
3. Minor mechanical adjustments that changed a servo's range or a
need to tweak ranges to compensate for things like gradually turning
while walking forward could be accounted for in one spot without
having to change hundreds of preprogrammed movement values.
* * * * PHYSICAL SERVO RANGE LIMITS * * * *
Forward Back Up Down In Out
Left Front
0 hip 180 20
1 thigh 60 180
2 knee 40 190
Right Front
3 hip 70 230
4 thigh 220 80
5 knee 220 70
Left Rear
8 hip 220 55
9 thigh 60 180
10 knee 40 190
Right Rear
11 hip 70 240
12 thigh 220 80
13 knee 220 70
Corresponding entry in the ROBOTS.SEQ file:
ServoRanges {
servo 0 extend 20 retract 180
servo 1 extend 180 retract 40
servo 2 extend 190 retract 40
servo 3 extend 230 retract 70
servo 4 extend 80 retract 220
servo 5 extend 70 retract 220
servo 8 extend 55 retract 220
servo 9 extend 180 retract 40
servo 10 extend 190 retract 40
servo 11 extend 240 retract 70
servo 12 extend 80 retract 220
servo 13 extend 70 retract 220
}
The next step was to come up with the rest of the static movement
description language and write a parser for it. This was the result -
this sequence defines two movements, one called PrepareToWalk and
one called ForwardWalk. ForwardWalk is an endless cycle. In the
definition language, 255% causes a servo to remain at its last
commanded position for the specified number of ticks.
Primitive PreForwardWalk {
servo 0 to 255% in 16 to 45% in 16 to 255% in 32 to 35% in 8
servo 3 to 255% in 4 to 5% in 8 to 255% in 4 to 20% in 16 to 255% in 32 to 5% in 8
servo 4 to 0% in 8 to 100% in 8 to 255% in 48
servo 5 to 0% in 8 to 50% in 8 to 255% in 48
servo 8 to 255% in 16 to 45% in 16 to 255% in 4 to 65% in 8 to 255% in 20 to 50% in 8
servo 9 to 255% in 16 to 255% in 16 to 0% in 8 to 100% in 8 to 255% in 16
servo 10 to 255% in 16 to 255% in 16 to 0% in 8 to 50% in 8 to 255% in 16
servo 11 to 255% in 16 to 45% in 16 to 255% in 20 to 35% in 8 to 255% in 4 to 20% in 8
servo 12 to 255% in 48 to 0% in 8 to 100% in 8
servo 13 to 255% in 48 to 0% in 8 to 50% in 8
}
; Forward walking is split into two symmetrical 48-tick halves
; This allows us to stop partway through at a known state if need be
Primitive ForwardWalk1 {
; RF hip from 5% to 35% in 1st half
servo 3 to 35% in 48
servo 4 to 255% in 48
servo 5 to 10% in 16 to 255% in 32
; RR hip from 20% to 50% in 1st half
servo 11 to 50% in 48
servo 12 to 255% in 48
servo 13 to 10% in 16 to 255% in 32
; Left side 1st half is same as Right side 2nd half
servo 0 to 60% in 40 to 5% in 8
servo 1 to 255% in 40 to 0% in 4 to 100% in 4
servo 2 to 90% in 16 to 255% in 32
servo 8 to 60% in 16 to 5% in 8 to 20% in 24
servo 9 to 255% in 16 to 0% in 4 to 100% in 4 to 255% in 24
servo 10 to 90% in 16 to 255% in 32
}
Primitive ForwardWalk2 {
; RF hip from 35% to 60, then back to 5% in 2nd half
servo 3 to 60% in 40 to 5% in 8
servo 4 to 255% in 40 to 0% in 4 to 100% in 4
servo 5 to 90% in 16 to 255% in 32
; RR hip from 50% to 60%, forward to 5%, to 20% in 2nd half
servo 11 to 60% in 16 to 5% in 8 to 20% in 24
servo 12 to 255% in 16 to 0% in 4 to 100% in 4 to 255% in 24
servo 13 to 90% in 16 to 255% in 32
; Left side 2nd half same as Right side 1st half
servo 0 to 35% in 48
servo 1 to 255% in 48
servo 2 to 10% in 16 to 255% in 32
servo 8 to 50% in 48
servo 9 to 255% in 48
servo 10 to 10% in 16 to 255% in 32
}
Movement PrepareToWalk {
PreForwardWalk in 72
}
Movement ForwardWalk {
ForwardWalk1 in 48
ForwardWalk2 in 48
repeat
}
After about 150 hours of mechanical and software development over a one
month period, the robot finally executed the above sequences and walked
across the room, trailing its power and RS-232 tether behind it.
Play-by-play...
2/21 Got inspired by Sony's Aibo and Lynxmotion web sites
2/22 Bought one servo at a local hobby shop to look at $12
2/23 Bought sheet of lucite and bolts for building body $40
2/24 Designed legs - prototyped with cardboard
Standard servo hole slots .8" wide 1.6" long
Ordered 2 servo controllers and BASIC Stamp 1 from
http://www.seetron.com/ $127
2/25 Cut out acrylic parts for legs - dremel with cutter bit
2/26 Glued hip rotation pivot point flanges to top of hips
Worked on body design - try to support both crab and dog
configurations without requiring leg reattachment.
2/27 Glued hip rotation servo lower mount flanges to bottom of hips
Ordered 12 servos from http://www.towerhobbies.com $126.96
Expect to receive order FROM 03/06/00 TO 03/08/00
2/28 Bought 24 little bolts for attaching servos to legs $7.50 bah
2/29 Drilled servo mounting holes
Bought some linkage hardware $17.27
3/1 Assembled Stamp 1 & a wall wart power supply for it
Built Stamp 1 programming cable & PC-to-SSC RS-232 cable
Loaded up some test programs to verify that it worked
Received email that servos have shipped
3/2 Built cable for PC<->Stamp testing; serout 1K ohm, serin 22K ohm
3/3 7.2v wall wart power supply for tethered servo power
Received and tested servos - 1 bad, will need to return
Additional hardware to finish linkages and separate body panels $8
Assembled and tested first leg - hip and knee joints
3/4 Finished assembling legs
Drilled upper pivot holes in hips
Draft body design 8"x12" leg pivot points at 6" and 9"
Cut out 2 8"x12" body panels
3/5 Assemble body
Redid hip joints with acrylic "bearings" for smoother rotation
4 1" squares with 1/8" center holes
Added center board between body panels and mounted electronics
3/6 Center hip servos and drop into sockets
Make nice-looking power wiring harnesses
7.2v wall wart way too weak for servos (duh) use 5v 250w PC supply
Bot did its first one-armed pushup!
3/17 Reversed thigh servos and simplified linkages
First cut at servo driver software - simultaneous servo control
3/18 Convert waypoint position values to servo range percentages
Designed feet and floor touch switches
Cut out front leg clearance notches
3/19 Designed static sequence definition format
Wrote function to compute center of gravity relative to leg tripods
3/20 Wrote code to parse static sequence definition file ROBOT.SEQ
3/21 Experimenting with walking sequences and debugging code
3/22 Split forward walk into two symmetrical halves
3/23 Convert delta computations to use physical values for smoother movement
3/24 PreForwardWalk sequence Wahoo! It's ALIIIIVEEEEE!!!