# Holey Triangular Calibration

#82

@madgrizzle, thanks for the thought. It wasn’t clear by the way the math was implemented, but I think you are right. I committed a change to address this. This change (hopefully) resolves 2 of the issues.

Related to the other major issue, in which DistanceBetweenMotors was not calibrating, there is a “recomputeGeometry” method in the kinematics.py class. It is necessary to call that method in order for changes to DistanceBetweenMotors (property, ‘D’) to apply. I will give it another try sometime when I get home.

#83

I sat down to give this a try this morning, and it worked well enough that I cannot see anything clearly incorrect. The one exception is the MotorYOffset, which can be resolved with an anchor measurement to an absolute position on the worksheet.

I used @madgrizzle’s measurements from the original holey calibration. The results are below. I tried a few initial conditions, and arrived at the same answer, within 1E-3. I started with 4 parameters, as a starting point, to keep the problem simple. I removed the MotorYOffset, because it is just a distraction. Calibration of the chain tolerances and a x and y position for the two motors was not included. These are all things that can be added as needed. For now, there are some constants which look non-physical, specifically the rotational radius. I believe that if we include all the necessary parameters, this may change.

Calculated Parameters:
Distance Between Motors:
3567.1267524352315
117.29604622714962
Chain Sag Correction Constant:
70.65904316347218

Calculated Errors:
M_0_to_1:
-0.08455585
M_0_to_2:
1.87791097
M_0_to_3:
-2.12208903
M_0_to_4:
-0.08455585
M_1_to_2:
1.02455752
M_1_to_4:
0.0821885
M_2_to_3:
0.10196217
M_3_to_4:
-0.97544248

Here are items which need to be done before this is functional.

• Include additional measurements to an anchor location to enable calibration of the Motor Y Offset
• Additional parameters included for Chain tolerances
• Additional parameter included for Rotational misalignment of the work surface

#84

Do I understand that the process you go through results in differences between measured chain lengths for each cut and calculated chain lengths for each cut using the optimized parameters result in an error of less than 1E-9 mm?

If so, I’m having a hard time understanding how that is really possible without a fudge factor incorporated… Don’t get me wrong, it would be great if it was, but my theory for saying this is that measurement error (my ability to accurately place a tape measure between two points and read the distance accurately) is probably on the order of +/- 0.5 mm… Are you still using cut34Yoffset in the optimization?

#85

This part isn’t worded well… let me try again…

Do I understand that the process you go through results in differences between calculated chain lengths for each cut based upon the measurements and calculated chain lengths for each cut based upon the optimized parameters differ by less than 1E-9 mm?

#86

With the first try, yes. However, I realized a few mistakes and tried again. Now the errors are somewhere between 0 and 2 mm. The errors are in terms of measured distance, rather than chain-length error.

The measured errors are these, in mm:

Where M_<#>_to_<#> is the error between the calculated kinematics.forward distance between points, and the measurement between two points e.g. kinematics.forward calculates distance between point 0 to point 1 to be 1000 mm, but it is measured as 1001 mm. These are the measurements you made in your original Holey Calibration work.

When I tried it the first time, I didn’t realize that I was calibrating to the original points calculated before the calibration started. So, the lengths that were calculated at the start were the lengths that were used in the calibration. Your suggestion helped me realize the mistake.

#87

Here are some updates on work I have done. Still, everything is on this GitHub site, https://github.com/schmittjoshc/MaslowCalibration/blob/master.

At this point, everything appears to be working on the calibration side. Looking back at @madgrizzle’s original calibration results, here is a comparison:

• This solution is not significantly better, with the exception that the solution comes in ~4 optimization iterations; much fewer than @madgrizzle’s.
• There is a dependency on the scipy Python library, which has to be installed.
• There are no parameters like “desiredMotorSpacing”, which anchor the calibration.
• The calibration operates on the GC kinematics calculations, so the calibrated constants should translate into GC.
• IMHO the calibration algorithm referenced from the scipy Python library is very capable, and is the correct tool for the job. It is capable of handling very large problems, and should scale up well, regardless of where we end up taking this.

Here are the things that I hope to do in the future.

