| Simulating The Robot
While I was building the mechanical aspects of the robot I though about how I would write the software. I've only been coding for microcontrollers for a few years but I've already learned that debugging the code is tricky. If you don't have a proper in-circuit debugger (ICD) or a reliable method to get information out to where you can see it (maybe an LCD display) it's hard to know what's going on. My Pickit2 can do limited ICD but it's quirky and sometimes the dsPIC33 gets into a weird mode where it's hard to program so I reserve this for the knottiest of problems.
I decided that since I'm new to inverse kinematics and walking gaits that I ought to write a simple simulator so I could learn in a friendly environment. For Windows, I code in VB6 classic. Sucks to be obsolete and deprecated but it still works. The result is an untidy but handy tool that allows me to see a stick representation of the robot and that allows me to make it walk.
The model doesn't yet account for the centre of gravity (CG). The two legged gait for the quadruped is therefore impractical unless the movement is very fast, perhaps short steps. Thus the momentum of the robot might keep it from tipping much before the legs are back on the ground. Alternately one might be able to add a gyro and use body tilting to aid balance during movement. Something to work on once the robot is built. Animals manage this type of movement so something should be possible.
I purposely haven't looked deeply at how other robots create their gaits in an attempt to keep my options open. There's hardly a point to replicating what others have done as many have already done it extraordinarily well. I'm hoping that I can contribute some new ideas.
My approach is to use forces and to let walking occur as an emergent property. Emergent means that something has not specifically been programmed but that it occurs as a natural consequence of simpler rules.
In my design I can "push" the robot in different directions. Not physically but programmatically. If I push the robot it moves in the direction I push. If I push harder it moves a bit faster. The legs are on the ground of course so movement cannot occur indefinitely. Eventually the legs will reach the limit of their travel. In my design I have the legs calculate a resistance as they approach their limits. This resistance has a component that counters the "push" I've given the robot. Eventually the resistance from the legs balances my "push" and the robot stops but leaning in the direction I'm pushing.
Each leg has a "rest" position/orientation that it would like to be in. Any deviation from this position produces a resistance vector. The resistance vector shows the direction the leg would like to move and how badly.
Now to walk. If I "lift" a leg it is now free to move and it's urge is to move back to its rest position where the resistance it feels is a minimum. The leg determines a trajectory that will clear the ground by a desired amount and that will return it to its rest position. Without the resistance of the lifted leg, the robot is now able to lean a bit further in the direction of the "push". Once the first leg touches down on the ground we can lift another leg and repeat. As we cycle through the legs one by one or in groups, the robot walks.
As each leg is lifted it returns to its rest position. But this does not necessarily produce the best gait. If a robot is moving in a direction it would be useful if the leg could "learn" what is expected of it and move to a location ahead of its rest position so that it could spend more time on the ground as the robot moves. I call this anticipation since the leg anticipates what it will be expected to do.
Ideally the leg should learn to anticipate by itself but for the moment the brain tells it by how much to anticipate. A cheat but perhaps something that can be remedied in the future as I get a better handle on the best values of anticipation.
I had an opportunity to work with proportional integral (PI) controllers in a previous project. PI or PID (proportional integral differential) controllers are used to control a myriad of devices such as heaters trying to reach and maintain a constant temperature or servos trying to reach and hold a specific position.
While the legs are on the ground their behaviour is controlled by the robot. When the legs lift off the ground they determine their own path to the preferred position. I could have hard coded this but I wanted to play with PI controllers and also this seems to make the leg's behaviour a bit more "organic".
In my PI controller I use the leg position and target position as inputs. The output is the acceleration in each of the X, Y and Z axis. By selecting acceleration, I can specify maximum acceleration and velocity values for the leg. I'm hoping that this will be helpful in not destroying my cheap servos by setting modest limits. If all is well I can up the limits.
PI controllers are a bit difficult to work with in that they need to be tuned. Each controller has three gain values (scalar multipliers) that need to be determined.
Gain1 is the proportional gain. Large values will increase the speed at which the leg approaches the target but at excessive values can cause the system to oscillate.
Gain2 is the integral gain. It damps the system and helps the leg converge to the target when it's close.
AWU Gain is the anti-windup gain. The PI controller may specify values of acceleration that the system cannot match. When the movement result is less that expected, the PI controller will continue to increase and increase the specified acceleration not realizing that the system simply cannot comply. This is called windup. A PI controller therefore contains an AWU gain value that reduces the amount of windup that occurs when the specified acceleration cannot be achieved.
More on all this later.