Saturday, September 17, 2022

Acuitas Diary #53 (September 2022)

Last month's Narrative feature addition dealt with planned actions and their side effects: a desired action or state might be chosen for some outcome (e.g. solving a problem), but will also have other outcomes. If any of these are too negative, Acuitas will expect the character planning that action to take steps to mitigate them.

This month's work directly built on that by introducing the idea that agents can *add* side effects to other agents' actions, by choosing a conditional behavior: "If you do X, I will do Y." This is the groundwork for understanding social interactions like bargaining, reward, and coercion.

A series of captioned stills from Disney's "The Emperor's New Groove." Yzma and Kronk are locked in a closet (the scene is dark, with little except their eyes visible). Yzma says to a person outside, "Tell us where the talking llama is and we'll burn your house to the ground." Kronk says, "Uh, don't you mean 'or'"? Yzma then says, "Tell us where the talking llama is OR we'll burn your house to the ground."
Film stills from kpfun.tumblr.com via Sam Stryker (Buzzfeed). Copyright Disney. 

The introduction of a story sentence like "Agent A decided to do X if Agent B did Y" now creates a new cause-and-effect rule for the Narrative engine to use; it isn't stored to the permanent database, only used within the domain of that story. For reasoning purposes, it is assumed that "B does Y" will automatically happen if A does X ... so long as nothing is preventing B from doing Y.

I can start to define some verbs in terms of these models - much as, in previous Narrative work, I effectively defined "lie" as "tell someone a proposition that you don't believe." Now "coerce" ... in at least one of its forms ... can be defined as "deliberately apply a negative side effect to someone else's subgoal." If this happens, the Narrative engine will infer that A coerced B.

I was more interested in coercion than the positive options, thanks to the second goal of the month: to figure out a functional understanding of "freedom." As with other important abstractions I've introduced, I don't promise the result is better than an oversimplification. But we have to start somewhere.

And seeing as it's the high concept of my whole country, I should probably figure it out.

A still of Cloud William in the prison, from Star Trek: The Original Series episode "The Omega Glory." William is saying, "It is a worship word, Yang worship."
"The Omega Glory" is one of the silliest Star Trek: TOS episodes there is, and I still love it.

Freedom could be defined, in a very simple and broad sense, as a lack of constraints. But all humans live with constraints. We generally don't presume that freedom requires *omnipotence.* So to get closer to the idea of freedom that people generally have in mind, we might say "a lack of *unnatural* or *exceptional* constraints." These could include situations that severely reduce one's options below the ordinary level ... getting trapped in a cave by a landslide, for instance. Since any constraints imposed by other agents are not part of the default state of things, they are also included. Freedom in a narrower sense is concerned with not having one's existence, abilities, and purpose subverted - not being *used* as a means to someone else's ends.

Assessing what counts as a "severe reduction of options" is a little beyond Acuitas' capability right now, so I plan to just put conditionals in the database for some of these. "Confined implies not free," "restrained implies not free," etc. But as for the other part, the Narrative engine can assess whether some other agent is applying coercion, or otherwise purposely constraining the viewpoint character's actions. If this happens, the viewpoint character is less than free.

There are a couple of additional wrinkles. Agent B's freedom is not regarded as being lost if Agent A thwarts one of Agent B's goals in *self-defense.* If we didn't have this provision, we'd be stuck with conundrums like "Agent B wants to prevent Agent A from living. Agent A wants to prevent Agent B from killing them. Who is offending against whose freedom?" For an idea of how "self-defense" is defined, take a look back at the Odysseus and the Cyclops story.

Now for what I found to be the trickiest part: sometimes you can interfere with someone else even while minding your own business. For example, let's suppose Josh has a goal of buying a PS5. There's a world of difference between "Josh could not buy the PS5 because I bought it first," and "Josh could not buy the PS5 because I wrestled him to the ground and wouldn't let him enter the store." I take a volitional action that reduces Josh's options and prevents him from achieving his goal in both cases. In the first case, I'm not limiting Josh's freedom, just exercising my own; my interference is indirect and incidental. In the second case, my interference is direct and intentional. So I can express the difference in words, but how on earth to explain it to a computer?

I finally decided a handy encapsulation was "Would Agent A still take the interfering action if Agent B didn't exist?" In the above example, I would still buy the PS5 whether Josh were involved or not. (Unless I were being a dog in the manger and only buying it to spite him, in which case that *would* be reducing his freedom! See how context-dependent these things are.) But I'd have no incentive to wrestle Josh down if he were not there (not to mention that I wouldn't be able to). Can you come up with any thought experiments in which this doesn't work? Let me know in the comments!

Again, testing for this in the Narrative engine is a little complex for now - it requires a somewhat more thorough analysis of character intent than I'm currently doing. But having it in my back pocket for the future makes me feel better. As a stopgap, I went with the less perfectly accurate "is Agent B an object of Agent A's interfering action?"

For purposes of a quick test, I wrote the following totally not historical story about ... feudalism, I guess:

0:"Robert was a human."
1:"George was a king."
2:"Robert wanted to study mathematics."
3:"George wanted Robert to work George's farm."
4:"Robert didn't want to work the farm."
5:"If Robert studied mathematics, Robert could not work George's farm."
6:"George decided to beat Robert if Robert studied mathematics."
7:"Robert left the farm and went to the big city."
8:"George did not know where Robert was."
9:"So George could not beat Robert."
10:"Robert studied mathematics."
11:"Robert became a scholar."
12:"Robert never worked the farm."
13:"The end."

The Narrative engine picks up on a threat to Robert's freedom on Line 4, and retroactively marks George's goal from Line 3 as something negative. Wanting another agent to do something, or not do something, is all fine and dandy; it's only if your wishes for them oppose theirs that we run into trouble. An attempt at coercion happens on Line 6; Robert cannot safely fulfill his goal of studying math now. But George's illegitimate plan is blocked, and Acuitas can conclude that this story has a good ending.

With this done ... I think I've built the capacity for understanding all the necessary concepts to explain the conflict in the big story I've been targeting. They need more refinement and expansion, but the bones are there. This is exciting, and I may start pushing toward that more directly.

This post is dedicated to all who pursue freedom and relief from an oppressor - particularly my Ukrainian friends. I know the cost is heavy. Much love.

Until the next cycle,
Jenny

Friday, September 9, 2022

Anycubic Vyper 3d Printer Review

Many of you may already be familiar with my recent decision to become a two-printer household. Here I'm doing a more formal write-up to help others decide whether a Vyper might be the right printer for them.

A Qidi Tech X-One 2 3d printer (blue metal box with plastic windows) sits next to an Anycubic Vyper 3d printer (vertical black metal frame with tan PEI build plate)
My little manufactory now.

My original printer is a Qidi Tech X-One 2, and you can read my early review of it here. Since I got it, the X-one 2 has produced all the pieces for three substantial projects - Ghost, Atronach's Eye, and ACE the quadruped - plus quite a few gifts for friends. So it's been a pretty solid workhorse, but I decided to add the second printer for several reasons.

1) I wanted a larger build volume. The X-One 2 can't print anything bigger than about 6x6x6 inches. The limitations of this became most obvious when I couldn't help print face shield parts during the early pandemic, because the models wouldn't fit. I can usually get around the limitation by splitting models and adding joins, but sometimes that just doesn't work. The Vyper's volume is much larger than the X-One's, and slightly larger than typical printers in its class, at 245 x 245 x 260 mm.

2) I wanted to potentially run both printers at once and accomplish projects faster.

3) I just wanted to try out one of the ubiquitous "Rep-Rap" style printers, with the open frame. This is a very different design from that of the X-One, which is a self-contained box. The X-One's print head is suspended from the upper inner portion of the box and moves in the XY directions, while the build plate moves along the vertical (Z) axis, along a lead screw. The Vyper moves its plate along the Y axis, and its print head along the X and Z axes.

A cat lying on top of an Anycubic Vyper 3d printer, disassembled in its box. The vertical part of the printer is visible nestled in black packing foam.
Unboxing and inspection

The Vyper also came with some quality-of-life improvements over the Qidi. It has automatic bed leveling. As careful as I was with the X-One's bed, in the end the only way to get it perfectly level was to do test prints and see how much the filament was "smashed" on different sides of the first layer. So this was a welcome feature - and possibly a must given the much larger print bed. The printing plate itself is a spring steel sheet coated with textured PEI (a slippery plastic), and magnetically attaches to the underlying heated bed. The idea is that you can remove the plate and bend it to peel away stubbornly attached prints.

The only real disadvantage of the Vyper, compared to my previous printer, is that it's not fully enclosed. So when I start wanting to print PETG or ABS on it, I'll probably need to rig up a tent for it to hold in heat. It also doesn't come fully assembled. But I'm feeling braver now than when I bought my first printer.

A cat clawing the packing foam of an Anycubic Vyper 3d printer, still in its box.
Packing foam must be destroyed.

The Vyper requires light assembly. The print head, the filament feeder, the bed mechanicals, etc. are already all together; the end user just needs to bolt the upright portion of the frame to the base, attach the touch screen and the filament holder, and connect some cables. All necessary tools are included. It took me (going cautiously) about an hour and a half to unbox the printer and put it together.

Base, build plate and included tools, shown packed in the small tool drawer that fits into the base.

