2025-09-04
TL;DR: I burned myself out a little on my self-playing piano project by working on it all summer, so I’ve decided to switch to a weekly rotating project schedule. To help clear my mind, I’ve begun building a little art piece made out of some single-sided FR4. This has prompted me to learn more about how to use Inkscape, how Bézier curves work, and some of the details of the SVG standard.
I spent the summer working on my self-playing piano, which was fun at first but became unexpectedly challenging and frustrating. I learned a lot and still intend to finish the project, having overcome a lot of the problems I found in the summer, but I need a break before I can do that. I also realized towards the end of this iteration of the project that I should reconsider how I allocate my time for them. Right now, I choose a project, set a rough goal and end date, and then work on it more or less exclusively until one or the other arrives. I started doing projects this way in order to give myself some structure and encourage actually getting to the end. Previously, as soon as a project got difficult, I’d switch to something else. Selecting a project and working on it for a longer period on purpose was a good way to avoid this issue.
It turns out that this method can burn me out if I work on something too hard or for too long. I overestimated my progress on the piano project at the start of the summer, so a lot of my frustration came from uncovering the lurking problems with my design and “catching up” to where I thought I already was. This is likely to happen again if I continue with this approach. It also makes it difficult for me to react to changes in my own interests on shorter time scales.
I’ve decided to adopt what I call the Usagi model of personal project management, which I’ve stolen from David at the Usagi Electric YouTube channel. His method is to maintain a list of around four projects and cycle between them on a weekly basis. When a project finishes, a new one takes its place. Sometimes a one-off project will displace another one for a short time. He claims that it reduces burnout and helps to maintain a high level of interest in the projects over the course of years. I like this idea because it directly addresses the problems I’ve encountered with my current system. It also reminds me of a round-robin timesharing system that you might find in an older computer operating system. Maybe that’s where David got the idea.
I still plan to write a big post about my piano work over the summer, and then the piano project will take its place among the four normal slots in my rotation. I’ll spend my next piano “time slice” on writing the post and ordering any additional parts, and then the next slice in a few more weeks will be the first one where I get back to actual engineering. That should be plenty of time for me to recover from this minor burnout. I also plan to write weekly posts corresponding to each project period (like this one), which should make them shorter and easier for me to write.
My wife suggested that I try to make some of my projects under this new system about art, and I think that’s a good idea. I don’t have much skill in most of the traditional art disciplines, but I think it’ll be healthy for me anyway because it’s harder to completely fail to make art. I had an idea for a sunrise picture knocking around in my head, so I sketched out a few ideas and then drew it up in Inkscape.
Initially I wanted to cut up some bits of wood on my new CNC mill and then apply different stains to separate the two colors, but I decided against it because the cutting depth for most of my end mills just isn’t deep enough to work with the lumber I have. I could resolve this by just getting thinner pieces of wood, but I realized I could use some spare single-sided FR4 I had laying around from the piano project and potentially get a better result. The shiny copper will represent the sun and its rays, while the fiberglass on the back will be the sky, which explains the unusual colors in the SVG. I’ll cut the pieces and glue them all together on an MDF backing board.
It was fun to learn a bit more about how to use Inkscape for non-trivial work. It’s a really powerful program for this kind of stuff, and I only understand a tiny fraction of its features.
Kerf is the width of the cut that a tool makes. Rather than simply splitting the material into two pieces with no loss, most mechanical cutting tools take tiny bites out of the material and spit it out as chips or dust. It’s important to account for kerf when planning cuts. If you line up a cutting tool with the center of a cut, then half of the tool width will eat into each side of the cut path, leaving you with two pieces that are shorter than you might have wanted.
For this project, I need to tell my CNC mill how to make several
closed loops in such a way that it cuts out the shapes I want. If I feed
the paths in the above SVG directly into svg2gcode
,
then I’ll end up with shapes that are all half a tool width too small.
Instead, I need to offset the tool by half a tool width in the “outward”
direction for all paths and cut along that path. The tool will
sort of “roll” along the edge of the desired shape. The kerf isn’t
eliminated, but it’s fully inside the waste area of the material that
I’m going to discard anyway.
The general problem of finding offset
curves is interesting and sometimes difficult. Because they
show up all over the place, lots of software can compute them in one
form or another. For my projects, I like to try to find non-GUI
solutions since they can be automated more easily. This increases my
iteration speed by allowing me to make tiny changes, run
make
or whatever else, and get new output immediately
without clicking around and maybe forgetting something. I searched
around for an easy way to compute offset curves for either SVG paths or
G-code, but I couldn’t find what I wanted. It seemed like I would need
to do it myself.
In this case, it’s okay to approximate the offset curves as
sufficiently small line segments, rather than finding mathematically
perfect solutions. Since SVG paths are a sequence of several different
possible parameterized subpaths, an algorithm can convert the path
description into a list of points with some geometry. This
polygonal path is just the kind of thing that the Clipper2 library is
good at handling, and it’s a particularly good fit for me because it has
Rust bindings and an inflate
method that computes the offset path exactly how I want. I was hoping to
avoid figuring out how to compute the offset path (even from a point
list) because of annoying problems like “which of the two normal vectors
points in the outward direction?” and “how do I handle extreme
concavity?” Clipper2 sweeps that all up for me as long as I can provide
it a list of points.
The SVG path
language is somewhat complex and has some edge cases that I didn’t
expect. There also doesn’t seem to be a Rust SVG parsing library with
the higher-level features that would make this problem easy, so I had to
build out the “path to point” logic myself based on the svg
crate. I was able to get by with just line segments for now by doing
some manual path management in Inkscape (mainly subdividing and
straightening). I also used this tool to debug my
code and convert to absolute coordinates. These last bits kind of break
my intention of doing everything with command line tools, but at least
in principle I could work towards that with my new tool in the
future.
The code is here.
The tool is called svg-kerf
, and it reads and writes on
stdin
/stdout
for maximum pipe-ability.
For now, the code is good enough to work with the above SVG as input,
producing chunkier versions of the same paths that (I think) are ready
to be sent to svg2gcode
. Next time around I’ll try to get
the artwork done and then use the rest of the time to make improvements
to the svg-kerf
code.