TLDR: I’m re-writing the calibration system. It’s WAY better than any previous Maslow, but it’s not perfect yet.
Since we hit our goal I’ve been focusing on the only thing that I am at all worried about which is the automatic calibration process. Up until a few weeks ago I was using a genetic algorithms based approach which “evolved” the correct X,Y coordinates for each of the anchor points. Right before launching the kickstarter I was going through and vetting and checking everything and I realized that while it did a great job sometimes, genetic algorithms are non-deterministic because of simulating random mutations which meant that it didn’t always give a the same answer even given the same input measurements and it could be wrong. I decided that I wanted a deterministic solution (ie it will always give the same correct answer, given correct measurements) so I started re-writing it.
The new system is coming along well and I wanted to share my progress both for the sake of transparency and also because many eyes are better than two.
Here’s how the system works.
We start out with a series of measurements. These measurements are taken by moving the machine to some unknown point using the upper two belts the way the two chain Maslow moved, and then pulling the lower two belts tight. We don’t know the XY coordinates where each measurement was taken, we only know the lengths of all four belts at that point.
We have an initial guess for the XY coordinates of the anchor points, but it’s a random guess. No matter how bad that guess is we want the process to end with the right answer.
We then take those starting coordinates for the anchor points and “attach” each measurement to them then we find the setup that puts the end of each measurement as close together as possible. When we have found the correct solution each of the measurements will join at a single point, but for now they don’t meet.
Next we find the “center of mass” of each measurement (basically the center of each grouping of 4 dots) and compute how far each dot is from that grouping in X and Y. We then take the average of all of these and determine which corner we should move to make the most dots closer together and move that corner.
(A couple iterations later to show some progress)
The process then repeats until moving any anchor point in any direction will move the dots apart.
At this point we’ve found our anchor points.
This works very well on simulated data and always produces the correct result independent of what the starting guess is and it handles inaccuracy in the measurements well.
I showed it above with 9 measurements which is what I was initially using because it’s easier to see, but I’ve found in practice that more data is better so we are now using 110 data points which looks like this
(initially)
(solved)
One other note is that because we get to define our coordinate system we can declare that the lower left anchor point is (0,0) and the right anchor point is at (?,0) so we’re only actually solving for the top left X,Y, the top right X,Y and the lower right X.
How does it work in practice:
Pretty good, but not perfect yet. Running the calibration process twice on the same frame should give the same results, and while it gives close to the same results they aren’t identical. Two back to back runs yesterday produced
(-1.2775505926851451, 2125.411304076909), (3036.051941957454, 2127.91394620096)
(0, 0), (3041.4964766419607, 0)
and
(-1.639147982037378, 2128.4314646585512), (3033.2235866981528, 2131.949568552577)
(0, 0), (3038.5630396604274, 0)
Which are closer than I could measure by hand, but the goal is for them to be identical.
After running the first one I cut two 600mm test squares (one in the center of the sheet, and one at the far left of the sheet) and then measured them to be:
Left:
Width: 596.5
Height: 598.5
Center:
Width: 598.5
Height: 595.5
I think I may have accidentally forgotten to change to cut outside the line instead of on the line in Carbide Create (for some reason they have on the line as the default) which would give a target 600-(6.35/2) = 596.8mm in each dimension. Measuring across the tops of both squares with a straight edge I can’t see any bend.
It’s a heck of a lot better than the “my circles are ovals” type of issues we’ve had in the past, but the goal is ±.5mm across the whole sheet so we need to keep dialing it in.
What can we improve?
One of the thing which I discovered this week is that the order that the belts get pulled tight in matters sometimes. For example:
In this location if the right belt pulls tight before the left belt is taught the tension can be removed from the upper right belt leading to an inaccurate measurement.
Changing the system to always pull the left belt tight first on the left side of the sheet and the right belt tight first on the right side of the sheet made a big difference in improving repeatability.
Belt stretch is not currently taken into account, and while the belts are very low stretch, they aren’t zero stretch and I would like to factor that in.
How can you play with it before you have actual hardware? (by which point I intend to have perfected it)
I’ve written a simulator to mess around with the math. You can find it and sample data from test runs here: GitHub - BarbourSmith/Calibration-Simulation
It’s written in JavaScript so you don’t need to install anything, just download the files and double click on the index.html
file there to play with it.
I haven’t made it super user friendly yet (pull requests are welcome ) so if you want to see what is going on in the background you will need to open the console where it can print things out.
I’ll keep you updated on my progress, and answer any questions. I’m open to any and all ideas and suggestions.