repetier / Repetier-Firmware

Firmware for Arduino based RepRap 3D printer.
812 stars 734 forks source link

Heuristic delta calibration using simulated annealing #367

Open 626Pilot opened 9 years ago

626Pilot commented 9 years ago

Hello,

I had problems getting my Rostock MAX calibrated properly for years! I tried Marlin, Repetier firmware, and Smoothie, all of which have delta calibration routines, and none of which could produce a good result for me. So, I decided to write my own routine. Instead of using fuzzy logic like "if the effector is too high next to Z and too low opposite Z, adjust Z endstop," and so on, I used a machine learning algorithm called parallel simulated annealing. SA is used a lot in artificial intelligence, especially for machine vision and "travelling salesman"-type optimization problems. It's fairly easy to implement. More info is here: http://en.wikipedia.org/wiki/Simulated_annealing

After a few months, I had it all figured out, and my printer was printing across a wider footprint than it ever had before. I've had several other people test the firmware, and it has produced really good results for them, as well.

Code here: https://github.com/626Pilot/Smoothieware/blob/edge/src/modules/tools/zprobe/ComprehensiveDeltaStrategy.cpp Method is ComprehensiveDeltaStrategy::heuristic_calibration()

Discussion, with before+after on my printer (others got even better results), here: http://forum.seemecnc.com/viewtopic.php?f=82&t=7640

I developed all of this to run on Smoothieware, with the hope that others would port it to run on Arduino-based firmwares after I got all the hard math and logic figured out. It is very CPU-intensive, but it doesn't use recursion, so it should be possible to implement it in a memory-efficient way on Arduino firmware. I have already put this in front of Rich C for inclusion into Marlin, but I feel Repetier is easier to use (stores more stuff in EEPROM) so I think it would make sense to show the code to you as well. I think most people on the Rostock MAX are using Repetier, and I don't think they want to go back to Marlin just for this...

-HOW IT WORKS-

My algorithm manages 14 variables altogether: Arm length, delta radius, endstops, individual tower rotation and radius offsets, and print surface normal. The only thing I don't simulate yet, which I know to be a problem "in the wild," is tower lean. The algorithm starts by probing the bed in a grid, in order to gather a set of real-world depths in different locations. The goal is to use the firmware's built-in IK and FK functions to simulate a virtual printer, and to see what variables would have to be fed into that printer's config, to get the same results measured by the probe. The closer the simulated result to the measured result, the less "energy" in the system. We want the energy to be as close to 0 as possible, because if it's 0, we've found the exact real-world geometry of the printer! It works OK if you just give it endstops and delta radius. But the more variables you give it, the better a job it does. There is no fiddling with rules, or rules that work on one machine but not another, because there are no rules to begin with. It has access to simulate delta kinematics, but it doesn't understand all the tricky relations between settings. It only knows how to find what works, and get away from what doesn't.

For each variable, we use a binary search routine to find the best current setting for that variable across a range (for example, tower rotation offsets can vary by up to 3 degrees from default, so for the Z tower, it would search from 87 to 93 degrees). Once the best value is found, the variable's setting is "creeped" a random distance in the direction of the best setting.

Because each variable's simulation doesn't know what the others might do, there is some error in the result. However, by limiting the impact of that error by only letting the variable change a little each pass, and by making them compete in a random environment (each one can advance a random amount that changes each time), we allow better solutions to percolate to the top. The amount each variable can change per pass is controlled by "annealing temperature". This starts at a high value, and is slowly ratcheted down towards 0 pass after pass. This allows a broad search in the beginning, which slowly settles down to the finer search pattern needed to zero in on the optimal values. Each variable can have its own annealing temperature, but I usually just let them all use the default temperature, which I think is 0.35.

The algorithm can find its way out of local minima on the way to the global minimum, backing out of blind alleys if you will - the numbers can get better, then worse, then better still, as the algorithm wanders through some less optimal solutions on the way to the best one it can find.

I usually give the algorithm 50 passes. At the end of that, the settings are better than they were when it started. If I run it 3 or 4 times, it benefits from the improved starting point each time, allowing the end calibration to be better still. I've seen users gain access to lay down a first layer on much more of their print surface than they did before. I have had several people test this firmware, and it produces accuracy improvements of better than 100 microns in some cases.

This is an improvement over simple bilinear interpolation Z correction, because that only corrects Z - not X or Y. If you're printing pieces that have to fit with each other - sectional objects, gears, things that have to fit around bearings, etc. - that helps you get the first layer down, but they still come out screwy. Because on a delta printer, increasing the accuracy of Z also helps X and Y, this solution will take some of the error out of the XY plane. This is why I spent months working on it, rather than just throwing up my hands and settling on simple depth-map/bilinear interpolation. (My code DOES have separate logic that will use bilinear interpolation/extrapolation to correct for whatever error wasn't taken out by the simulated annealing, but I tell people to run simulated annealing first, for the best results.)

sigma957 commented 9 years ago

I would be very interested in this implemented in repetier. On Feb 23, 2015 8:25 AM, "626Pilot" notifications@github.com wrote:

Hello,

I had problems getting my Rostock MAX calibrated properly for years! I tried Marlin, Repetier firmware, and Smoothie, all of which have delta calibration routines, and none of which could produce a good result for me. So, I decided to write my own routine. Instead of using fuzzy logic like "if the effector is too high next to Z and too low opposite Z, adjust Z endstop," and so on, I used a machine learning algorithm called parallel simulated annealing. SA is used a lot in artificial intelligence, especially for machine vision and "travelling salesman"-type optimization problems. It's fairly easy to implement. More info is here: http://en.wikipedia.org/wiki/Simulated_annealing