• Updates to the kinematics.py class should be merged back into the main branch. The implementation of chain tolerance is already in the firmware, and there is no reason it shouldn’t be in GC.
• I am on the fence as to whether or not I should change the hole-pattern. I think it is valuable to have a hole at the top-center of the workpiece, since this area is the most sensitive to changes to calibrated parameters.
• I would like to benchmark against simulated points. I would like to run a simulation in which the machine parameters are perturbed slightly, to represent an inaccurate machine. Then, go through a calibration to determine how close to the original parameters I get.
• If the simulation works out, (I should be the guinea-pig) I would like to test it on hardware.
• I think it makes sense to put the actual catenary equations into GC and the firmware. That way we are working with real chain tension, chain weight, and sled weight. The calibration of chain sag this is then easier to understand because there is a physical phenomenon associated with the numbers and calculations. I don’t believe there is a big computational penalty here.
• While we’re modifying the kinematics equations, may as well include chain-stretch. I know @gero has done some tests and found the chains stretch a few mm with very reasonable tension. This is a predictable phenomenon. Here is some information on chains: http://tsubaki.ca/pdf/library/the_Complete_guide_to_chain.pdf
• I spent a brief moment determining the elastic deflection calculation. StretchedLen=BaseLen*(1+Tension(lbf)*2.3e-05) I got the 2.3e-5 by visually looking at the graph in the above hyperlink. It is a property of the chain. It is not precise, but is is approximately correct. Length units just need to be consistent between StretchedLen and BaseLen.

List of sources of error
#88
• Added measurements to the top of the worksurface (4x8 plywood). This was necessary to calibrate the motorYOffset parameter.

the reason that the calibration tries to figure this out is that measuring it
accurately proved to be rather hard.

If we have two cuts along the center line, we should be able to work out what
this value is.

Here are the things that I hope to do in the future.

• Updates to the kinematics.py class should be merged back into the main branch. The implementation of chain tolerance is already in the firmware, and there is no reason it shouldn’t be in GC.

I agree

• I am on the fence as to whether or not I should change the hole-pattern. I think it is valuable to have a hole at the top-center of the workpiece, since this area is the most sensitive to changes to calibrated parameters.

once we make sure things are working, we should change the pattern (and also add
support for other ways to detect position). The last time we tried this, the
results got worse due to other problems in the calculation.

• I think it makes sense to put the actual catenary equations into GC and the
firmware. That way we are working with real chain tension, chain weight, and
sled weight. The calibration of chain sag this is then easier to understand
because there is a physical phenomenon associated with the numbers and
calculations. I don’t believe there is a big computational penalty here.

yes, the actual equasions should be there, the fact that there is something
there that claims to be chain sag but is only an approximation is a problem.

However, I do think that we can combine some

is there any real stretch? or is it just taking up the slack from the chain
tolerance?

• I spent a brief moment determining the elastic deflection calculation.
StretchedLen=BaseLen*(1+Tension(lbf)*2.3e-05) I got the 2.3e-5 by visually
looking at the graph in the above hyperlink.

which graph, that’s a large pdf

It is a property of the chain. It is not precise, but is is approximately
correct. Length units just need to be consistent between StretchedLen and
BaseLen.

0.000023 * tension is a low value , but when multiplied by a baselen of 3000 and
tension gets to 40 pounds or so, it could be noticable.

David Lang

#89

On 1 full (~11 ft) chain roughly 2mm with 15 kg/~33.0693lbs. That is a sled weight mostly not reached. It also needs to be divided by both chains. What is the max weight in one top corner that has to go in the equation?

Edit: Or does it not have to, because there the chain is so short that it does not matter?
Edit 2: Surprisingly I could not find a chain length difference between my 2 abused chains and 2 new ones while others have reported significant differences.
I would have expected my old left chain would be longer because of the ~30kg ‘pull tight’ that is went through how many GC versions.

#90

Big for using scipy.leastsquares… As much as I wanted to, I couldn’t figure out how.

This was there to attempt to constrain the optimization so that it didn’t run that value off to some silly number when I knew what it should be (or close to being).

There’s nothing special about the holes I picked. Go for it. Maybe rotate the inner holes 90-degrees (i.e., like a diamond)?

What are the actual equations that reflect what we are doing?

#91

If you don’t stretch it past the yield value (200+ pounds), when the tension is

The very first time a chain is put under tension, the components of the chain
may shift slightly into their final alignment, this is what vendors refer to as
‘pre-stretched’ chain

max tension is in the top center, at that point the chains are about 1300mm
long, so 2.3e-5 * 1300 *40 = 1.1mm

in the bottom corner you have the most length (almost 3x the lenth), but only
1/10 the tension, so the stretch will be less there (sag dominates there)

David Lang

P.S. does anyone have time to loop their chains and run a series of tests to see
if the chain length varies over it’s length?

#92

Tomorrow is Friday, the lazy day. If the instructions are clear I would invest 3 hours (if that is enough) on Saturday if it helps.
I would need to break a chain I guess. Can do that.

#93

I don’t think the intent is to stretch the chain so hard that it breaks. I think it is more about how much the chain tolerance varies over its length, and how much it elastically stretches under normal loads.

#94

I don’t think the intent is to stretch the chain so hard that it breaks. I
think it is more about how much the chain tolerance varies over its length,

exactly.

and how much it elastically stretches under normal loads.

not as much this.

it would be ‘pull tight, check the encoder positions, release tension, advance a
few inches and repeat until you have gone through both chains’ with the interest
being how much the measurement varies as you go around the length of both
chains. My hope is that for a pair of chains that came from the same
manufacturer at around the same time, the numbers are going to be consistant
enough that we don’t care (off by a small fraction of a mm), but in part this is
a sanity check in case the chain isn’t that consistant.

David Lang

#95

Tomorrow is Friday, the lazy day. If the instructions are clear I would invest 3 hours (if that is enough) on Saturday if it helps.
I would need to break a chain I guess. Can do that.

connect the chains together using the master links into a loop, put the loop
over both motors (close to snug, you don’t need to worry about 12 o’clock). clear your log file

``````G21            ( metric mode )
G91            (relative mode)
B11 R S-63 T 5 ( run the right motor at a bit under 1/4 power for 5 sec )

( if this doesn't take up the slack, repeat until the slack is taken up)

B06 L0 R0      ( set chain lengths to 0)
B09 L5         ( move the left motor a little bit to release tension )
B09 L95 R-95   ( move to the right about 4 inches, leaving a little slack to take up in the next step )
B11 R S-63 T 5 ( run the right motor at a bit under 1/4 power for 5 sec )
B10 L          ( report the position of the left motor )
B10 R          ( report the position of the right motor )

B06 L0 R0      ( set chain lengths to 0)
B09 L5         ( move the left motor a little bit to release tension )
B09 L95 R-95   ( move to the right about 4 inches, leaving a little slack to take up in the next step )
B11 R S-63 T 5 ( run the right motor at a bit under 1/4 power for 5 sec )
B10 L          ( report the position of the left motor )
B10 R          ( report the position of the right motor )

B06 L0 R0      ( set chain lengths to 0)
B09 L5         ( move the left motor a little bit to release tension )
B09 L95 R-95   ( move to the right about 4 inches, leaving a little slack to take up in the next step )
B11 R S-63 T 5 ( run the right motor at a bit under 1/4 power for 5 sec )
B10 L          ( report the position of the left motor )
B10 R          ( report the position of the right motor )
``````

repeat this block until you have finished the loop

what we will be looking for in the log is the lines:
B10 L
[Measure: 199.94]
B10 R
[Measure: 199.76]

and how much they vary over the loops.

I expect that B10 L is always going to be the same (or very close to it), and
B10 R is what should vary.

This is only pulling at 1/4 power, if you add a second B11 line with S-255 that
will run the motor at full power. It would be interesting to have one loop be:

``````B06 L0 R0      ( set chain lengths to 0)
B09 L5         ( move the left motor a little bit to release tension )
B09 L95 R-95  ( move to the right about 4 inches )
B11 R S-63 T 5 ( run the right motor at a bit under 1/4 power for 5 sec )
B10 L          ( report the position of the left motor )
B10 R          ( report the position of the right motor )
B11 R S-255 T 2 ( run the right motor at a bit under 1/4 power for 5 sec )
B10 L          ( report the position of the left motor )
B10 R          ( report the position of the right motor )
``````

and see how much the two positions differ (how much does the extra power reduce
chain sag and/or stretch the chain)

David Lang

DL's loop chains and run a series of motor position reporting
#96

be ready with the kill switch the first time you run that, just in case I didn’t get something turning the right way

both motors should be running clockwise all the time.

you may need to run more than 5 seconds the first time, depending on how much slack there is to take up.

#97

So I don’t need to break the chain. Connect 2 together, make sure the chain is fairly tight on top (edit: set at 12?) of the sprockets before start and somehow take care that the slack I have does not interfere?

#98

These commands seem to all be in absolute mode rather than in relative mode

``````B09 L5         ( move the left motor a little bit to release tension )
B09 L95 R-100  ( move to the right about 4 inches )

``````

will leave the left encoder at 95mm, the right one at 100mm instead of both at 100mm. Is that the intention?
The G91 gcode sets relative mode, G90 sets absolute mode.

#99

Is absolute default? A G91 for relative at the start would do, right?

#100

G21 G91 at the start would put you in metric relative mode.

#101

So I don’t need to break the chain.

Correct

Connect 2 together, make sure the chain is fairly tight on top

right, the first action takes up the slack (1/4 power for 5 seconds), if that
isn’t enough, just repeat this line until it does pull tight

(edit: set at 12?) of the sprockets

it does not matter.

before start and somehow take care that
the slack I have does not interfere?

correct, with stock chains, it will sag about 2 feet down in the center if I’ve
done the math right.

It my help the chain to feed if you can tilt the machine forward so that the
sprockets and chain are vertical.

David Lang