3

I'm working on an inertial measurement project using a 3-axis accelerometer and an Arduino. I want the Arduino to take in the x, y, and z g-values and spit out the magnitude. Since the |a| = sqrt(x^2 + y^2 + z^2) is computationally expensive, I wanted to investigate whether there was an alternative algorithm that could be used to speed it up (I'm willing to sacrifice a little accuracy).

I read about the Alpha-max, Beta-min method, but that appears to only work for 2D vectors. Is there anything similar for 3D vectors?

EDIT: Program language is C++

Justinas Marozas
  • 2,482
  • 1
  • 17
  • 37
Raddy
  • 39
  • 2
  • 6
  • It would be helpful if you'd tag a programming language you're using as performance implications will differ based on that. If you're using Python numpy is usually a performant option for calculations. [This answer](https://stackoverflow.com/a/9171196/2091230) shows an example of how to use it to calculate vector magnitude. – Justinas Marozas Jan 17 '18 at 17:43
  • Its being written in C++, added that to the original post. Thanks! – Raddy Jan 17 '18 at 17:53
  • [Related on math.se.](https://math.stackexchange.com/questions/1282435/alpha-max-plus-beta-min-algorithm-for-three-numbers) – Nelfeal Jan 17 '18 at 18:11
  • A sqrt calculation on a microcontroller _can_ be expensive, but how fast do you need it to be? How much precision are you willing to trade off? Is there anything you know about your inputs that can be leveraged (e.g., are they floats or ints and what range will they be in?) – Adrian McCarthy Jan 17 '18 at 19:45
  • I'm shooting for 100Hz sampling. I haven't had a chance to see if that's possible given the other tasks it is has to do, but since I'm still somewhat in the planning stages, I thought it would be best to start optimizing efficiency now. – Raddy Jan 22 '18 at 15:37
  • Sorry, to your other questions, the range of the accelerometer is -16 to +16 gs, and I'd like two decimal point precision in the final product. The input from the accelerometer is float, but only 12-bit precision per axis. – Raddy Jan 22 '18 at 15:50
  • Related: https://math.stackexchange.com/q/1282435/111897 – Herpes Free Engineer Jan 04 '20 at 12:24

3 Answers3

2

If you have a fast way of calculating two-dimensional magnitude, then perhaps the three-dimensional magnitude can be restructured in those terms.

The three-dimensional magnitude can be derived from the Pythagorean theorem.

|a| = sqrt(sqrt(x^2 + y^2)^2 + z^2) = sqrt(x^2 + y^2 + z^2)
MAhipal Singh
  • 4,745
  • 1
  • 42
  • 57
MattH
  • 121
  • 8
0

Normalizing Spatial Vectors without Square Root If you use what this guy posted to calculate the unit vector, you can then divide the x of the original vector by the calculated unit vector's x.

0

There is also std::hypot, which computes the length of a 2D vector (since C++11) or 3D vector (since C++17). For in-between versions of C++, you can compute the length of a 3D vector using the 2D version of the function as std::hypot(std::hypot(x, y), z).

Hypot is more robust against over- and underflow (especially during squaring of the individual components) compared to computing the formula manually. It might or might not be faster, depending on your standard library and hardware.

Eph
  • 225
  • 1
  • 5