After a few months, I had it all figured out, and my printer was printing across a wider footprint than it ever had before. I've had several other people test the firmware, and it has produced really good results for them, as well.

Code here: https://github.com/626Pilot/Smoothieware/blob/edge/src/modules/tools/zprobe/ComprehensiveDeltaStrategy.cpp Method is ComprehensiveDeltaStrategy::heuristic_calibration()

Discussion, with before+after on my printer (others got even better results), here: http://forum.seemecnc.com/viewtopic.php?f=82&t=7640

I developed all of this to run on Smoothieware, with the hope that others would port it to run on Arduino-based firmwares after I got all the hard math and logic figured out. It is very CPU-intensive, but it doesn't use recursion, so it should be possible to implement it in a memory-efficient way on Arduino firmware. I have already put this in front of Rich C for inclusion into Marlin, but I feel Repetier is easier to use (stores more stuff in EEPROM) so I think it would make sense to show the code to you as well. I think most people on the Rostock MAX are using Repetier, and I don't think they want to go back to Marlin just for this...

-HOW IT WORKS-

My algorithm manages 14 variables altogether: Arm length, delta radius, endstops, individual tower rotation and radius offsets, and print surface normal. The only thing I don't simulate yet, which I know to be a problem "in the wild," is tower lean. The algorithm starts by probing the bed in a grid, in order to gather a set of real-world depths in different locations. The goal is to use the firmware's built-in IK and FK functions to simulate a virtual printer, and to see what variables would have to be fed into that printer's config, to get the same results measured by the probe. The closer the simulated result to the measured result, the less "energy" in the system. We want the energy to be as close to 0 as possible, because if it's 0, we've found the exact real-world geometry of the printer! It works OK if you just give it endstops and delta radius. But the more variables you give it, the better a job it does. There is no fiddling with rules, or rules that work on one machine bu t not another, because there are no rules to begin with. It has access to simulate delta kinematics, but it doesn't understand all the tricky relations between settings. It only knows how to find what works, and get away from what doesn't.

For each variable, we use a binary search routine to find the best current setting for that variable across a range (for example, tower rotation offsets can vary by up to 3 degrees from default, so for the Z tower, it would search from 87 to 93 degrees). Once the best value is found, the variable's setting is "creeped" a random distance in the direction of the best setting.

Because each variable's simulation doesn't know what the others might do, there is some error in the result. However, by limiting the impact of that error by only letting the variable change a little each pass, and by making them compete in a random environment (each one can advance a random amount that changes each time), we allow better solutions to percolate to the top. The amount each variable can change per pass is controlled by "annealing temperature". This starts at a high value, and is slowly ratcheted down towards 0 pass after pass. This allows a broad search in the beginning, which slowly settles down to the finer search pattern needed to zero in on the optimal values. Each variable can have its own annealing temperature, but I usually just let them all use the default temperature, which I think is 0.35.

The algorithm can find its way out of local minima on the way to the global minimum, backing out of blind alleys if you will - the numbers can get better, then worse, then better still, as the algorithm wanders through some less optimal solutions on the way to the best one it can find.

I usually give the algorithm 50 passes. At the end of that, the settings are better than they were when it started. If I run it 3 or 4 times, it benefits from the improved starting point each time, allowing the end calibration to be better still. I've seen users gain access to lay down a first layer on much more of their print surface than they did before. I have had several people test this firmware, and it produces accuracy improvements of better than 100 microns in some cases.

This is an improvement over simple bilinear interpolation Z correction, because that only corrects Z - not X or Y. If you're printing pieces that have to fit with each other - sectional objects, gears, things that have to fit around bearings, etc. - that helps you get the first layer down, but they still come out screwy. Because on a delta printer, increasing the accuracy of Z also helps X and Y, this solution will take some of the error out of the XY plane. This is why I spent months working on it, rather than just throwing up my hands and settling on simple depth-map/bilinear interpolation. (My code DOES have separate logic that will use bilinear interpolation/extrapolation to correct for whatever error wasn't taken out by the simulated annealing, but I tell people to run simulated annealing first, for the best results.)

— Reply to this email directly or view it on GitHub https://github.com/repetier/Repetier-Firmware/issues/367.

Jmjcoke commented 9 years ago

One of the biggest time savers for delta operators who mod their machine or change print bed plates for different materials. I use a Arduino controller on one of my printers and would like to see this implemented.

nyl0cke commented 9 years ago

I'm stuck with an X3 Pro until someone makes a smoothie compatible board capable of running a Kraken. I would love this feature in Repetier, it would save so much time. Calibrating a machine and doing the tower rotation offsets is a several hour thing even with a dial indicator.

Jmjcoke commented 9 years ago

Duet with expansion board. http://www.reprap.cc//index.php?main_page=product_info&cPath=2&products_id=208&language=en&zenid=cmectj7p9h75uaqb8v2tkf26d7

On Mon, Feb 23, 2015 at 8:12 AM, nyl0cke notifications@github.com wrote:

I'm stuck with an X3 Pro until someone makes a smoothie compatible board capable of running a Kraken. I would love this feature in Repetier, it would save so much time. Calibrating a machine and doing the tower rotation offsets is a several hour thing even with a dial indicator.

— Reply to this email directly or view it on GitHub https://github.com/repetier/Repetier-Firmware/issues/367#issuecomment-75546767 .

Joshua Coke

815-323-2784