1  Introduction

Machine building is a core competency for an industrial society, and is becoming increasingly democratized. For decades, manufacturers have used digital fabrication1 to build products in large and small volumes. More recently even small engineering firms are using machines to prototype designs in house, build automation equipment and tooling, and to perform process-specific tasks and tests. Alongside these engineers we find scientists, (Subbaraman et al. 2024) (Politi et al. 2023), STEM educators (Gershenfeld 2012) (Blikstein 2013) (Jacobs and Peek 2020), craftspeople (Rutter and Gershenfeld 2022), and autodidacts who all use (and develop) machines to learn - about our world, about maths and artistry, and about their ability to change the world while participating in our material economy.

Figure 1.1: Machine systems that were originally developed to toil in factories are escaping: we find them now in the classroom, the laboratory, and in small prototyping firms. In each of these contexts we need controllers developed for flexibility, adaptability, and inspectability.

It is not surprising that engineers might develop and deploy machinery, but our scientists, educators etc belong to groups whose main concern is not the machines themselves - these people’s heads are already filled with other (important!) knowledge. Understanding their tools should not require that they give up an exceptional amount of that valuable headroom.

Even large manufacturing firms need their machines to be easier to use: some half a million manufacturing jobs were unfilled in the USA in 2025 (NPR Planet Money 2025) (Bureau of Labor Statistics 2025) and thirty thousand in Canada (Statistics Canada 2025)2, largely due to a gap in the availability of skilled workers. These valuable jobs (Labrunie, Lopez-Gomez, and Minshall 2025) often involve the operation and use of digital fabrication machines. Aspirationally, they involve machine development as well as use: MIT studies have found that factory workers were hopeful about automation that allows them to do more complex tasks (Armstrong et al. 2024), and that flexible manufacturing (which involves rapid re-tooling of equipment) is of key importance if we want to bring manufacturing back to the west, where automation has been poorly adopted (Armstrong and Shah 2023) (Berger and Armstrong 2022).

This motivates the central question in this thesis: how can we make the making, maintenance and use of machines simpler? In particular, I am interested in replacing a pervasive and opaque representation of machine control (GCode) with more interpretible and extensible representations that are intuitive (based on physics) and authored in an inspectable, easily modified systems architecture.

This thesis also aims to provide value for folks for whom machine design and control is the main activity. Tooling for machine builders is notoriously proprietary - even large firms like Fanuc, Haas or Robodrill contract the controls for their machine to other firms like Siemens and Heidenhain, whose algorithms are kept close to the chest (Landau-Taylor and Dixon-Luinenburg 2020). This is despite the fact that almost every machine, before it can become excellent, must first master the simple task of moving around well - quickly, precisely, efficiently, and smoothly. If state-of-the-art design patterns for these core competencies were more broadly understood and easier to implement and extend, we may be able to help advance innovation worldwide.

Machine control is a task that I and many of my peers have found to be surprisingly nuanced; it runs us through a gauntlet of topics from power electronics and current control through time, space and frequency domains and into model predictive control, dynamic programming and nonlinear optimization. Mostly, people wade into these problems after having designed some hardware that they want to control - only to find the task riddled with “gotchas” and “traps for young players.”3

Besides my own colleagues and friends who I have worked with on machine building, I have been able to meet many small (and large) companies who are developing new machines i.e. for composite fiber layup, novel additive manufacturing processes, hydraulic valve tuning, medical device manufacturing, etc. Each of them has had to rebuild a controls stack internally, especially in cases where motion controllers must be tightly coupled to process controllers. If nothing else, I hope that this thesis can serve as a guide through these tasks, towards a world where building machines is more like building software - i.e. where we can find very good solutions to common problems available in the commons, and easily yoke them to our particular applications.

1.1 A Small GCode Primer

Understanding how GCode works, what niche it fills, why we might want to replace it (and why it is so pervasive) is important background for this thesis. To that end, let’s look at a basic GCode “program4” that, for example, cuts a square out of a piece of stock using a router (a subtractive tool).

Listing 1.1: An example GCode program that cuts a small square from a 1/8” piece of stock using a CNC Router.
L01   G21                   ; use millimeters 
L02   G28                   ; run the homing routine 
L03   G92 X110 Y120 Z30     ; set current position to (110, 120, 30)
L04 
L05   G0  X10 Y10 Z10 F6000 ; "rapid" in *units per minute* 
L06 
L07   M3  S5000             ; turn the spindle on, at 5000 RPM 
L08 
L09   G1  Z-3.5 F600        ; plunge from (10, 10, 10) to (10, 10, -3.5) 
L10   G1  X20               ; draw a square, go to the right,
L11   G1  Y20               ; go backwards 10mm 
L12   G1  X10               ; go to the left 10mm 
L13   G1  Y10               ; go forwards 10mm 
L14   G1  Z10               ; go up to Z10, exiting the material 
L15 
L16   M5                    ; stop the spindle 
L17   G0  X110 Y120 Z30     ; return to the position after homing (at 6000) 

