[From Bruce Abbott (2014.02.27.1840 EST)]
A week or so ago I wrote about the “Little Man” demos that Bill Powers created, known and “Arm1” and “Arm2.” These show a perspective view of a stick figure (alias “Little Man”) whose single arm can swing at the shoulder in two rotational directions, yaw (left-right) and pitch (un-down) and at the elbow in one rotational direction, pitch. These three degrees of freedom allow Little Man to track a target with his finger tip as the user moves the target up and down, left and right, and in and out (i.e., closer to or farther from Little Man’s body).
The original version, Little Man 1, accomplished this via a two-level hierarchy of control systems. The three bottom-level systems controlled the elevation, azimuth (horizontal position), and reach of the finger tip by setting references for the three joint angles. The top level used “visual” information about the relative gaze-angles from eye to target and from eye to finger tip, based on the differences between eye position and the positions of target and finger tip, to determine the error between target position and finger-tip position in 3D space.
The lower-level control systems would be expected to send their outputs to a set of bottom-level systems that move the joints by contracting the relevant muscles, but these were not modeled in Little Man 1; instead, the outputs of the first-level systems (normally serving as the references for the muscle-systems) were simply connected to the inputs of the same first-level systems – in other words, the joint angles magically changed to match the reference values. The original Little Man 1 was written in C as a DOS program; later Bill converted it to a Delphi (Turbo Pascal) version that runs on the Windows operating system.
At some point Bill added a bottom, muscle-based level of control, resulting in Little Man 2. This also was written in C for DOS. Bill stated that at some point he hoped to create a version for Windows but so far as I am aware, the project never went forward. As I think it would be valuable to have a version that will run on Windows, I’ve been working on creating a Delphi version of Little Man 2. However, as I am not a C programmer I’ve had to work out what some of the C-code actually says. Fortunately there’s the Delphi version of Little Man 1 that I can use to compare the C and Delphi versions whereever the same functions and procedures are implemented. (The Delphi version differs from the C version in more than just the programming language – the C version for DOS was written pre-mouse; thus everything the user does is done via keystrokes, and there’s a lot of code that just handles getting the keystrokes and deciding what to do based on what key was pressed. The Delphi version replaces keystrokes with mouse movements and with on-screen buttons and sliders.)
I thought it might be easier to start with the Delphi version of Little Man 1 and then make the necessary changes to convert it to Little Man 2. To make sure there were no significant differences between the parts that Little Man 1 and Little Man2 have in common, I imported the Little Man 2 C-code into the Delphi code for Little Man 1 and made a line-by line comparison to be sure that procedures bearing the same names performed the same computations. It turned out that, for the most part, they do. However, Bill chose to rename several of the variables to reflect their new positions in the hierarchy; for example, variables containing a “2” in the name (for level 2) were revised to “3” (for level 3), and level 1 variables were now level 2 (with one exception). In addition, control system variables that had been differentiated by “a,” “b,” “c,” etc. were now identified by new letters that Bill evidently thought would be descriptive of the system’s controlled variable, e.g., “a” (azimuth), “e” (elevation), and “d” (distance).
Code that had resided in the ARM.C main file of the Little Man 1 and 2 programs had been moved to a subsidiary unit called TPUnit in the Delphi version. The C-version of Little Man 2 had added a unit called “ARMDYNAM.C” for the code of the new bottom-level control systems for the muscles. Bill had coded the previous work using integer arithmetic in order to speed up the computations so that the demos would work reasonably fast on the PCs available back then, and had retained this feature in the Delphi version of Little Man 1. I was surprised to discover, however, that the new, muscle-based levels were coded using floating-point numbers. (There’s a routine called “armcont” that converts integer values from the older code to floating point, does the relevant computations, then converts the results back to integer values for the integer-based routines to use.)
Another difference between the C-versions of Little Man 1 and Little Man 2 is that the latter uses three parameter files whereas the former uses only one. One of the new parameter files of Little Man 2 saves the parameters specified in at the muscular level (these parameters do not exist in Little Man 1). The other new parameter file saves gains for proportional and integral control in certain slightly revised versions of the previously existing control systems.
At this point I thought it might be instructive to convert ARMDYNAM.C to a Delphi unit and simply try hooking it into the level 1 system of the Delphi version of Little Man 1. This resulted in the Little Man’s arm flailing about and the program eventually crashing. It’s possible that this result has something to do with Bill’s introduction of proportional-integral control in the higher level, but I haven’t had time yet to explore what is going wrong and why. Fearing that I had not properly converted ARMDYNAM.C to Delphi, I decided to test that unit by itself, and toward that end created a new test program that simply runs the muscle-level systems and presents the results in a set of edit windows that display such things as the joint angle, angular velocity, and angular acceleration of each system, with sliders that are used to set the references for the joint angles. The computations include the dynamics involved in moving an arm that has mass, specified segment lengths, moments of inertia, and so on. The control systems combine perceptions of both tendon force and muscle length.
When I got the test program to run, the control systems turned out to be stable – not at all like the behavior of Little Man 1’s arm when I grafted these systems onto his existing code. Two of the systems quickly bring the perception of the relevant joint angle to the reference value. The third acts a bit strangely – there is a persistent error between reference and perception and sometimes it’s possible to reach steady numbers with the joint velocity indicating a non-zero value while the joint angle fails to change. The next step is to find out where the problem lies. However, that may not happen right away as I’m getting ready to head off on Monday to Florida for a 10-day respite from the Northern Indiana snow and bitter-cold weather. But I wanted to relate how the project has progressed to this point.
The original Little Man 2 demo includes a number of “test” modes that can be activated via various keystrokes, the ability to change and save parameters, and a way to turn the effects of gravity on and off. Once I get the basic program working properly, I’ll add back those features.