Distance measurement

Fixed the Processing sketch that attempts to measure distances based on acceleration. (It was off by a factor of 10. Guess who didn’t convert from g to m/s^2.) Anyhow, instead of compensating for tilting in code, I built a rail:


Of course, this doesn’t mean I might not have to take the orientation into account at some point. Still, with the rail I can roughly measure the moved distance as the change in acceleration happens almost exclusively on the x axis.


Drifting is quite bad, though. I’ve got a good 15cm of travel on the rail and measuring movement that’s done right after the measurement starts (within a couple of seconds) seems accurate within +/- 1 cm. But when measuring a completely stationary sensor over a time of 30 seconds, the measurement may have wandered off even beyond 40cm. Currently, I’m fresh out of ideas on how to counter this.

I figured that building a data glove that can track the hands position in 3D space may be quite difficult measuring the accelration of the glove alone. Because the MPU-6050 is able to produce orientation data (as a quaternion), one could of course track the hands position from the shoulder on onward. The shoulder would be a “fixed point” with a ball joint. Having sensors on the upper and fore arm measuring the direction where the arm is pointing to (and knowing one’s arm’s length), one could calculate the location of the hand in relation to the shoulder. It’s not ideal for motion capturing either since the shoulder is capeable of subtle movements, but I think it might be the way to go.


