Monday, August 22, 2022

Acuitas Diary #52 (August 2022)

For the first half of the month I just did code refactoring, which is in general rather boring, but essential to make my life easier in the future. Better organization really does make a difference sometimes.

My main project was to unify how Acuitas represents "problems" and "subgoals." This was one of those cases in which I thought I had a good structure initially, but then realized, through further development, that the practical needs of the system were different. I found out that "problems" and "subgoals" are really just negative and positive variants of the same thing. Both consist of states or events that are goal-relevant to an agent - the only difference is that subgoals are being *sought* and problems are being *avoided.* But since I had separate tracking systems for both, I was having to write everything twice. To make matters worse, sometimes I would only throw a new feature into the system that needed it most for what I was doing at the moment, and the code for the two was starting to diverge.

A pizza with vegetable toppings

So I undid a big snarl of code in the Narrative and figured out how to smoosh them both together into what I'm calling "issues," and made sure all the stories still worked. I also unified problem and subgoal tracking in the Executive. Much better. This has been a pain point for a while.

I also fixed up the "motivated communication" features that I introduced to the Conversation Engine last month. These allowed Acuitas to draw on both his own internal states (mostly the time-dependent Drives) and his own problems, oops I mean Issues, for things to tell a conversation partner. The difficulty here is that he has a lot of issues that spring from internally generated questions. These are fairly trivial - no particular random question is all that compelling - but after hours of sitting alone and "thinking" to himself, he would have so many of these that they tended to overwhelm other conversation topics. The goal priority scheme was also treating them as "more important" to talk about than the Drives, even if the Drives were urgent (uncomfortably high) and the questions were not.

So I introduced a new categorization scheme for describing *how* important an Issue is to the achievement of its relevant Goal, which helped bring the Drives up to the top in terms of importance. Then I switched to a weighted random selection (like the one the Executive uses to pull Thoughts out of the Stream) of which topic gets mentioned next, so that it privileges the most important topics but isn't fully predictable.

The second half of the month was for new features, which meant *even more* upgrades to the Narrative module. I started work on how to handle actions that have mixed results or side effects. For an illustrative example, I wrote the following story:

Ben was a human.
Ben was hungry.
The oven held a pizza.
The pizza was hot.
Ben wanted to get the pizza.
But Ben didn't want to be burned.
A mitt was on the counter.
Ben wore the mitt.
Ben got the pizza.
Ben ate the pizza.
The end.

Fun fact: I wrote the original version of this on a laptop and e-mailed it to myself to move it to my main PC. Gmail auto-suggested a subject line for the e-mail, and at first it thought the title of the story should be "Ben was a pizza." Commercial AI is truly doing great, folks.

Based on information I added to the cause-and-effect database, Acuitas knows that if Ben picks up the hot pizza, he will both 1) have it in his possession and 2) burn himself. This is judged to be Not Worth It, and the old version of the Narrative module would have left it at that, and regarded the story as having a bad ending (why would you touch that pizza Ben you *idiot*). The new version looks at how the implications of different events interact, and recognizes that the mitt mitigates the possibility of being burned. Grabbing the pizza switches from a bad idea to a good idea once the possibility of self-harm is taken off the table.

The explicit addition of "Ben didn't want to be burned" establishes the bad side effect of his "get the pizza" subgoal as an independent problem, which enables speculations about how he might solve it and so forth. The story wraps up with two solved problems (this one, and his primary problem of hunger) and one fulfilled positive subgoal (get the pizza).

That's enough for now, but wait until you see how I use this next month.

Until the next cycle,
Jenny

Saturday, August 6, 2022

ACE the Quadruped, 3.0

I've had a chance to finish and try out the latest iteration of quadruped joints and frame, and I'm happy to say that I think they're a significant improvement. As in, IT CAN STAND UP NOW.

  Exploded 3D model of one quadrant's worth of frame piecesOne half of the frame, assembled in the real world

For newer readers, the quadruped's name is ACE (Ambulatory Canine Emulator), and I first started trying out quadruped designs in my late college years. I was thinking that the interesting part would be designing or training the walk cycle, but I haven't even gotten that far yet due to difficulties with the mechanical side of the project. It turns out that you need a decent degree of precision for something like this, and that can be hard to get from homemade parts and salvaged materials. Specifically, I had big trouble with 1) joints moving out of plane and 2) parts of the structure flexing. A little bit of variability or unconstrained motion may not seem like a big deal, but once you consider the contributions of multiple joints in a leg *and* a bending frame, you get a robot that can't stand up.

Prototype of elbow/hock joint with temporary homemade spring.

