Optical Calibration Demo and Three Hours Working on a Bug

I get a headache looking at it :slight_smile: Is this basically the same thing we worked on back in September?

But with a few tweaks added in? I had incorporated what we worked on back then into firmware and activated using it if you entered the chain sag value as a negative number. I can take your python and convert it to cpp if that’s what you need if you want to test it out (by entering a negative chain sag value). Honestly, there’s very little difference between the python code and the cpp code… just some brackets, semicolons, you don’t need to name the math routines.

Is chain elasticity and important factor at this point to test out (that might require a more intensive change to add another setting… it could be hard coded to something if you’d like).

I get a headache, too. Yeah. That is what I am talking about. I have implemented it in my branch of the kinematics.py class. I was able to validate the chain-tension calculations, etc. I validated that the horizontal components of the chain-forces were equivalent, for the left and right chains. I validated that the vertical components of the chain-forces (left+right) sum to the weight of the sled. I tried to run an analysis of displacement vs. position. I ran into an issue. I am not sure what the cause of the problem is. Sometimes, the calculation predicts a chain-length that is obviously incorrect. It is not ready for prime-time, yet.

Do you think you could bake it into the simulator and see what’s going on? We shouldn’t put it in the firmware until we are confident it won’t result in bad chain lengths. Nothing is more frustrating than getting a message indicating that the controller could not determine the position of the sled and you need to reset the chains to known lengths…

1 Like

I haven’t dug into the Kivy part of GC, so that will be an additional hurdle. I may need help.

Agreed. That is what’s going on right now.

this is the sort of problem we were running into when we were using the
incorrect calculation (one that assumed that the low point in the arc was
between the endpoints), the forces still balanced out, but the length
calculations were useless.

David Lang

1 Like

Here it is. Chain-sag displacement plotted against position on the worksurface, as predicted by the catenary equation. This shows the magnitude of how far the catenary equation displaces the sled, the geometric distance the sled moves as a result of chain sag.

image

so ~6mm displacement at the corner? I don’t know what the true value should be, but at least this seems reasonable. What chain sag compensation values have you found the calibration routine to come up with? Correct me if I’m wrong, ideally the value should equal the weight of the sled.

It hasn’t been all that good when calibrating sled weight. If I start with a sled weight of 20 lbs, I end up with a sled weight of 10.4 lbs, which is clearly incorrect. I believe this is consistent to your experience.

My hypothesis is the calibration is compensating for very small measurement differences. When I look at your original measurements for the 5 point Holey Calibration, the bottom measurement is 1 mm shorter than the top measurement. I believe the calibration reduces the sled weight by 50% to compensate for this 1 mm difference. I would like to test to confirm. If this is true, sled weight isn’t a very good candidate for calibration, because it is so sensitive.

1 Like

This is the latest optical calibration run with hand entered parameters (no real calibration had been done)

Actual measured Y-Error

image

Curve fit to a*x^2 + b*y^2 + c*x*y + d*x + e*y + f (please ignore the trace colors, they are inverted)

image

So I’m thinking a different curve might be needed as the “curve” doesn’t really match all that well… especially along the left and right edges (0 and 30 on the x axis)… It does smooth out the data at least.

The calibration near the top is pretty good (6 inches from top the accuracy is ~ 0.5 mm) but the bottom corners still have issue (~1.2 mm) and I’m think it might be more of a precision issue (friction, sled balance, etc.)

3 Likes

What are you using for chain sag correction and rotational radius as your defaults?

132.75 rotation radius and 33 chain sag.

132.75 with the ring kit or @pillageTHENburn linkage?

ring kit, but I’m passing the cotter pin through the second link to avoid this:

Why not just also just use the second chain king th over the top of the sprocket when setting vertical? That’s what I’m doing to avid the snapped chain issue

1 Like

Yeah, you can do it that way as well, but I had already marked my chains. Either way works.

Agreed. It looks like the equation doesn’t have the appropriate degree of freedom to capture all the displacement curves. It is like a y*x^2 term is needed.

I think that would show up as noise: both up and down from the curve. To me, this looks like the curve equation doesn’t have sufficient degrees of freedom.

I was using something somebody came up with and have absolutely no clue how to change it so it would do something different. So, now I found something else that I think I can use:

I’m just trying to figure out what the form of the equation that it is fitting and how the returned coefficients relate to the coefficients of that equation. There’s got to be a standard way this is done because nobody seems to ask that specific question…

I don’t think a library reference is necessary. If it is confusing, you can create your own polynomial, and implement your own constants. That way there is no ambiguity.

Something like this:
def Poly(x,y,Coefficients):
c=Coefficients
return c[0]*x+c[1]*x**2+c[3]*y+c[4]*y**2+c[5]xy+c[6]x**2y

It’s numpy that I have a hard time with. It’s not intuitive if you don’t understand its syntax. This is what I’m using.

        ....
        dataX = np.zeros(15 * 31)
        dataY = np.zeros(15 * 31)
        dataZX = np.zeros(15 * 31)
        dataZY = np.zeros(15 * 31)
        for y in range(7, -8, -1):
            for x in range(-15, 16, +1):
                dataX[(7 - y) * 31 + (x + 15)] = float(x * 3.0 * 25.4)
                dataY[(7 - y) * 31 + (x + 15)] = float(x * 3.0 * 25.4)
                dataZX[(7 - y) * 31 + (x + 15)] = self.calErrorsX[x + 15][7 - y]
                dataZY[(7 - y) * 31 + (x + 15)] = self.calErrorsY[x + 15][7 - y]
        mx = self.polyFit2D(dataX, dataY, dataZX)
        ....


def polyfit2d(x, y, z, order=3):
    ncols = (order + 1)**2
    G = np.zeros((x.size, ncols))
    ij = itertools.product(range(order+1), range(order+1))
    for k, (i,j) in enumerate(ij):
        G[:,k] = x**i * y**j
    m, _, _, _ = np.linalg.lstsq(G, z)
    return m

and I get back a bunch of coefficients. How would I put in my own polynomial in that?

1 Like

I didn’t test it, but this is how I think it should work, based on what the website describes the output of “itertools.product”.

1 Like