The actions (if properly configured) of the GCode snippet from Listing 1.1.

GCode was developed around the same time as programming languages, compilers, and instruction sets: in computer science we call these “layers of abstraction” and they help us to build complex things without worrying about the particulars. Programming languages allow software engineers to write algorithms without manually writing out machine instructions (Parnas 1972), and compilers rely on static instruction set architectures (ISAs) to generate low-level codes without concern for how they are actually implemented in hardware (see Figure 1.4). GCode was meant to take the same place in machines, allowing machine programmers (formerly machinists) to develop manufacturing routines that could be deployed on variable hardware (Noble 1984).

Figure 1.2: The first computer-controlled CNC machine, the ‘whirlwind,’ was developed at MIT around the same time that programming languages and compilers were being invented

This probably seemed like a good idea at the time, but it is stymied by two important facts. Firstly, while there are only a few ISAs for compilers to contend with (and even then, a real homogeneity around x86, ARM and now RISC-V5 in practice), there are perhaps tens of thousands of unique GCode interpreters each with a unique “flavor” of GCode. I diagram this relationship in Figure 1.4. For example, in line 10 above, we tell the machine G1 X20 (move the X axis 20mm to the right (from its previous position established in L05)), but it is impossible to know from the code alone which motor (or combination of motors) is actually going to execute this move; there is a system configuration that is hidden from us that is unique to the individual machine. This seems like a simple problem (simply write down the configurations, right?) but is a major hurdle for companies like AutoDesk, whose CAM software (Computer Aided Manufacturing, see Section 1.2) must interface to many machines, and needs to know exactly how (for example) the X axis moves relative to the rest of the machine in order to simulate collisions and show the user what their program will do. This is even more difficult with advanced machines like mill/turn machines6 where most users result to programming jobs manually (i.e. bypassing CAM software) - a clear failure of what is meant to be a low-level layer.

Figure 1.3: GCodes are written by upstream softwares known as CAM tool (for Computer Aided Manufacturing). In the 3D printing world, these tools are known as “slicers” since they typically process parts layer-by-layer. Since there is no feedback from machines to CAM tools, they must be carefully configured by machine users in order for the whole process to work. This works reasonably well when machines or materials don’t change very often, but makes it is difficult to debug when things go wrong (since parameters aren’t related to any real physics) and it presents a challenge when new materials or machines are developed. CNC Milling Machines, where multiple cutting tools are used on any given job, configuring CAM parameters is a full-time job because each new tool requires careful consideration.
Figure 1.4: Here I diagram the common set of computer architecture abstractions… to compare to GCode’s implementation.

Secondly, physical processes themselves are also heterogeneous: even if we run the same job on a machine thousands of time, each is bound to be different: cutting tools wear out, incoming stocks are of slightly different sizes and compositions, external factors like heat soak and ambient air temperature all change. Whereas computer science goes to great lengths to ensure the homogeneity of the lowest layers of its stack (the implementation of ISAs), it is simply not possible in manufacturing to do the same. All the while, GCode provides no recourse to use real-time information in the execution of manufacturing plans, i.e. it is entirely feed forward: if we want to describe an algorithm that controls a machine intelligently based on physical measurements, GCodes are simply not an option.

GCode also contains a mixture of simple instructions like G1 (goto position) alongside larger subprograms like G28, a homing routine that may involve coordination of many of the machine’s components. If we want to interrogate what G28 is actually going to do (i.e. to see which axis is going to move first), there is no way to inspect “one layer down” from the G28 that is blankly staring at us. Later on in Section 1.5.1.2, I articulate how the contributions in this thesis transform the opaque GCode above into an inspectable set of programming tools.

1.2 A Small CAM Primer

While GCodes can be written by hand, they are most often generated using CAM tools (for Computer Aided Manufacturing). When someone learns how to make things with digital fabrication, much of their effort is devoted to learning how to use CAM softwares. CNC Machining CAM is notoriously difficult, whereas 3D Printing CAM tools (known as slicers) are much easier (this is one of the main reasons that 3D Printing has become so ubiquitous). Each has its own quirks, but follow a similar pattern: a 3D file is imported and positioned in a virtual work volume, and then various parameters are configured such that the software can generate a path plan (which will become GCode) for the selected machine. Figure 7.2 and Figure 8.2 give examples of printing and milling parameter sets respectively. For a longer discussion of each, see Section 7.1 and Section 8.1.

For now the main issue to point out is that CAM tools are disconnected from the machines that they write instructions for. Again, see Figure 1.4. GCode does not afford a pipe that can send data from the machine into CAM. Neither are the parameters that users set in CAM related to physical models of the process: success in printing is related to filament flow and cooling, but in a slicer we tune layer height and print speed (which are only indirectly related). Machining tools are limited by stiffnesses, cutting forces and vibrations: in CAM tools we set feedrates and spindle speeds - again, indirectly related.

1.3 Machines are Thoughtless

So we come to the core of the problem in the state of the art, which is that digital fabrication equipment does not think about what it is doing, nor can it tell a user what it is capable of, anticipate errors that may arise from a particular program, or be easily re-configured to do a task that its original programmers did not imagine. This is essentially due to the disconnect between CAM tools, where users program their machines, and machine controllers, where instructions are carried out. When mismatches arise between CAM outputs and real conditions they simply fail. For all of its advance, most digital fabrication seems about as sophisticated as the injket printing we are all familiar with: sometimes straightforward and unsurprising, or else error prone and frustrating, but never enlightening.

Most of the world’s 3D Printers and CNC Milling machines’ realtime controllers know very little about what they are doing, they simply consume and execute series’ of low-level instructions called GCodes. Those codes are generated in software that knows little about the machine (and has no way to verify what it does know).

For example, a CNC Milling Machine itself has no ‘knowledge’ of the physics of metal cutting, chip formation (see Figure 8.1) or structural resonances even though these physics govern how we might whittle a block of aluminum down into the desired shape. In the same way, a 3D printer knows nothing of the rheology involved in heating, squeezing and carefully depositing layers of plastics in order to incrementally build 3D parts (see Figure 7.1). It is difficult to say whether any computer system has ‘knowledge’ of anything; in this case I mean that our machines do not use any information about the material physics (and very little about their own physics) they are working with while they operate7.

In order to operate succesfully, machines need to have some understanding of these physics embedded into the low-level instructions they do receive, but those are developed in CAM tools that only encode them as heuristics and as abstract parameters that don’t have direct correlations to process physics. This poses a problem for machine builders (who need to carefully tune their motion systems) and machine users (who need to intuitively tune a slew of CAM parameters). It also means that many machines do not operate near their real world optimal limits (since hand-tuned parameters tend to leave considerable safety margins), leaving some performance on the table. Finally, it prevents us from learning from our machines: where the limits are, where we are operating with respect to those limits, and how we might best change our machines or our approaches in order to do better.

1.4 Machines are Poorly Represented

The technical root of this non-thinking issue is perhaps best articulated like this: machine controllers and users don’t have good representations of the machines that they are meant to operate. They don’t know what they are, let alone what they are doing. A slightly more precise way to say this is that machine representations are lossy - they are misaligned with reality, and difficult to correct.

I discussed one aspect of this problem already: when we issue a code to G1 X100 (move the x axis 100 units), we need our mental model of the machine (which axis is “X”) to align with the controller’s model (and wiring diagram). This level of the problem is just configuration. In the state of the art, this configuration is setup in the machine’s firmware8, which is difficult to inspect and edit. These “hidden states” cause all manner of headaches for educators, hobbyists, and scientists who want to re-purpose off-the-shelf controllers for their own inventions, especially if their machines deploy nonlinear or novel kinematics. One common result of this problem is to find machines in the wild whose controllers are convinced that they are a 3D Printer when in reality they are i.e. a gel extruder (Dávila et al. 2022) or a liquid handling robot (Mendez and Corthey 2022), or cases where authors have had to develop their own adhoc control systems (rather than re-using available designs) (Dettinger et al. 2022) (Florian 2020).

Figure 1.5: In this thesis I develop computational representations of machines that let us simulate them in software. This frame shows a 3D Printer (left) and it’s digital twin (center, top), alongside time-series data (right) of key process variables.

What a machine builder normally wants is a computational representation of their machine that is aligned with reality - this is half semantic alignment (any axis can be named “X” if we declare it to be, but our CAM and Controller should agree on the declaration) and half tuning and model fitting (how are the kinematics arranged, how much torque is available, and what happens if we apply some amount of it over the course of one second?). With a complete computational representation of our machines, we would be able to simulate and visualize them in software to learn what they might do given certain instructions. The danger in this approach is that the simulation is misaligned with reality - remember how no two machines are truly the same - and this is why this thesis focuses on using in situ instrumentation to build the models used to represent machines: i.e. we use the machine to build models of itself.

1.4.1 The Hidden Optimization

Before I describe the efforts I have made to ameliorate some of these problems, I want to look at one of the very particularly lossy components of the CAM/Controller system.

