User Tools

Site Tools


newsletters:2024-02

February 2024 newsletter

What we've been up to

Demos

  • Vedran Budimcic made a train set demo at home:
    • Vedran is also starting work on a Scratch-like environment:
  • Forrest O. has a nice reel on Instagram emphasizing “craft computing” and the hand-made element of interacting with Folk, he makes these individual hexagon tiles
    • The video is also nice because it's end-to-end, shows a lot of little process details of working with Folk, even showing the initial calibration of the table
    • Integration with Cuttle:
  • Andrés made a demo of a Folk-highlighted quote using an excerpt from this Spike magazine article about Folk. The program displays a letter-page-sized border and highlights the text of the quote on the printed-out article. To the right is a program that pulls out the highlighted text and projects it. This is a simple proof of concept, but you could imagine feeding these quotes into a spatial note-taking system on the table, or associating different kinds of data (definitions, related articles, comments on the same passage) to the highlights.
    • highlightquotedemo.jpg

(Omar: Both Forrest and Vedran's demos [and the receipt printer work from last year] indicate the potential importance of custom regions and accurate calibration, instead of the hard-coded 'half-size page' that we currently have. Ideally, it would be easy to make the program region follow the outline of the hex tile or the train or whatever else.)

(I always like when there are specific physical objects, like Folk being overlaid on a book, or a toy train track, etc, instead of a featureless table. The train track in particular has a nice inherently three-dimensional character, it's not like your hand just lifting planar stuff above the table for a second. This all also motivates some of the RFID / alternative tracking, seeing how much the tags stick out visually and how much space they occupy.)

Template matching

Andrés: I've spent most of this month working on template matching (finding the location of an image in a larger image) to enable tracking custom game pieces in Folk. I wanted a basic demo where you can:

  1. capture a small, square image from the table, this is known as a template.
  2. run a program that continuously searches for the template and highlight its location

To that end, I wrapped a few programs into this “Image Slice Matcher” folder made from cardstock:

templatefoldercover.jpeg

templatefolderinside.jpeg

When you open the folder, the left side includes two programs: on the full-size page is a program titled “slice” that will show if you've captured a template image, plus a program that pulls out to the side allowing you to trigger the template capture. Like so:

In a previous version, you had to manually take a photo of the table in order to recognize a template. Now the program reads the global camera image from Folk's main process. This allows the program that looks for and highlights matches to operate much faster and work continuously. Here it is searching for the cover of a small zine as I move it around the desk:

Next month, I'll be extending this to track game pieces in a booklet of games I've been working on.

Parallel evaluator

Omar: I've had some downtime this month, so I've mostly been continuing to work on the parallel evaluator (see also last month).


I've been saying that the pattern is that every 5 months or so, Folk starts feeling too slow, so I rewrite the Folk runtime; then it's way faster, so we pile more stuff onto it over the following 5 months, making Folk slow again, which leads me to rewrite the runtime again. (These runtime rewrites are usually surprisingly backwards-compatible and keep all the language and user programs and hardware interface intact.) This has happened like 3 or 4 times by now, including changes like:

  • converted more and more Tcl code to C code (which is what makes the parallelization reasonable, the evaluator is almost all C already now)
  • introduced various data structures – trie, priority queue
  • removed bottlenecks/blocking and introduced limited parallelism (moved blocking operations onto dedicated processes, used shared memory instead of channels and event loop)
  • graphics optimization (better framebuffer functions and then finally Vulkan)
  • reordered operations to reduce wasted work (don't fully retract a statement until the new replacement statement is in place, so that any retained consequences of the old statement stay alive under the new one; don't re-Collect until as late as possible)

We have reached this point again; I'm regularly frustrated with how slow things feel on folk0 when more than 1-2 things are on the table, even though low-load performance is still pretty good. (I think a lot of people's home systems don't suffer from this as much because they don't have random stuff out, they're working on one thing at a time, and they're mostly using it on their own, not showing it off.)

But I'm hoping that this rewrite will be a permanent improvement where each program doesn't have to make latency worse at the margin, once we have scheduling and preemptive multitasking – we'll be much more like a real operating system where the marginal program doesn't slow down the rest of the programs.


In the new evaluator, I've been introducing a lot of the breaking changes that we've wanted to introduce for a while. These are only in the separate new repo right now, but we fully expect them to come into mainline Folk once the new evaluator is ready:

  • Commit has been renamed to Hold! (sort of named from sample and hold)
  • In general, non-reactive / sampling / imperative language constructs (not Wish/When/Claim) now have a ! at the end:
    • Assert is now Assert!
    • Retract is now Retract!
    • Commit is now Hold!
    • Statements::findMatches is now Query! (this is used on stuff like the web server to snapshot query the database as it is right now, without introducing any new reactive dep)
  • C compiler objects are now implemented as standard Jim objects instead of with weird namespace hacks, so [c create] is now [C] or [C new]
    • also feels correct because stateful objects should probably be made with new instead of create which I think is more for immutable objects like dicts and lists
  • $cc compile now binds C functions as methods on the $cc object instead of making them global Tcl functions
    • (part of removing as much global state as we can, since we can't guarantee that code will run on the same Tcl interpreter. at least you can conceivably pass $cc around explicitly and then do the ferrying through statements)
  • you can no longer rely on procs from earlier in a program being available inside Whens (since procs are only state in the thread-local Tcl interpreter); for now, the pattern is to make a 'lambda' in a variable in lexical scope, which gets inherited by Whens
    • like loopRegion here which is passed through lexical closure:
    • ugly/tedious but should suffice to port/test most things for now, we can think of better ways to do this later

Example of how you'll be able to write programs/Whens that run concurrently, with arbitrary blocking & loops:

This is useful, for example, for talking to webcams: you can have a virtual program that is a simple infinite loop, where the body blocks on the webcam read from Linux, then Hold!s a statement with the resulting camera frame. Or for making HTTP requests: you can write a program that literally does exec curl and then uses the result without halting the rest of Folk. I really like that naive straight-line imperative code will just work and do the reasonable and expected thing.

Also notice how the other thread gets arbitrary samples of the counter value (0, 97, 107, etc), it doesn't actually evaluate for every intermediate state. This is the behavior that you want for statements! If processing takes a while, you don't want to fall behind by processing intermediate page locations or whatever as the user moves a page around, you want to catch up to the latest stuff as soon as possible.

(If you _do_ want to process intermediate states, you want something with different semantics from normal statements, like event statements or something. This is an open question.)


(under the new evaluator, I'm hoping you can just beam stuff out to the GPU at 60fps, using Query! to sample from whatever happens to be in the database at that moment; you don't need to wait for a system convergence that includes all programs)


Ported the web server, which (elegantly) can now just be a normal virtual program, since it blocking on clients/sockets is perfectly OK in the new evaluator.

Ported most virtual programs (camera, AprilTag, GPU/display). Also elegant: finally trashing the pi/ directory and inlining everything (talking to GPU, cameras, other libraries) into the virtual programs. (We want to do this partly to make everything live-editable inside the system; it should help with readability/understandability, too, since you'll know exactly what files to read to understand those subsystems, and there'll be fewer intimidating random folders/files in the repo.)

Even mostly works on my laptop (because we're no longer reliant on fork which completely breaks GPU access on macOS):


The key issue with the parallel evaluator right now is the locking, which is increasingly messy. (the naive one-big-lock implementation from last month ended up not working at all, deadlocks everywhere). So I've been trying to figure out what data structures and invariants we actually need…

img_6042.jpeg img_6095.jpeg

Did a pass of looking at the data structures (Statement and Match) and ripping out stuff, especially reverse (child→parent) pointers.

matchstmt.jpg img_6167.jpg

(I think we can get rid of a lot of reverse pointers by 1. using a flat reference count instead of list of reverse pointers [flat reference count is also just a lot cleaner to deal with in C as a value, you can make it atomic] and 2. leaning on weak refs more and just letting the forward pointers get invalidated and leaving them dangling instead of needing to use reverse pointers to walk back and clean them up)



Next steps here are to figure out the data structures/locking/atomics so that tests reliably pass, then do a run on a table with all the major components of the system (camera, AprilTags, GPU) and see how it performs compared to the old evaluator (that end-to-end test is really the only way to find out, I think)

RFID

Omar: RFID work continues, on and off – we left off in January just about being able to do multiple hops on IB and wanting to continue on to OOB and live reporting and localization.

Unfortunately, this month I found that IB is still too unreliable (it breaks down after the first round for some reason). so it can continue for multiple hops, but not _that_ many hops, which means it's not feasible yet to leave it on and sync the OOB to it and do the whole live localization process. See how it breaks after 1-2 rounds (“THE TOP”) in these examples:

and

Anyway, in February:

  • Started bringing back the live imgui GUI, at least for the IB part that currently works (the Python after-the-fact GUI was always a stopgap)
    • (It still just reads the dump file, but it's a start. At least it's more customizable and interactive. Some work just to port over x-axis annotations and stuff like that to display bit boundaries and decode results.)
  • Started on new IB↔PC↔OOB communications scheme (now that decoding happens on the radio, we don't want or need to stream all samples from the radios to the PC – I don't think we can spare the time on the radios anyway – we just need to stream timing and bit boundary information)
  • Working out error states so that if something goes wrong during decoding, we can revert to a state where we can recover and continue normal IB functions once we see a sync pulse (within a few hundreds of microseconds). You don't ever want the system to end up in a terminal state, you want it to be able to run forever
  • Now trying to speed up the IB decoder even more to give us more headroom. Simpler pulse detector that uses a window instead of needing to scan 2*buf, removing heap allocations on the decode path, stuff like that
    • (sometimes I wonder if I'd be better served writing Verilog instead)

There must be some bit of hidden state in the IB radio that causes it to go off the rails and consistently fail after that 1-2 rounds… fix that & fix error recovery, then set up OOB(s), then set up localization.

Friends and outreach

  • We had our monthly open house on Feb 22. People were really into the editor this time, which was great to see – it's nice when people get to stick around for a few hours and make things, not just get walked through demos:
    • img_6082-oh.jpeg img_6074.jpeg img_6044.jpeg
    • img_6086.jpeg img_6062.jpeg
  • Vedran and Forrest set up their systems this month – Forrest had a Discord thread where he ran into an issue with glslc not working out of the box, had to fix that
    • First photo of Forrest system:
  • Rob Ochshorn and Cristóbal Sciutto came by Hex House and we attempted to fix wobble/jitter in folk0. We concluded that a lot of it is actually physical jitter where the webcam is vibrating, not frame-to-frame variation in the tag detector…
    • img_5587.jpeg img_4405.jpg
    • You can literally put your finger against the webcam and feel it vibrate with the heater and other stuff in the warehouse.
    • We even tried hanging the webcam by its cable, just for fun:

Other work

  • Got folk0's printer on USB instead of Wi-Fi after it completely failed during open house
    • (It's been an irritant for a long time, it failing to get on the network or getting on the wrong one or ending up in weird dead-end states)
  • Andrés fixed a bug in the table editor that was preventing printing more than one program from an editor. Now you can print to your heart's desire right from the table.

What we'll be up to in March

  • New collaboration (still TBA) on deeper phone/laptop integration and knowledge management
    • (Omar: I did some prototyping last weekend on localizing a phone using its camera + a tag on a laptop screen. I feel like you could do clever stuff with phone sensors and dead reckoning and smoothing to make this a nice experience even if tag tracking cuts out. Ideally you could just use a valid QR code, not even a specialized fiducial. Also thinking about Joy-Cons and Wii Remotes and how they do mouse-like pointing.)
  • Fine-tuning the template matching and using it to create small board-game interactions
  • Polishing Folk/CNC interface for use by other people at Hex House and in general
    • USB stick install / Linux distro packaging, both Owen's demo and Folk more broadly (this will be a big deal for getting people up and running, I think)
    • Better Web UI
    • Finishing up the 3D/high-accuracy calibration work from late last year to actually do the machine preview in Folk
  • Going to the hardware store to do some jitter reduction
  • RFID: Continuing to try to debug why we lose contact after 1-2 rounds of IB communication, work on the imgui GUI, hopefully start on OOB
  • Parallel evaluator: continuing to work on locking and scheduling, goal is to do a table test after that to see how it performs

Omar

Andrés

newsletters/2024-02.txt · Last modified: 2024/02/29 22:22 by osnr

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki