# Experimenting with Walking Robots — Autonomous Leveling

Walking robots offer many unique challenges for hobbyists.  This series explores some interesting solutions to the problems I have encountered during my experimentation.

In Part 1, we explored making the robot in Figure 1 walk by using a collection of routines that could shorten or lengthen a leg, move a leg forward or backward, etc. Using such routines — instead of the typical frame-based approach — makes it possible for software to monitor sensors such as contact switches to determine if a foot is touching the ground or an accelerometer to see if the robot is level.

FIGURE 1.

A simple program in the original article demonstrated that utilizing basic movements in appropriate configurations could indeed make a robot walk. As with frame-based walking though, the robot’s movements were somewhat unsteady at best and totally unusable on uneven terrain. Experimenting with the program quickly revealed some of the problems.

## Analyzing a Step

Imagine that you want the robot of Figure 1 to step its rear left leg forward by moving the hip joint. If the robot’s left rear foot is still on the ground, then moving the hip forward will result in the body trying to move backward instead of the leg moving forward. Obviously, the leg needs to be raised before it’s moved forward.

To raise the leg, the hip should be moved forward a small amount (let’s use 10° for this example). At the same time, the knee joint should move backward by 20°. This is true because even though we want the knee to also be angled back by 10°, the hip movement is already moving the knee forward 10°. In order to compensate for this, the knee must move twice as much as the hip as shown in Figure 2. Notice that angle B is twice that of angle A.

FIGURE 2.

## Potential Problems

If the leg is not lifted high enough (the toe still touching the ground), then trying to move the hip forward can still result in the body trying to move backward as mentioned earlier. You might be thinking the easy solution is to just lift the leg higher, but there’s another potential problem.

If the robot’s weight happens to be centered slightly toward the raised leg, then the robot’s body can easily tilt toward that leg as it’s lifted. This can cause the foot to stay on the ground (which results in the same problem as a leg that is not lifted high enough).

These types of problems are far more common than you might think, because it’s easy for a programmer to assume that the robot is level and balanced when a movement is being initiated. Unfortunately, simply moving the legs to produce walking can induce very unpredictable balance problems, and since every imbalance can result in unexpected results from subsequent movements, the problems can easily escalate.

## A Solution

One solution I’m exploring is a subroutine that can level the robot’s body. I envision the routine being called repeatedly while other movements are being made to ensure that the robot can remain level even when leg movements or uneven terrain alter the robot’s center of gravity.

## A Leveling Algorithm

My first thoughts were that building such a routine should be easy. An accelerometer could provide indications of the forward/backward and left/right tilt angles. If the robot was tilted forward (for example), it could level itself by simply increasing the length of the front legs or shortening the back legs. If the robot had two tilts (for example, forward and left) then it could either straighten the front left leg or shorten all the others.

While these principles seem straightforward, there are other problems to consider. For example, a leg should never be straightened past its full length configuration (because it will start to shorten again). This means the program needs to be able to determine if a leg can be straightened by determining if one or more of the joints are already at their maximum orientation.

Once that problem is solved, we need a way to decide whether to lengthen or shorten various legs to correct for any specific tilt. I chose to always straighten legs when possible, which makes the robot maintain its maximum height for any given situation.

I actually thought an implementation of the above algorithm would easily make the robot level itself in all situations. I was wrong. Remember, this leveling routine was conceived of to make sure the robot doesn’t tip toward a leg when it’s being lifted to begin a step. Just as we could not predict how the robot would react to lifting a leg, we can’t predict how it will react when a leg is shortened (which is exactly the same thing).

In both cases, we’re shortening the leg by moving the hip forward and the knee backward. When shortening the leg before a step, we want the robot’s weight to stay on the other three legs. In our leveling routine though, we want the robot’s weight to shift toward the shortened leg.

Remember, the whole reason for shortening a leg (when leveling the robot) is to correct for a part of the robot being tilted higher. We want the short leg to lower a portion of the robot’s body to correct for that tilt. If the leg simply raises (as it does for a step), then shortening the leg does nothing to correct an unlevel tilt.

## Solving the Problem

So, what to do? The algorithm for leveling the robot seems to require that we already have a predictable level-related situation. If you place yourself in the robot’s position, though, a workable behavior should eventually become apparent. Let’s look at an example to help clarify this situation.

Assume the robot is tilting to the front and left and we need to correct it (based on the original algorithm discussed earlier) by either straightening the front left leg or by shortening the back right leg. Let’s assume the front left leg is already straight, so we have to shorten the right rear leg. Our problem occurs when the robot’s current weight distribution (perhaps from uneven terrain) causes the right rear leg to simply raise up instead of the body tilting toward that leg (to become level).

Since the robot being used has switches on the bottom of each foot (see the last article), it’s easy to determine when this situation is occurring. So, what’s the solution? The answer — while not immediately obvious — is actually pretty easy.