Expert CAM users know that process physics alone are not enough to intuit where a job’s parameters should be set. The machine’s own physics also present constraints in the form of actuator limits: the velocity of a moving mass cannot change instantaneously, as doing so would generate infinitely large forces \((F=MA)\)! To counter this, controller firmwares perform an optimization on the instructions they are given so as to avoid issuing instructions to the hardware that would be impossible to achieve: instantaneous changes in speed and direction, or instantaneous changes to i.e. flowrates and spindle speeds are smoothed out dynamically. However, these changes modify process parameters. If we slow the printer down, we also need to slow down extrusion rate, and if we cannot extrude fast enough to produce a track of a given width, we need to slow the printer down. In CNC machining, when we slow the machine down without changing the spindle speed, we change the size of the chip that the tool cuts (again, see Section 7.1 and Section 8.1 for a lengthier discussion on both).

Figure 1.6: Machine controllers perform a real-time optimization of the speeds and feeds that are requested of them in GCode files. This optimization is effectivley a speed scaling that prevents excessive loads on the machines’ structure and motors according to pre-configured limits to acceleration and velocity. This figure shows velocity over time for the GCodes generated by a CAM tool, vs. the actually realized speeds as adjusted by the machine’s controller.
With 100mm/sec Feedrate With 500mm/sec Feedrate
Figure 1.7: Here I show the result of two print layers that have been optimized by a machine’s firmware. In both cases, acceleration is limited to \(1000mm/s^2\). At the left, we target \(100mm/s\) and on the right, \(500mm/s\). The histograms (top row) render the actual velocity distributions of each job.

In the figure above, I show the actual feedrates realized by a classical motion solver (using trapezoids) for two target velocities (\(100\) and \(500 mm/s\)). We would expect that the second is five times faster, but in reality it is only 14% faster because the solver’s maximum acceleration is limited to \(1000mm/s^2\) in both cases. This is a simple example of what I mean by a lossy layer, or a bad machine representation: the parameters that we set in any given CAM tool may not be realized in practice, something that has stymied other authors as they develop optimizations for milling machines (Lavernhe, Tournier, and Lartigue 2008).

1.5 Key Goals and Contributions in this Thesis

By now we can tell that getting a machine to operate successfully requires machine users to implicitly understand process physics and machine physics, but also to understand how parameters will translate into real-world operation through a set of hidden control and configuration steps. The broad goal of this thesis is to take these scattered, misaligned machine representations and collect them together into comprehensive and comprehendible computational representations. Doing so will let us operate our machines more effectively, reduce the parameter space that requires trial-and-error tuning, help us to rapidly build new machines and teach us about those that already exist, and enable us to connect them to smarter control algorithms.

Figure 1.8: This figure shows a systems-level view of major components in this thesis. OSAP Chapter 2 and Pipes Chapter 3 are systems architecture tools I developed, together with MAXL Chapter 5, they let us replace GCode with software. I then developed a series of machine models and controllers that let us refactor machine control as an online optimization.

The ambition here is large: machine control is an old field that represents many years of collective effort, and I am proposing to replace some of its core assumptions. This is possible now largely due to the ever increasing ubiquity of computing: the compute power we can now buy for less than one dollar outstrips what was available at an institutional level when GCode was first developed. This new availability, alongside years of my colleagues’ work, leads to a handful of new contributions that I have been able to make.

1.5.1 Design Patterns for Distributed Machine Control

In the simplest sense, GCode just a way to communicate with machines. Our main frustration with it is that it splits our computational representation of machines: we have components of our workflows above and below GCode, but these are not connected. So our first key goal is to develop a systems architecture that lets us connect software components in the realtime “control” domain with the higher level “planning and tasking” domain. Taking a cue from software design, we also want to build these larger systems from a reuseable set of components (motor drivers, sensors, control software, planning software etc). The main challenge in this domain is to develop an architecture that is descriptive and broad enough to include all of the required parts, but that does not introduce an amount of computing overhead that would prevent us from doing performant, realtime control.

1.5.1.1 Flexible Networking and Discovery Services

Years of work at the CBA have gone into making machine controllers more inspectable and reconfigurable, most notably in Nadya Peek and Ilan Moyer’s theses (Peek 2016), (Moyer 2013). These both developed the idea of “virtualization” - where we represent machines as software objects to enable rapid reconfiguration of modular hardware via programming in high level languages. This core idea to build object oriented hardware is crucial to my work: if we take machine systems as collections of hardware and software and then turn the hardware into software, our systems assembly, reconfiguration and inspection tasks can all be handled in code. This idea is completely familiar to software developers but remains (somewhat) novel in the development of new hardware. Nadya and Ilan’s work is proceeded by work at the CBA on “small” inter-networking architectures (we need to connect to hardware modules before they can be virtualized), most notably my advisor Neil’s early work on the Internet of Things (Gershenfeld, Krikorian, and Cohen (2004)) which, of course, is surrounded by decades of work on computer networks.

