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:

enter image description here

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?

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

2 Answers 2


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.

  • $\begingroup$ How about $M$ coefficients? And $B_d$? $\endgroup$
    – c0dehunter
    Jul 11, 2013 at 5:23
  • $\begingroup$ And $V_x$? (couldn't edit last comment). $\endgroup$
    – c0dehunter
    Jul 11, 2013 at 6:02
  • $\begingroup$ The question has now been updated Tim, so you might want to consider revising your answer. Thanks, $\endgroup$
    – Mark Booth
    Jul 11, 2013 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))
  • 1
    $\begingroup$ "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 $\endgroup$
    – uhoh
    Sep 24, 2017 at 5:33
  • 1
    $\begingroup$ 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. :) $\endgroup$ Sep 25, 2017 at 22:59
  • $\begingroup$ OK well if it worked, then that's the ultimate authority! OK I'll give it a go, thanks! $\endgroup$
    – uhoh
    Sep 26, 2017 at 0:10
  • $\begingroup$ 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. $\endgroup$
    – uhoh
    Oct 3, 2017 at 11:12
  • 1
    $\begingroup$ Glad my post was of help :) $\endgroup$ Oct 4, 2017 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.