I guess I've done a lot since the last entry. I integrated the new Text Generator into the main body of Acuitas code, so now it's his solution for generating speech. I continued with the Text Parser rework and improved handling of infinitive phrases. And I (tentatively) completed Big Story.
Let's start with Big Story. It is plot-complete and currently stands at 99 lines. It generates 45 character "issues" (problems or subgoals), all of which are resolved in some way by the time the story is complete. Compared to any story I've told Acuitas before, this is dramatically longer and more complex (and it still leaves out a bunch of subplots and secondary characters from the movie this story is based on). I did my best to reproduce character motivation and the major story beats in a way Acuitas can "understand."
I don't want to give the story away yet, but here's a low-detail zoom-out of just part of the narrative diagram, to give an idea of how it's shaping up.
Once the full plot was established and all the issues were resolving, I started refining the explanation of some points and fixing bugs. I'll continue this work in hopes of having it wrapped up by year's end. Before I demo the story, I'll also need to reinstate Acuitas' reactions to story lines and the ability for Acuitas and the conversant to ask each other questions about the story (things that fell by the wayside during my last Narrative rework). This should be easier now that the new Text Generator is in place. And of course, working on this project has revealed tons of pain points in the way I currently do things, and ways I could improve the Narrative module. Some time after I get done with it, I'll be tilling all those insights back into the soil, as it were. But that will almost certainly have to wait for next year.
One of the fun asides from this round of storytelling was figuring out how to render another new concept. I originally had this line:
[A] wanted to obey [B] because [A] was cowardly.
Problem: Acuitas has no specific grounding for "cowardly." Could I explain cowardice with the existing tools? Well ... yes actually. Like the obsession with power, it's another goal misprioritization. I replaced the line with these two:
[A] wanted to be safe more than [A] wanted any other thing. [A] wanted to obey [B] because [A] wanted to be safe.
The first line gets this safety obsession flagged as a negative goal, because putting anything but altruism in the top spot is a no-no. Then that taints the motivation for obedience on the second line, which would be fine in isolation. The issue is not that Character A desires safety, but that he will do literally anything to get it (which includes submitting to coercive orders to harm others).
I need breaks from working on Narrative (it's hard), so I've also continued improvements to the Parser. My major accomplishment in the past month was getting infinitives to work again under the new scheme that better supports phrase/clause nesting. While I was at it, I finally dealt with some special constructions that the old parser couldn't handle. Consider these sentences:
1. To live is to exist. 2. Is to live to exist? 3. What is it to live? 4. What is to live?
The previous version of the Parser could handle the first two. The open-ended question form was tricky. I think the most correct way to ask it is Sentence 3; without further context, Sentence 4 means something more like "which things are intended to live." But it's pretty easy for the parser to trip over Sentence 3 (What's the direct object? What role does the phrase play? Does the "what" belong inside the phrase or outside?). This time around I finally put in the effort to get all four variations working - plus some other constructions I hadn't tried before, such as "What is he to do?"
Work on the new Parser continues. I'd also love to have that done by the end of the year, but we'll see.
I've been taking tentative steps into the field of hydraulics, and I'm probably done with those for the year, so I want to write them up. My starting goal was pretty simple: get a minimum viable system together and make it cycle a cylinder. And I got there, mostly.
Why am I doing hydraulics now?
The robots I've showcased here so far have all been pretty simple. The eyeball has two motors; ACE in theory has at least eight. But in the back of my mind there's always a lurking desire for something with a *ton* of degrees of freedom. And once you add an actuator for every possible direction of movement around a joint, the weight of all those actuators starts to become prohibitive. Long-time readers of this blog will recall that I experimented with artificial muscles, specifically the ones made out of nylon. They disappointed me. My home-made fishing line muscles were wondrously cheap and, yes, lightweight ... but slow, power-hungry, and worst of all, not durable. So I'm beginning to explore other options.
The attraction of a fluid-driven actuation system is that you can have *one* motor - in the pump or compressor - which you locate near your robot's center of mass, and a panoply of lighter and smaller actuators that control fluid flow to the appendages. The full power of the central motor can be applied in any part of the robot; instead of having some smaller motors as useless dead weight when their joints aren't currently moving, you can use all the available motive force for whatever the current motion is. And with the right design, the system doesn't need to expend any energy to hold a joint in position either - contained fluid pressure will just do that. A choice remains between pneumatics (gas as working fluid) and hydraulics (liquid as working fluid).
Issues with pneumatics:
Noisy Compressed air is a potential safety hazard Motion tends to be fast and jerky - precision control is difficult Leaks are harder to locate
Issues with hydraulics:
Messy (leaks can cause damage or contaminate environment) Working fluid adds weight Motion tends to be slow System must be primed to remove air
Pneumatics are somewhat common in FRC robots, so I have experience with them from mentoring one of the local FRC teams. We tended to use them for binary motions, like gripper operation (the gripper can be either open, or closed as far as the held object will allow). See video of one of these robots. You can tell when the pneumatics are operating by the hissing sounds. Another year, we used pneumatics to power a throwing arm, which was expected to move quickly through its full range. We stuck to motors for applications that called for positional control.
And that, I think, was the main reason why I decided to go with hydraulics for my own recent experiments. I want that option of precision control. Concerns about the safety of compressed air were also a big factor. I want the freedom to work with unrated home-made or repurposed parts, without worrying about whether my system might explode and skewer me with shrapnel.
The parts
Now for the first hurdle: miniature hydraulics barely seem to be in use among other robotics hobbyists. In my research, I discovered that there's a small market for them among people who build working scale models of earthmoving equipment. Huh. (I took a look at some of their stuff - it felt too expensive for a first try.) But the maker community at large doesn't seem to have an interest, and that makes parts hard to find. The best prior project example I uncovered was this little hydraulic quadruped, which doesn't seem to be documented anywhere.
Fortunately, there is basically no issue with repurposing a lot of pneumatic equipment for hydraulics. I got a pair of solenoid "air" valves from Adafruit, and a bag of cheapo check and regulator valves meant for use with aquarium air pumps. My tubing is all aquarium tubing also.
My "cylinders" are Monoject medical syringes, which I already had a collection of because I save them whenever they come to me (usually with cat medicine). They're a bit of a problem. There is so much friction between the seal and the inside of the cylinder that moving the plunger takes serious effort, even without a load on the cylinder. (If you've never noticed, it's because you don't know your own strength, you big muscley human, you.) And lubrication doesn't help all that much. So I may need to find another solution for the next phase of this project, but I don't know what yet.
The pump was the biggest issue. It's easy enough to get a tiny water pump - aquarium suppliers and CPU cooling system suppliers are both good places to look. But these pumps are built for *moving* water, not pressurizing it, and I suspect they're all built with a poor speed-to-force tradeoff. They don't even advertise maximum pressure in their specs; the closest you'll usually get is a measure of the pump's "head," which is the height to which it can raise water in a vertical pipe. (This is not a pressure measurement, but you can convert it to one.) I included a little 3V water pump in my Adafruit order, hoping it would be enough ... and no way could that poor thing push water into one of my syringes. I'll have to use it for a decorative fountain or something.
So I built my own pump, following the well-known "syringe pump" design. A linkage converts the rotary motion of the pump motor to linear motion that draws a syringe plunger back and forth. Above and below the intake of the syringe are two one-way valves (check valves). When the volume inside the syringe is expanding, water is drawn in through the upper valve; when the volume inside the syringe is shrinking, water is expelled through the lower valve. Control over the connection between the motor and the pump mechanicals means I can theoretically use any gear ratio I want.
For this first attempt, I grabbed a random stepper motor and gear assembly out of my pile of salvage, hooked it to one of my driver boards and got it running under control from the Arduino, whipped up a 3d model of a compatible coupler and syringe cradle, and somehow made the whole thing go. It'll draw the pump syringe back and forth if powered with 6V, and run the hydraulic system well enough to push another syringe at 10V. (I can't seem to find specs for this motor, so I have no idea what voltage it's supposed to run at.)
The system
Diagram of an extremely basic hydraulic system
A basic hydraulic system is a closed loop in which fluid flows from the reservoir (not pressurized) into the pressure chamber, and back to the reservoir again. Valves admit fluid from the pressure chamber to the cylinders, and permit fluid to drain from the cylinders back into the reservoir. A relief valve or bleed valve allows fluid to move directly from the pressure chamber to the reservoir if the pressure in the chamber exceeds the relief valve's limit (this keeps the pump from stalling if the pressure is not being "used up" to drive the cylinders at the moment).
I was going for a single three-way valve that would connect my cylinder to either the pressure chamber or the reservoir - with a passive load on the cylinder, so that it would automatically drain back into the reservoir if connected thereto. (The pump could not help pull the cylinder closed because my reservoir was open to the air.) That's what the rubber band on the end of the syringe is for - I could wrap that around the plunger to create elastic tension that would empty the unpressurized syringe. In practice, my system was using up so much power just overcoming the friction in both syringes that there was virtually none left to drive a load. So I let it fill my syringe and then applied a dynamic load (with my fingers) to empty it. If you watch the video you will also notice that it is waaayyy toooo sloooow. I need more power and more fluid flow all around. So ... okay for a proof of concept, but this has a long way to go before I put it in a robot and it does anything useful.
Future work and thoughts
I already mentioned that the friction losses in the system are far too high. I probably need something that is better designed for easy motion than these syringes are. And despite how high-friction the plunger seal is, my pump syringe eventually started leaking out the back.
The check valves work well enough, but as I mentioned they are not designed for use with liquids. They tend to retain some air inside their housing; getting it all out when priming the system is difficult. And then that air soaks up some of the pump power. A part of its strength during each cycle goes into temporarily compressing the retained air bubbles instead of driving the cylinder.
The silly little aquarium air regulator valves are pretty imprecise. But I looked and looked for an actual relief valve (hydraulic or pneumatic) without finding one that could operate in an adjustable low psi range, for a reasonable amount of money.
So in principle this "works," but I need better parts all around. I wanted to demonstrate a poor man's hydraulic system and I'm reasonably satisfied that I have done so, but now I have to trade out all the pieces in ways that get the performance up.