On top of this design pattern I have added a few new capabilities. The first is to write a lightweight networking stack that generalizes across heterogeneous link layers, a-la the OSI model (Standardization (1994)). Earlier work was mostly developed on a specific serial bus called “fabnet;” in my network code (OSAP, Chapter 2) I build out a layered approach that lets us use “almost any” physical link layer - this lets us build machines across a mixture of links. As I discuss in that section, this is useful because machine systems normally use more bespoke networking: we want different protocols, connectors (etc) depending on each individual machines’ context and application. Most “other networks” (i.e. the internet) are built with more homogenous networking technologies.

The broad strokes of the networking I use are based on a scheme that Neil has developed (but not published!) called “Asynchronous Packet Autonoma” where packets use source routing (Sunshine (1977)) rather than fixed addresses. To this scheme I add a discovery routine that effectively serves as a “distributed DNS” (Domain Name Service) (Section 2.5.1). This helps us to “plug and play” - i.e. add new devices to our network and put them to work without having to manually update registries, addresses, etc.

OSAP also implements a simple time synchronization algorithm (Section 2.5.2) that gets everyone’s clocks lined up. There are multiple time sync protocols in use on the internet today, namely Network Time Protocol (NTP, Mills (1991)) and it’s fancy descendent, Precision Time Protocol (Eidson, Fischer, and White (2002)). I chose to develop my own because the state-of-the-art approaches are somewhat complex (being designed by committee to serve very many use cases), whereas the devices we are concerned with in machine control are often resource constrained: simplicity is best. Adding time sync was invaluable in my work: it lets us coordinate motion with ease, and make precise models of machines across modular sensing elements. It is also, for sure, nifty as hell.

1.5.1.2 Replacing CAM, GCode and Control with a Software Stack

Whereas the contributions I just discussed are mostly concerned with connecting to machines, PIPES (for Piped Interconnect for Physical and Experimental Systems, Chapter 3) is the layer where we make semantic meaning out of those connections… i.e. it is where we do the programming.

Pipes is my solution to the “high level” / “low level” split that I mentioned earlier; i.e. we want to represent, modify, and task our systems in high level languages, but the most important parts of the machine controller can’t run in these high level languages because they are too slow, and are burdened by non-determinism (i.e. shakiness)9. Pipes overcomes this gap by combining dataflow programming (where functions are connected to one another with… pipes) with traditional programming and scripting where complex, multi-step and stateful tasks are easier to describe.

To build systems, Pipes first takes arbitrary functions from any given device or program and rolls them up into software objects that I creatively call Pipes Functions (Section 3.1). These are Remote Procedure Calls (RPCs) that can be operated from any other device in the system (a common design pattern from distributed computing). They are also dataflow blocks: their outputs (return values) can be connected to other functions’ inputs (arguments). To boot, they are automatically generated from source code (easing the burden on component developers) and can be remotely discovered (easing the burden on systems integrators) (Section 3.1.1).

Configuration of realtime, continuous-operation machine components, we use dataflow. I use dataflow because it is a computational representation that easily spans multiple devices and processes (a topic I started developing in my master’s thesis (Read 2020)), it can be executed quickly in simple hardware, and it can be well represented at a high level (with a graph). For example, we can pipe the output from an encoder module to the input of a servo motor’s control block - and setup a timer to trigger that encoder sampling. The motion controllers that I developed are configured in this way, combining flows of position streams through functional blocks to i.e. assemble kinematic chains (Section 5.3.2). Sensor data streams are piped up into data loggers to enable model building (Section 6.1, Section 6.2, Section 6.3, Section 7.3). Pipes’ dataflow configuration also enabled me to integrate the high performance compute required for optimization based motion planning (Section 6.4.3).

Dataflow doesn’t work well to describe complex, conditional tasks for machines. Instructions at a high level are typically sequential in nature: do this, then do that if (condition), otherwise (do something else). They are also stateful: we need to track what the machine has done previously, what it should do next, etc. Traditional programming is great for all of this: we basically just write scripts to describe tasks. To connect those scripts to our realtime systems, we can use Pipes’ RPC functionality to remotely trigger components of the dataflow graphs. A key note is that dataflow configurations can also be read and reconfigured in software, so i.e. most of the codes I use to learn from and control machines in this thesis start with an initialization script that reconfigures the machine for whichever task it is going to do, and then operates that dataflow graph using RPC calls10.