17 thoughts on “Distance measurement

  1. Even a slight misalignment, when the acceleration doesn’t happen purely on the X axis, can cause an error. I think what you need to do is to rotate the acceleration vector by the orientation vector, to align it to world coordinates. Then subtract (0,0,1g) to remove gravity. Which should leave you with pure world-coordinate system acceleration.

  2. Hello. I want to mail you some equations I had found on a scientific article, that can help you compensate tilt or yaw. So that you can calculate the displacement in one direction accurately. It is in pdf format . I extracted the main page as jpeg. Mail me , and i will send you the file.

  3. Hi, first of all I would like to thank you for sharing your research with the community.
    I’m trying to measure the distance traveled by quadcopter based on the MPU-6050, is that even possible?

    Thank you!

    • Hi, thanks for commenting. Well, in my experience, if you know the initial position and velocity, you can get a rough estimate within the first few seconds, but then the error just grows beyond anything useable. (Hm, I’ll need to update this blog and publish another test program I’ve got, so people who are interested can evaluate this themselves. Hopefully, I’ll do that soon 😉 ) As for quadcopters, I’d probably add a GPS module and get the traveled distance from there. It won’t be 100% exact either, but the measurement’s error doesn’t accumulate over time.

  4. Hello,

    I am trying to recreate your experiment on my uno but cannot seem to use the processing code that is posted. The pin out that I am trying to use is:
    3.3v -> VDD & VIO
    SCL -> A5
    SDA -> A4
    INT -> D2
    GND -> GND

    When I try to run the code it tells me that I am getting 0 samples/sec. Do you have any ideas on how I could correct this problem?

    Thank you

  5. Hi, I new with the mpu stuff, so first of all thank you very much for this!
    I want to try your code, I have an mpu9150, and I wonder which parameters your code expect from the dmp, Im using arduino and there are some possible options.

    Thanks for any help!

    • figured it out.

      Another question: when you multiply by g, to work in force units, is it always g? or its depend on the sensitivity? mpu9150 has 2+-,4+-,8+- g…

      • Uh.. It’s been a while since I’ve looked at this.

        I think I first converted the reading to units of g by using a divider (8192), which will depend on the selected sensitivity. (Apparently I assumed it the be set to +/- 4 by the Arduino which was the default by Jeff’s code at the time. He might have changed this later. Can’t remember, really.) Anyway, that first conversion gives a float indicating the g’s experienced by the sensor.

        Then, one g is simply equivalent to the acceleration of 9.80665 m/s^2..

        Oh. Oops. I may have been stupid while commenting the processing code: I say force, when it’s really all just acceleration. Either g or m/s^2. No newtons here. Sorry, for the confusion.

  6. Hi! thank you for you time:)
    I thought the divider is 8192 is because the mpu given reading in 13 bit, (2^13=8192) so you normalize it and then turn it to g units, if the sensitivity is up to 4g, I thought I should multiply with 4g. but I guess its not what you were thinking..

    Another question, If you still remember, I don’t understand why you subtract the acceleration average. why use the difference between current acceleration and the average of all samples till that time? I will really appreciate explanation!

    • Thanks for commenting 🙂 Let’s see if I can get this correct…

      The read 16-bit value is a signed integer. The range represents -4g to 4g as the MPU was set to this sensitivity.

      The 1st bit is the sign. The next two bits represent the 4 g’s (or more accurately 0-3 g’s on the positive side) and the remaining 13 bits are essentially decimals. So, I seem to have gotten the measured g acceleration (as float) by dividing with 2^13, which is 8192.

      The distance measurement was done on a 1-directional rail with the MPU mounted securely on the top of a “sled”. However, there is no way to assure perfect alignment. The sensor is probably tilted in some way or another in respect to gravity. Also, the calibration of the accelerometers zero probably isn’t perfect. So, although the MPU isn’t moving and you have about 1g on the z-axis, you’ll still get a small acceleration also in x and y.

      So, I measured the distance in basically 2 separate parts: 1) measure the average (offset) acceleration while resting and 2) measure the distance while moving (by measuring the current acceleration and removing from it the acceleration measured while resting).

      In part 2 the movement is limited to one direction only and more importantly, the MPU can’t turn (pitch, yaw or roll) in respect to the world. So, I can subtract the “average acceleration” of non-movement (i.e. the offset) from the acceleration measured while moving. Now, I hope to have a fairly accurate acceleration caused only by the movement itself and not by gravity or other non-perfect starting conditions.

      As you might notice, this distance measurement is pretty dumb, as it uses only the acceleration data, and could be done by any accelerometer. The MPU-6050 can also provide it’s orientation (the quaternion) if the DMP is used, and the MPU-9150 could also tie this orientation to it’s compass data (using the magnetometer). However, what I learned from this (and subsequent attempts) is that measuring the distance by acceleration alone is difficult. The errors accumulate fast!

      PS: I recently also bought a 9150 to play around with, but sadly haven’t really had the time to look into it. Maybe one of these days…

      • Hi again. thank you so much you helped me a lot.
        As I finally get the right data through my processor, I have another question,
        why is your delta time is 10 ms? I see gyro and accel’ work at 1khz, so is the fifo sampling (as I set it), so I though it should be 1 ms (0.001s).
        Do you change the fifo rate to 100hz?

      • Hi. (Sorry for the delay.) I used the i2cdevlib’s code pretty much “as is”. That means (if I recall correctly) that the DMP was enabled and calculating the device’s orientation from the accel. and gyro data. The resulting quaternion as well as the gyro and accelerometer data then get pushed into the FIFO. The MPU would fire an interrupt every 10ms to indicate a new set of data was available. Therefore delta time was also 10 ms.

        I didn’t really try to modify the gyro’s or accelerometer’s sampling speed directly because I don’t know how it would affect the “DMP program” (i.e. that bunch of binary code provided by the i2cdevlib that sets up the DMP functionality). My guess is that the gyro and accel. run at higher speeds internally, but they might be averaged by the DMP code in order to reduce noise? It’s hard to say as the DMP-functionality wasn’t really documented anywhere and the binary code was just copied from an Invensense dev board using a logic analyzer.. (Rumor has it, that the DMP is based on a Kalman filter. However, that’s a topic that goes well beyond my understanding.)

        You can listen to Jeff’s story about reverse engineering the MPU’s DMP-code from TheAmpHour-podcast. The MPU-stuff begins 1 hour and 10 minutes in:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s