We can’t lengthen the left front leg and we can’t shorten the right rear leg because it simply lifts up. However, if we shorten the other two legs, the body will lower until the right rear leg does touch the ground. At that point, if the body is not level, the leveling process can continue with the other procedures in the algorithm.

## The Final Algorithm

Here’s a summary of the final algorithm. It’s assumed we know the X-Y tilts. If there is only one tilt, then both legs on the lower side (left, right, front, or back) will be lengthened if they are not already straight. If both legs can’t be straightened, the other two legs will be shortened.

If there are two tilts, then the leg on the low corner will be straightened if possible, and the opposite leg will be shortened if it’s touching the floor (as determined by the foot switch). If neither of these options are viable, then the other two legs will be shortened until another viable condition exists.

Finally, there will be limits on how short a leg can become to prevent potential damage to the robot. Over-shortening a leg is usually not a problem since the robot always gives preference to lengthening legs, but a test for this possibility is needed just to be safe.

Figure 3 shows the code for the Level sub routine I used for testing.

Level:
repeat
Level = false
gosub DetermineTilt
gosub LegPossibilities
if (TiltX>LevelX+2) and (TiltY+2<LevelY)
//Left Front is lower
if LFcanLengthen
call Lengthen(LF,0,0)
else
call Shorten(RF*RFsw,LR*LRsw,RR*RRsw)
endif
elseif (TiltX>LevelX+2) and (TiltY>LevelY+2)
//Left Rear is lower
if LRcanLengthen
call Lengthen(LR,0,0)
else
call Shorten(RF*RFsw,LF*LFsw,RR*RRsw)
endif
elseif (TiltX+2<LevelX) and (TiltY+2<LevelY)
//Right Front is lower
if RFcanLengthen
call Lengthen(RF,0,0)
else
call Shorten(LF*LFsw,LR*LRsw,RR*RRsw)
endif
elseif (TiltX+2<LevelX) and (TiltY>LevelY+2)
//Right Rear is lower
if RRcanLengthen
call Lengthen(RR,0,0)
else
call Shorten(RF*RFsw,LR*LRsw,LF*LFsw)
endif
elseif TiltX>LevelX+2 // body tilting LEFT
if LFcanLengthen and LRcanLengthen
call Lengthen(LF,LR,0)
else //if RFcanShorten and RRcanShorten
call Shorten(RF*RFsw,RR*RRsw,0)
endif
elseif TiltX+2<LevelX // body tilting right
if RFcanLengthen and RRcanLengthen
call Lengthen(RF,RR,0)
else //if LFcanShorten and LRcanShorten
call Shorten(LF*LFsw,LR*LRsw,0)
endif
elseif TiltY+2<LevelY // body tilting forward
if LFcanLengthen and RFcanLengthen
call Lengthen(LF,RF,0)
else//if LRcanShorten and RRcanShorten
call Shorten(LR*LRsw,RR*RRsw,0)
endif
elseif TiltY>LevelY+2 // body tilting backward
if LRcanLengthen and RRcanLengthen
call Lengthen(LR,RR,0)
else//if LFcanShorten and RFcanShorten
call Shorten(LF*LFsw,RF*RFsw,0)
endif
else
Level = True
endif
until Level
return

FIGURE 3.

The RobotBASIC code (a free language available from RobotBASIC.org) is easy to follow, but a few items deserve clarification. The variables LevelX and LevelY are the accelerometer readings for a level robot. The current tilt values (TiltX and TiltY) are set by the routine DetermineTilt.

Two routines Lengthen and Shorten can change the lengths of one, two, or three legs. If you only want to change one or two legs, just use a zero parameter for the unused positions.

The routine LegPossibilities establishes values for a number of variables such as LFcanShorten and RRcanLengthen. These two examples indicate if the left front leg can shorten and if the right rear leg can lengthen. The values are established by examining the current servomotor positions of the leg in question and comparing them to the limit values.

This routine also establishes a True or False value for the variables RFsw, LFsw, RRsw, and LFsw. These variables indicate the conditions of the four foot switches. Since the values of these variables are effectively 0 or 1 (1 indicates the foot is touching the ground), calls to the Shorten routine always multiply the leg to be shortened by its corresponding switch condition. This causes the parameter to become zero when the foot is not touching the ground and thus prevents that leg from being shortened (as dictated by the final algorithm described previously).

## Testing

The subroutine does level the robot when called in all situations that were tested. Figures 4 and 5 show the robot obtaining a level condition in two situations involving uneven terrain. Note, adding an offset value to the LevelX and LevelY parameters also allows the robot to autonomously orient itself in various desirable positions such as leaning forward or leaning right. Such orientations can be using when developing a walking routine.

FIGURE 4.

FIGURE 5.

## Conclusion

Hopefully, you’re motivated enough by my work with walking robots to experiment some yourself. If you enjoy developing algorithms for hobby robots, walking robots can certainly keep you busy. I think my next project will be moving some of what I have learned to a two-legged humanoid. SV