Preparations for first print also went very smoothly, with one exception: the weak documentation forced me to look a couple of things up on the internet. This is another Chinese printer and I think they may not have used the greatest English translation services. To start bed leveling, you're supposed to "touch" the metal nozzle with a tool. I touched it repeatedly, to no avail, holding the wrench in different orientations in hopes of lining it up with some optical sensor. Turns out the sensor is neither optical nor capacitive; it's a pressure sensor. You have to *push* up on the nozzle, not just touch it. The other little hitch was that the printer's internal file system does not allow for folder navigation, so all GCODE files have to be in the root directory of the SD card (and the sample file that comes on the card is not!). So I had a brief scare when I repeatedly poked the folder name on the touchscreen and it wouldn't open. But this is apparently normal. You just have to read the SD card using a regular computer (this printer comes with a USB SD card reader too!) and move the sample file into root.

The Vyper heats itself to operating temperature before running the bed-leveling routine, presumably to make sure that the results account for thermal expansion of the parts. The print head will tap the bed with the nozzle in a mesh of locations to check and adjust the height. When I ran leveling for the first time, some plastic goop oozed out of the nozzle and left dots on the print bed. I take this as a good sign: QA must have run a test print, or at least checked filament feeding, before the printer was disassembled for shipping. I ended up running leveling a second time after the nozzle was cleaned out, just in case that leftover filament blobbing out of the nozzle interfered with results in any way. The automatic leveling seemed to work well. My first prints adhered to the bed just fine and had great-looking first layers.

So bed leveling just worked, and then filament feeding just worked - both into and out of the nozzle. This overcomes the biggest operational flaw of my X-One, which is frustrating to load and has *never* been able to retract filament successfully. I have to hold down the filament release lever and manually yank the filament out; telling the printer to retract it just results in slipping feed gears and the creation of a swelling in the warm filament below, after which I have to take apart the print head to get it out. The Vyper looks as though it could have more points of failure with its more complex feed path, but I had zero trouble loading my first PLA, then changing colors later.

Printing! The latest version of the eyeball cradle.

The Vyper feeder also has an extrusion tension knob, another feature new to me. My first print appeared to have slight signs of under-extrusion, so I made a small adjustment, and left it alone otherwise. For future maintenance purposes, there appear to be easily accessible mechanisms for tightening the belts. 

I decided to be brave and print directly on the PEI build surface, instead of covering it with tape. This also worked wonderfully. I was able to pull all four of my prints off without even removing the plate to bend it. One of them (a large, flattish piece) even released itself from the surface after being left to cool long enough, and was lying there loose when I came to get it.

Two 3d-printed Wolf School amulets, one in dark red PLA (left) and one in bright orange PLA (right). Top/front view.
First print from Vyper (left) compared with first print from X-One 2 (right). Model by Thingiverse user Daniel_W.

I've seen some reviewers complain that the magnetic build surface doesn't have any slots or guides to fit into, so it can be a pain to line it up perfectly when sticking it back onto the bed after print removal. I re-seated it when assembling the printer and found that yes, it's a little tricky, given that the strong magnet will try to pull it down fast and fight your attempts to shift it. I don't consider this an important issue. So it demands a little more care and coordination - oh well. I'm more concerned that the PEI surface isn't a sticker. If it gets scratched or gouged, I think you have to replace the whole spring steel plate, for about $25. But one of my future goals is experimenting with other surfaces, so I may end up layering something removable on top of it anyway.

I used Cura to slice my models, as I do for the X-One. It doesn't have printer-dimension presets for the Vyper yet, but the documentation will tell you how to start from existing presets and change the numbers to fit the Vyper. The manufacturer also provides recommended PLA print settings, which I loaded in and tweaked to my liking. No problems here.

The bottom sides of the two amulets. Red (Vyper-printed) amulet has a very even surface with a regular marbled texture on it. Bottom amulet (printed on tape) has traditional smushed diagonal lines plus some irregularities from boundaries between tape strips.
And the underside: first print from Vyper (top, textured PEI surface) compared with first print from X-One 2 (bottom, blue painter's tape). Model by Thingiverse user Daniel_W.

Print quality was great. I won't say "perfect," since I can see a few hints of wall irregularities, and the support situation on my first model was less than ideal. But I think quality is slightly better when compared with my very first print on the X-One (same model). I also haven't yet tried to really dial in the Cura settings.

After my initial test print, I put the Vyper straight to work on a new iteration of Atronach's eyeball (three parts, all PLA), and this went off without a hitch. I think that's a pretty good test for all the basic functionality. Prints I have yet to do include 1) something really detailed, like a miniature, 2) a print-in-place tolerance torture test, and 3) something in PETG.

A 3d-printed "eyeball" with a webcam mounted inside, sitting in its rotator cradle. Transparent nylon lines run like lines of longitude from holes around the "pupil" to the back of the eyeball.
The latest eyeball. More about this later!

On the whole I'm very happy with this printer. It was on sale on Newegg, and I got it for about $350 with free shipping. I was a little concerned about quality as compared to e.g. a Prusa, but at half the price I was willing to risk it, and I think that has paid off.

Until the next cycle,
Jenny