In Section 3.2, I show what it looks like when we roll this all together: dataflow configuration, and scripting-based tasking / operation. The end result is that we effectively replace GCode (an obscure ‘language’) with… python, an incredibly common programming language. I can imagine that this may upset readers who are already familiar with GCode’s ins-and-outs, but I would like to make a few counter-points: (1) if we were to randomly sample the world’s population, more individuals would be familiar with python than with GCode, (2) learning (some) python is about as difficult as learning GCode, maybe easier, (3) python-based codes can be authored so that they are semantically meaningful (i.e. machine.goto(x, y, z) is more descriptive than G1 <X>, <Y>, <Z> - or (even better) machine.spindle.set_rpm(5000, 'clockwise') vs. M03 S5000), and finally (4) our representation lets users discover (and modify!) the machine’s operation one layer down from the codes they are authoring (if they wish).

1.5.2 Using Models to Combine Motion and Process Planning

Earlier I was discussing how machine operation is limited by real-world constraints: motors produce limited torque, structures deflect with load, polymer extrusion is limited by fluid (and thermal!) dynamics, cutting forces are limited by tool and part stiffnesses, etc. Implicit to CAM programming is that users should setup parameters such that their GCodes don’t require the machine to violate these constraints, and explicit in machine firmwares is the velocity scaling Section 1.4.1 that prevents the machine from violating it’s kinematic constraints. I also explained how these two sets of constraints are coupled: if we change machine velocity, we change cutting or flow parameters implicitly.

Rather than solving these problems in disconnected steps a-la the state of the art, in this thesis I bring them together into one optimization code that works to maximize machine performance against both sets of constraints.

This happens in a few steps. First, I model my actuator of choice (the humble stepper motor, Section 6.1). I also develop a fancy stepper motor driver (Section 6.1.1) that can fit its own models. I model machine kinematics, inertial and damping terms (Section 6.2), and vibrations (Section 6.3) - and fit them to data generated on machine. This covers models for motion.

I then develop an controller that selects toolpath velocities: it maximizes speeds while respecting actuator and kinematic constraints. (Section 6.4.3). Doing this with high fidelity models for motion is computationally expensive; I lean on a set of tools that have been recently developed for parallel computing on the GPU to develop the controller. In doing so, our higher fidelity models let us achieve larger overall velocities than are generated by classical controllers which use simpler heuristics.

Because this controller is optimization based, we can add constraints without fundamentally modifying its structure. I use this pattern to add process models. In Chapter 7 I go through the rigamarol required to make sense of melt flow dynamics in Fused Filament Fabrication (FFF, i.e. plastics 3D printing), and of (surprisingly, simpler) cutting force dynamics in CNC machining (Section 8.3). Using these models, I develop a print controller that governs both flow constraints and motion constraints (Section 7.5), and a machining controller that governs deflection, tool breakage, and motion constraints (Section 8.4).

These solvers accomplish a few things. (1) We can program machines by articulate ideal outcomes and constraints, rather than hand-tuning parameters (replacing guesswork with model building). (2) They enable us to operate machines optimally - i.e. faster and better (closer to their actual limits, rather than the limits we could find by-hand without breaking things). (3) They can teach machine users and designers about their equipment. I explore these results in Section 7.6.3 and Section 8.6.

1.5.3 Replacing Process Parameter Selection with Model Building and Optimization

While the real-time controller can automatically prevent us from giving our machines instructions that would be infeasible, it does not extend far enough to completely encode our machine operation. For example in FFF, where our models describe flow constraints across a range of temperatures, we still need to pick a particular temperature to use during operation. We also need to look at longer-term effects like part cooling, and tune some other heuristics: the overall quality of our motion is determined by our speed and acceleration choices. Basically, while optimization based solving can help us most of the way, we still need a few heuristics.

Luckily, we can pull these heuristics out of our models. In Section 7.4, I develop one strategy for doing so. A particularely noteable result from that section is that our system successfully picks larger flow temperatures for large prints (greatly improving speed), while using lower temperatures for small prints (where print cooling limits total speed).

Because we pick these extra heuristics out of models, we don’t need to re-tune them across material changes. This lets us reduce the overall size of the parameter space that machine users need to tune, as I explain in Section 7.6.2. This also expands the set of materials we can use on our FFF printers by removing most of the trial-and-error steps, as I show in Section 7.6.

1.5.4 Continuous Learning with Computational Metrology

Lastly I want to note that across all of these topics, the machine is learning about itself - as in, we use hardware embedded in the machines to measure motion and process models. This is a key differentiation from lots of other work, where tests are often performed on specialized measurement equipment, reduced to models, and then deployed on “end-user” hardware. Combining our operating equipment with our measurement equipment sometimes requires that we do extra modeling steps (i.e. using models of motors themselves to measure forces), or include extra hardware (i.e. loadcells, thermistors, accelerometers). But we now live in a world where these expenses are slim, computing is cheap, and the advantage of using in-situ measurements means that we can skip the steps where we carefully calibrate our machines against external, often very expensive and purpose built measurement machinery.

