# Accelerometer calibration - how to get cross-axis sensitivities

I've already asked a related question (accelerometer bias removal) here on robotics and got a bit better results on corrected accelerometer output. To get even better results I found the calibration equations (7th & 8th paragraph) from Vectornav which are just a bit enhanced than the solution in the linked question:

However, six more variables are needed:

Sensitivity of sensor X-axis to Y-axis inputs ($$M_{xy}$$)

Sensitivity of sensor X-axis to Z-axis inputs ($$M_{xz}$$)

Sensitivity of sensor Y-axis to X-axis inputs ($$M_{yx}$$)

Sensitivity of sensor Y-axis to Z-axis inputs ($$M_{yz}$$)

Sensitivity of sensor Z-axis to X-axis inputs ($$M_{zx}$$)

Sensitivity of sensor Z-axis to Y-axis inputs ($$M_{zy}$$)

Below it is also stated:

IEEE-STD-1293-1998 [...] provides a detailed test procedure for determining each of these calibration parameters

However, after searching through the 1293-1998 standard (especially page 201 in Google Docs) I didn't find any clue on how to calculate the $$M$$ values. Also, $$B_{d}$$ and $$V_x$$ values from Vectornav equations is not explained anywhere. Can someone point me further?

• Added some excerpts, but not from 1293-1998 standard, since I don't know where the explanation is. – Primož Kralj Jul 11 '13 at 5:22
• Great stuff, thanks @PrimožKralj that makes the question much more stand-alone. – Mark Booth Jul 11 '13 at 11:06

OK. I'm too lazy to read the document, but in general you can model the sensor response as

$$\alpha_m = S \alpha + b$$

where $\alpha$ is the actual acceleration in three dimensions with respect to the accelerometer body (including the acceleration due to gravity), $\alpha_m$ is the measured acceleration from the accelerometer, $b$ is an offset, and $S$ is a $3\times3$ sensitivity matrix.

$S$ and $b$ can be derived from the equations you give in your question above: $S$ is the product of your two $3\times3$ matrices, while $b$ is the product of $S$ and their $B$ and $V$ vectors. We're all saying the same thing; I'm just compressing the math a bit.

If you know $S$, $b$, and $\alpha_m$ then you can solve the above equation for $\alpha$ to get $$\hat{\alpha}=S^{-1}\left(\alpha_m - b \right)$$

So if you don't assume that $S$ is symmetrical (I don't think it needs to be) then you have 12 unknowns (nine in $S$ and three in $b$).

If you mount your accelerometer into a cube whose sides are more accurate than the calibration you're trying to make, and you set it on a table that is as accurate as the cube, and measure the acceleration at each of the six faces of the cube, then you'll get 18 equations, three for the three axes, times the six faces of the cube. There should be sufficient information there to extract your 12 unknowns by linear algebra.

Serious aerospace companies do this job with rotary tables, but that gets kinda spendy.

• How about $M$ coefficients? And $B_d$? – Primož Kralj Jul 11 '13 at 5:23
• And $V_x$? (couldn't edit last comment). – Primož Kralj Jul 11 '13 at 6:02
• The question has now been updated Tim, so you might want to consider revising your answer. Thanks, – Mark Booth Jul 11 '13 at 11:08

I realize this question is 2 years old, but I have direct recent experience with this. The way I did this is with 6 rotated cube positions with 1000 points at each position, so a total of 6000 samples.

I'm assuming Matlab/numpy nomenclature, where NxM means N rows and M columns.

I assume an equation like Ax = B where B is the measured values matrix (6000x4, with right column all ones) and A is the "real" values matrix (also 6000x4, which has six 1000-value sections, with 1000 copies each of [1,0,0,1], [-1,0,0,1],[0,1,0,1], [0,-1,0,1], [0,0,1,1], [0,0,-1,1], corresponding to Xup, Xdown, Yup, Ydown, Zup, Zdown. x is a 4x4 matrix where the upper left 3x3 components are the gain and cross-axis sensitivities, and the right 3x1 components are the offsets; the bottom row is all zeros. By using a 4x4 matrix we can do everything in linear math and avoid the separate offset computation.

I then let numpy compute x as the least squares division of B/A. I think in Matlab it would be B\A. I'm not sure how least squares works in this case, but the result is a 4x4 matrix that minimizes the errors and averages out all the samples. Conceivably you could also do this with only two positions, where each axis is diagonal to gravity, then upside down from there, and you adjust the expected "ideal" values accordingly.

The result is a 4x4 matrix that fixes scale, offset, and cross axis errors, which also means it corrects for any rotation error you have between the sensor and the reference edge hardware.

Here is the python code, assuming numpy:

def least_squares_fit(A, B):
"""Does least squares fit to find x of Ax = B.  Returns best guess of original distortion
matrix x and its inverse.  A is ideal values.  B is distorted values.  Use inverse to
correct real data back to ideal data."""

# Need to extend A and B
A = np.hstack((A, np.ones(len(A)).reshape(-1, 1)))
B = np.hstack((B, np.ones(len(B)).reshape(-1, 1)))

X, res, rank, s = np.linalg.lstsq(A, B)
X = X.T # Not sure why we need T
Xi = np.linalg.inv(X)
return (np.asmatrix(X), np.asmatrix(Xi), np.sum(res))

• "X = X.T # Not sure why we need T" Yikes! It's hard to take this as an authoritative answer when you are not sure why you are taking the transpose! If you've since figured it out, maybe add an update? In the mean time it's a potentially great answer; +1 – uhoh Sep 24 '17 at 5:33
• Ha... that was a few years ago. I don't think I ever figured it out. I let myself believe it was either a quirk in numpy, or something I didn't quite get about how it does matrix multiplies. The code worked so I left it alone. :) – Sonicsmooth Sep 25 '17 at 22:59
• OK well if it worked, then that's the ultimate authority! OK I'll give it a go, thanks! – uhoh Sep 26 '17 at 0:10
• I've found myself throwing in a few .T's here and there myself, now I can happily believe that I'm calibrating too. I'm glad I found this answer, learned how to use some .linalg() as a bi-product. – uhoh Oct 3 '17 at 11:12
• Glad my post was of help :) – Sonicsmooth Oct 4 '17 at 18:26