This project has been dormant for a while. Here is a photo of some previous joint design attempts (along with previous lab assistant d'Artagnan, who has since passed on). I didn't have a 3D printer yet at the time, so I was still limited in what I could manufacture. In some ways, the elbow/hock joints described in that blog post were a real improvement: the metal tubing shaft + ballpoint pen sleeve combination provided smooth, constrained rotation. The problem was the method of attaching it to the leg bones. Suspending the two halves of the joint on wires didn't work out; they just weren't rigid enough for the application.

A cat lying next to a pair of robot legs made with PVC tubing.

Throw in further issues with the shoulder/hip joints and the frame/upper body (which were so embarrassing I don't think I even blogged about them) and the attachment of the motors to the legs, and it was hard to even get the robot to passively stand in an upright position. Some joint was bound to start wobbling or folding sideways and tip the whole thing off balance. The photo below shows my best effort to pose it for a robot "group picture." It isn't standing at full height, at least one leg is tilted out of plane, and it's probably still ready to fall over if someone blows on it too hard.

A quadruped robot made of PVC pipe, wood, and other salvaged materials, with motors mounted on the legs, standing awkwardly on someone's computer desk.

This latest round of work was a complete redesign of the joints and structural elements. I reused the PVC conduit legs, the same motors, and the wooden dowel sections from the original frame, and that was about it. The old version had each motor mounted above the joint it was to operate, with a linear actuator attachment; this would convert the motor's rotary motion into linear motion and push/pull one "bone" relative to the other. This meant one of the motors was attached directly to the upper half of the leg. In the new version, I decided to actuate the joints with differential pairs of tendons, and put all the motors up on the frame - which means there isn't a heavy, clunky motor hanging off each leg. I designed and printed plastic joint couplers intended to solve the problem of unconstrained motion. I gave some thought to gravity-countering tension elements for the first time, and included attachment points for them. And I eschewed screws in favor of bent/wrapped wire connections. I used these to good effect in Atronach, and they're my current favorite way of joining 3D-printed parts. The only screws in the new design go through holes in one of the frame pieces and into the ends of the wooden dowels.

The latest version of ACE "lying down."

The 3D printer's ability to produce almost arbitrary shapes was a big help here, but I also knew I would have some trouble getting smooth, precise motion out of printed joints, just by the nature of the thing. Tolerances aren't guaranteed to be perfect, and layer lines mean the surfaces will always be a little rough. So I included some of my old friends: chopped-up ballpoint pens. (This is seriously the most convenient way I know of to get rigid plastic tubing.) I designed each joint to use part of a pen as a shaft, with the 3D printed pieces wrapping around it to provide both the rotating shaft collar and the fixed mounting point.

The elbow/hock joints are simple hinges, with a range of motion somewhat less than 180 degrees. They are designed to join two tubes in the same plane. For the shoulder/hip joints, I came up with this design that has the leg tube suspended from the shaft and rotating between two guides. The total contact surface is fairly large, which I hope will help reduce any out-of-plane rotation.

    
The shaft rotates freely with respect to one part in each joint, and is fixed to the other. The part on the fixed side has ~1 mm holes which accept a paperclip wire. I pierce corresponding holes through the shaft, insert the wire, and bend the ends so it can't slip out, a bit like a cotter pin.

   

I also had to think about the routing of the tendons while I was designing all this. The tendons that work the elbow joint go up the inside of the hollow upper leg bone, through a hole drilled in the "fixed" part of the shoulder joint shaft, and out the end of the shaft to their motor's axle. That means they don't interfere with, or change length during, motion of the shoulder joint - because they're routed parallel to its axis of rotation. Control of the two joints can be fully independent as a result. Shoulder joint tendons feed through holes in the solid pieces that connect the two joint guides (so that they'll pull in the right direction), then turn ninety degrees and pass through holes in the joint's base to reach their motor.

Elbow tendon routing through shoulder

I designed all the pieces a little too tight, and sanded them to fit. So most things push or snap together well enough that it maintains a lot of integrity even without all the wires installed. Everything has options for a wire connection, though, because I know how important it is to guarantee that pieces don't unexpectedly move (and my first bitter lesson was that you can never count on glue). Printed pieces that join have matching holes; the leg joints wire up to drilled holes in the PVC.

So now, the moment of truth. Does it stand? Behold!

Unlike the previous version, whose linear actuators would basically lock the joints in position, this one kneels under its own weight. The unpowered holding torque of the motors isn't large enough to keep the joints extended. Tension elements will help with that, but I don't have any yet (except one spring I made for a test). So I used wires to hold the elbow/hock joints open for purposes of that photo. Most of the tendons aren't installed yet either, so three of the four shoulder/hip joints were free to rotate ... and I still got it to stand. Wow. I was half afraid I'd never get here.

Now that I've built everything, I've already got ideas for how to make the next round of joints better. But Atronach should get some attention now, plus I'd like to take a step back and try to improve my 3D printing technique. I hope to return to ACE next year and either try some real actuation, or decide these motors don't have an adequate torque-to-weight ratio and redesign the motor cradles to hold something else. (If I need new motors, I'll only have to change that one part, which is pretty nice.)

Until the next cycle,
Jenny