References

Armstrong, Ben, Valerie K Chen, Alex Cuellar, Alexandra Forsey-Smerek, and Julie A Shah. 2024. “Automation from the Worker’s Perspective.” arXiv Preprint arXiv:2409.20387.
Armstrong, Ben, and Julie Shah. 2023. “A Smarter Strategy for Using Robots.” Harvard Business Review 101 (3-4): 35–42.
Berger, Suzanne, and Benjamin Armstrong. 2022. “The Puzzle of the Missing Robots.”
Blikstein, Paulo. 2013. “Digital Fabrication and Making in Education: The Democratization of Invention.”
Bureau of Labor Statistics. 2025. “Manufacturing: NAICS 31-33.” U.S. Bureau of Labor Statistics. 2025. https://www.bls.gov/iag/tgs/iag31-33.htm.
Dávila, José Luis, Bruna Maria Manzini, Marcos Akira d’Ávila, and Jorge Vicente Lopes da Silva. 2022. “Open-Source Syringe Extrusion Head for Shear-Thinning Materials 3D Printing.” Rapid Prototyping Journal 28 (8): 1452–61. https://doi.org/10.1108/RPJ-09-2021-0245.
Dettinger, Philip, Tobias Kull, Geethika Arekatla, Nouraiz Ahmed, Yang Zhang, Florin Schneiter, Arne Wehling, et al. 2022. “Open-Source Personal Pipetting Robots with Live-Cell Incubation and Microscopy Compatibility.” Nature Communications 13 (1): 2999. https://doi.org/10.1038/s41467-022-30643-7.
Eidson, John C, Mike Fischer, and Joe White. 2002. “IEEE-1588™ Standard for a Precision Clock Synchronization Protocol for Networked Measurement and Control Systems.” In Proceedings of the 34th Annual Precise Time and Time Interval Systems and Applications Meeting, 243–54.
Florian, David. 2020. “OTTO Liquid Handling Robot.” https://openliquidhandler.com/.
Gershenfeld, Neil. 2012. “How to Make Almost Anything: The Digital Fabrication Revolution.” Foreign Aff. 91: 43.
Gershenfeld, Neil, Raffi Krikorian, and Danny Cohen. 2004. “The Internet of Things.” Scientific American 291 (4): 76–81.
Jacobs, Jennifer, and Nadya Peek. 2020. “Learning Remotely, Making Locally: Remote Digital Fabrication Instruction During a Pandemic.” ACM [Online].
Labrunie, Mateus, Carlos Lopez-Gomez, and Tim Minshall. 2025. “Manufacturing Remains a Core Driver of Economic Growth.” The Economist, July. https://www.economist.com/letters/2025/07/03/manufacturing-remains-a-core-driver-of-economic-growth.
Landau-Taylor, B, and O Dixon-Luinenburg. 2020. “Machine Tools: A Case Study in Advanced Manufacturing Industrial Economics.” BISMARCK 2: 1–18. https://www.bismarckanalysis.com/Machine_Tools_Case_Study.pdf.
Lavernhe, Sylvain, Christophe Tournier, and Claire Lartigue. 2008. “Optimization of 5-Axis High-Speed Machining Using a Surface Based Approach.” Computer-Aided Design 40 (10-11): 1015–23.
Mendez, Nicolas A., and Gaston Corthey. 2022. https://gitlab.com/pipettin-bot/pipettin-bot.
Mills, David L. 1991. “Internet Time Synchronization: The Network Time Protocol.” IEEE Transactions on Communications 39 (10): 1482–93.
Moyer, Ilan Ellison. 2013. “A Gestalt Framework for Virtual Machine Control of Automated Tools.” PhD thesis, Massachusetts Institute of Technology.
Noble, David F. 1984. Forces of Production: A Social History of Industrial Automation. Routledge.
NPR Planet Money. 2025. “Why Aren’t Americans Filling the Manufacturing Jobs We Already Have?” NPR. May 13, 2025. https://www.npr.org/sections/planet-money/2025/05/13/g-s1-66112/why-arent-americans-filling-the-manufacturing-jobs-we-already-have.
Parnas, D L. 1972. “On the Criteria To Be Used in Decomposing Systems into Modules 15 (12): 6.
Peek, Nadya. 2016. “Making Machines That Make: Object-Oriented Hardware Meets Object-Oriented Software.” PhD thesis, Massachusetts Institute of Technology.
Politi, Maria, Fabio Baum, Kiran Vaddi, Edwin Antonio, Joshua Vasquez, Brittany P Bishop, Nadya Peek, Vincent C Holmberg, and Lilo D Pozzo. 2023. “A High-Throughput Workflow for the Synthesis of CdSe Nanocrystals Using a Sonochemical Materials Acceleration Platform.” Digital Discovery 2 (4): 1042–57.
Read, Jake Robert. 2020. “Distributed Dataflow Machine Controllers.” PhD thesis, Massachusetts Institute of Technology.
Rutter, James, and Neil Gershenfeld. 2022. “Haystack Labs.” https://www.haystack-mtn.org/haystack-labs.
Standardization, International Organization for. 1994. Information Technology—Open Systems Interconnection—Basic Reference Model: The Basic Model. ISO/IEC 7498-1:1994. Geneva, Switzerland: ISO/IEC. https://www.iso.org/standard/20269.html.
Statistics Canada. 2025. “Job Vacancies, Payroll Employees, and Job Vacancy Rate by Industry Sector, Monthly, Adjusted for Seasonality.” Statistics Canada. October 30, 2025. https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1410040601.
Subbaraman, Blair, Orlando de Lange, Sam Ferguson, and Nadya Peek. 2024. “The Duckbot: A System for Automated Imaging and Manipulation of Duckweed.” Plos One 19 (1): e0296717.
Sunshine, Carl A. 1977. “Source Routing in Computer Networks.” ACM SIGCOMM Computer Communication Review 7 (1): 29–33.

  1. In this thesis, I will take Digital Fabrication Equipment to mean CNC Machines, 3D Printers or other direct-write fabrication equipment (not including automation equipment more broadly).↩︎

  2. That’s about 0.14 unfilled manufacturing jobs per capita for the USA, and 0.07 in Canada.↩︎

  3. A “trap for young players” is a term of art for surprising or non-intuitive design patterns, issues, or strategies that are commonly known to initiates in the dark arts, but cause issues for newcomers. As coined by the venerable Dave Jones at the EEVblog youtube channel.↩︎

  4. A GCode “program” is perhaps not actually a “program” since GCodes are (often) not turing-complete, i.e. they are more just a series of operations, rather than a proper computing language. We can fix this.↩︎

  5. Instruction Set Architectures encode the lowest level operations that a given computing device can execute: add, compare, move, etc. x86 (originally developed by Intel) runs most PC’s and was basically the market dominant until ARM (developed in Cambridge, UK and licensed worldwide) arrived, which offers a simpler set of instructions and is favourable in low-power devices. As it turns out, simpler ISAs are preferred in modern designs because they are more deterministic and easier to predict: instructions complex ISAs like x86 can take more than one clock cycle to complete, for example, which makes compiler-level optimizations more difficult to articulate. The new trend is towards RISC-V (Reduced Instruction Set Computer, 5th Generation), which is open source and even simpler than ARM.↩︎

  6. Mill/Turn machines are many-machines-in-one: they can operate as a lathe (“turn”) or a CNC mill, and they commonly mix modes. Often they have up to 12 axes, each of which can collide with others depending on configuration, tooling which is installed, and of course the work piece.↩︎

  7. Where state-of-the-art machines do use sensing and feedback it is normally relegated to one subsystem: for example most industrial machines have encoders for positional feedback on each axis, and some high-precision equipment measures temperature along each axis - but these are used in the subsystem that positions that respective axis. In this thesis, I try to close a longer loop across the machines’ global control controller, using matched computational models of the whole system (process and motion).↩︎

  8. We call the low-level computer codes that run on micrcontrollers ‘Firmware’ - the name reflects the difficulty in changing it, and its closeness to hardware. Firmwares typically run on small computing environments (which today means MHz and MBs), vs. Software which normally runs on i.e. a laptop, on top of an operating system. Firmwares are an important component in any hardware system, since they allow programmers to have tight control over their program’s timing. Operating systems and high-level language interpreters (on the other hand) sometimes interrupt program execution to switch threads or run garbage collection routines.↩︎

  9. Determinism is a measure of how sure we can be that something will happen in a certain manner. In programming, deterministic systems always use the same amount of resources (time and space) to complete. This is important in realtime systems: we need to know that (for example) a position control loop will take less time to run than the control interval, every time. High level languages are not deterministic, often simply because they run inside of operating systems, but also because they do things “behind the scenes” like run garbage collectors, etc.↩︎

  10. A topic that I didn’t have time to explore was the new capability for reflective programming that dataflow discovery opens up. As I mentioned, my scripts initialize by looking at the graph of hardware available to them, and then reconfiguring that graph. But we can also write scripts that modify themselves (or the system) depending on the resources they find available: for example if we find that our machine is configured with a laser cutting end effector, serve a UI appropriate for that task. This would be a kind of feedback programming - codes that look at codes.↩︎