Let’s talk about the Makelangelo Software, how it’s built, and what I’m doing to make it better. I hope we can continue this discussion in the forums.
The current version is 7.21.0 at the end of 2019. The top left is a What-you-see-is-what-you-get (WYSIWYG) preview. The top right are the creative controls, the connection to the robot, and the active controls (once connected). The bottom has status messages from the app and the dialog with the connected robot. The very bottom is a field to send commands to the connected robot. The entire bottom section can be (un)hidden with the arrows on the left.
A very special thanks to all of you who have downloaded the software, given great feedback, made pull requests, and those who have donated to help support its development. You give me the energy to keep making it better. Stay awesome!
When I built the first Makelangelo robot it understood gcode, a human-readable text format used by CNC machine like 3D printers and milling machines. I was typing one line of gcode to the robot at a time through the Arduino Serial GUI. Works great; doesn’t scale. I needed a tool to deliver the gcode one line at a time to the robot. Makelangelo software was born.
Later I added a GUI to get a WYSIWYG preview. The preview system would read in the gcode in the file and draw a picture. Every frame, up to 30 times a second.
I had an ugly way to turn a bitmap (like a photo or meme) into gcode. It was too hard! So I added some Converter classes into the app. Each converter would generate gcode, which was then treated as normal by the rest of the system. The app was still reading gcode every frame AND if you changed settings like “pen up angle” then the gcode had to be regenerated by the style system.
I need to segue for a moment here. The Makelangelo is a robot that only draws lines described with gcode. There are two ways in the software to make a set of lines that will get turned into gcode. One is with a Converter classes (which turn pictures into lines). Another is with a Generator class (which makes up lines based on algorithms, aka procedurally). Both of these classes are a type of Manipulator. Pure vector files like DXF and SVG are not really converted, but that’s a discussion for another time. My point is “Manipulator” is a word for both types of classes-that-make-lines.
Recently I’ve been cleaning up the mess with Manipulators. That means instead of writing gcode to a file, each Manipulator controls an instance of a Turtle, just like LOGO on the Commodore 64.
The turtle’s history remembers moves, pen up/down, and color changes. After the Manipulator is done moving the turtle, the turtle’s history is read and interpreted by a final stage that generates the gcode.
This method has many benefits:
- Drawing the Turtle history is much faster than re-interpreting the gcode every frame.
- A change to the robot settings means only the final step has to be run again to update the gcode.
- If the turtle moves with pen up many times, only the last step when the pen is lowered is written as gcode. That means less total gcode instructions.
- Optional middle steps can be added between the Manipulator stage and the final stage. Perhaps the lines will be scaled, rotated, flipped, or warped. Perhaps the lines will be cropped to fit in a weird outline.
- A middle step could look at the lines delivered by a turtle and try to reorganize them for faster drawing. This way the Manipulators wouldn’t have to optimize themselves, it could be handled by an expert middle step. There could be one optimizer that only reorganizes lines for efficiency, and another that merges short straight lines into one longer line, etc.
- Several Manipulator stages could be run and added together. A single gcode file could end up having multiple photos, each generated with a different style, each positioned differently. A CMYK file could be split into separate channels, converted once on each channel, and then put back together.
- Because the app is no longer re-reading the gcode every frame, it should be easier to display a subset of the preview. “show me only the first 30%. Show me only the last 200 commands. Show me only the magenta lines.” etc.
The art pipeline
Having made this change I now have a new perspective. Instead of seeing the trees – writing to a file, dealing with exceptions, reading it back in, and all the minutia about the contents of the file – now I see the forest called Turtle, and everything that is done to the Turtle before drawing is an art pipeline. Converters and generators both produce a Turtle from some (or zero) other data at the head of the pipeline. The middle steps take a Turtle, change it based on some other data, and then pass it to the next step. The tail of the pipeline saves the Turtle to a format you want.
- The pipeline should be locked while the robot is drawing live over serial.
- The pipeline process should be saved so that it can be repeated or shared.
- The pipeline should have any number of middle steps in any order.
- The pipeline must start with a head and end with a tail.
- All pipeline steps should show their parameters to the user, if any.
- All pipeline steps should do their work in an iterative way.
- All pipeline steps should show their work while they iterate, and provide a progress report (% remaining)
- The pipeline must be interruptible – it can be stopped or paused at any time.
- Changing a parameter in step N should visually show that steps >=N are now out of date. It is up to the user to stop the process and recalculate the pipeline. This way the user can change several parameters if they want.
- Pipeline steps may offer a “good enough” button.
- The pipeline steps should remember their work so that changing later steps does not automatically force recalculation of earlier steps.
One more thing
As a matter of convenience I am changing the drawing process so that all new drawings start with a “find home”. If your machine does not recognize the find home command, nothing changes. If your machine has find home, you don’t have to remember to do it yourself before starting a drawing. This more closely matches the behavior seen in 3D printers. Convenient!
The code can be found at https://github.com/MarginallyClever/Makelangelo-software. It is written in Java. There is a main branch for each release and a dev branch for unreleased maybe-broken current work.
The best way to contribute new code is to make a fork of the dev branch, make your changes, and then make a pull request. If you don’t know what those things are, please see this Github for Beginners tutorial.
If this has inspired you with new ideas or questions, please discuss it in the makelangelo forums.