psiphi75 / ahrs

AHRS (Attitude Heading Reference Systems) calculation for JavaScript
Apache License 2.0
87 stars 16 forks source link

Combining AHRS with gyronorm.js #7

Closed pliablepixels closed 7 years ago

pliablepixels commented 7 years ago

Hi there, my usecase is to gather accelerometer data (x/y/z) while driving a car. I'd like to make sure the data gathered is in earth co-ordinates, which means the data should be relative to earth coordinates irrespective of how the phone is placed in the car.

GyronormJS returns the rotation and acceleration values as follows:

    // data.do.alpha    ( deviceorientation event alpha value )
    // data.do.beta     ( deviceorientation event beta value )
    // data.do.gamma    ( deviceorientation event gamma value )
    // data.do.absolute ( deviceorientation event absolute value )

    // data.dm.x        ( devicemotion event acceleration x value )
    // data.dm.y        ( devicemotion event acceleration y value )
    // data.dm.z        ( devicemotion event acceleration z value )

    // data.dm.gx       ( devicemotion event accelerationIncludingGravity x value )
    // data.dm.gy       ( devicemotion event accelerationIncludingGravity y value )
    // data.dm.gz       ( devicemotion event accelerationIncludingGravity z value )

    // data.dm.alpha    ( devicemotion event rotationRate alpha value )
    // data.dm.beta     ( devicemotion event rotationRate beta value )
    // data.dm.gamma    ( devicemotion event rotationRate gamma value )

Based on reading your documentation, would AHRS be a good fit for my goals? I plan to use gyro norm to get the data and then

madgwick.update(data.do.beta, data.do.gamma, data.do.alpha, data.dm.x, data.dm.y, data.dm.z);
console.log(madgwick.toVector());

I'll give it a shot next week, but just wanted to know if your library is meant for this.

pliablepixels commented 7 years ago

Here is a snapshot of my output. Raw data is what gyro norm is reporting. Madgwick data is what this library is reporting. https://gist.github.com/pliablepixels/9694fb73f406724553be226464bf8a7b

The good news is that the X/Y/Z axis is staying constant now matter how much I turn the phone, which is what I wanted. But I don't understand the math enough to know if its doing what I want it to - that is, get acceleration vectors normalized to earth co-ords. Can someone take a look at the gist?

This is how I'm invoking the library:

adgwick.update(gdata.dm.beta * deg2rad, gdata.dm.gamma * deg2rad, gdata.dm.alpha * deg2rad, gdata.dm.gx, gdata.dm.gy, gdata.dm.gz );

Note that the data.dm.alpha/beta/gamma are the rotation rates, not absolute angles. Should I be using absolute angles (converted to radians)?

psiphi75 commented 7 years ago

It appears you are correctly calling AHRS for the gyro, the input angles are rotation rate in radians/second. However, the unit for the gx/gy/gz should be in g, but it appears you have it in m/s. To convert to g, just divide by 9.81.
The other key point is that the AHRS algorithm is expecting raw data from the gyro and accelerometer, generally these provide between 100 and 250 data points per second, without this resolution the AHRS will be very inaccurate.

pliablepixels commented 7 years ago

Thanks @psiphi75 I've updated my code to:

  madgwick = new AHRS({ 
        sampleInterval: 20,
        algorithm: 'Madgwick',
        beta: 0.4,
        kp: 0.5,
        ki: 0
      }); 

and:

let grav = 9.81;
madgwick.update(gdata.dm.beta * deg2rad, gdata.dm.gamma * deg2rad, gdata.dm.alpha * deg2rad, gdata.dm.gx/grav, gdata.dm.gy/grav, gdata.dm.gz/grav );

And am charting the data for:

        accdata.x = madgwick.toVector().x;
        accdata.y = madgwick.toVector().y;
        accdata.z = madgwick.toVector().z;

I am assuming this will give me earth coordinate of the acceleration axis, and do a reasonable job eliminating noise. I'll go for a drive tomorrow and try these readings in my phone in different coordinates.

Also, I've changed my accelerometer to report data every 50ms (0.05s) so that should match with the sample interval of 20 in AHRS. Is that ok?

Does this look right to you?

psiphi75 commented 7 years ago

Looks good. Keep your raw data, such that if something does not work, then you can try it again back in the office. Yes, 50ms = 20Hz, all good there. Not an issue, but you don't need the kp and ki values, these are for the Mahony filter and do nothing with Madgwick.

The input axis should be as follows, you may need to check this: x - points forwards y - points left z - points up

The output using toVector() will have the same orientation. Because I don't think you have a magnetometer (compass) connected you won't a frame relative to Earth, except for the vertical orientation. You won't know which way is north.

pliablepixels commented 7 years ago

Thanks. I do have a compass - but right now, I can extract a 'heading' that will be in degrees (0 is north). Your APIs are looking for x/y/z. Anyway I can use this?

psiphi75 commented 7 years ago

If you are already getting the heading, then it will work. For best results you would want to feed in the raw x/y/z magnetometer data into AHRS, it will give you the best result.

pliablepixels commented 7 years ago

Interesting - here is a comparative. The top graph is the output after AHRS after passing it the accelerometer + gyro data. the one in the bottom is raw data of just the acc. I'm not quite sure how to interpret the AHRS representation

screen shot 2017-10-29 at 8 08 17 pm
psiphi75 commented 7 years ago

Yes, AHRS output values look strange. To me it looks like the input axes are around the wrong way. Make sure the gyro and accelerometer axes are aligned. For instance, the gyro x-axis should rotate around accel x-axis. Make sure you are getting unfiltered gyro and accelerometer data, filtered data won't work well. To begin with try to feed it the highest rate data you can (works best that way).

Also if you can, use the deltaTimeSec value, e.g. 0.01 for 10 ms. To do this without the magnetometer, do the following:

ahrs.udpate(gx, gy, gz, ax, ay, az, undefined, undefined, undefined, deltaTimeSec);

As input, the direction of g might have to be negative (e.g. around -1.0).

pliablepixels commented 7 years ago

Thank you. I'll remove gyronorm and work with raw accelerometer/gyro data and will also incorporate your suggestions. Will post an update - my car is in the auto shop for the next 2 days, so I'll just be doing controlled hand swing tests till then (much to the amusement of my kids) :)

psiphi75 commented 7 years ago

How did it go in the end?

pliablepixels commented 7 years ago

Very confusing to be honest. I'm wondering if I'm doing this right. My key goal is to get all 3 axes of the accelerometer in the direction of motion of the car irrespective of how the phone is kept. What I'm seeing now as I drive is the AHRS axis does change as I twist and turn the phone. The device I am on is an iPhone.

That being said, I got drawn into some other issues and couldn't collect all the data yet. I plan to do that over the next week. Would you prefer I close this issue and continue the conversation when I have data? I'm fine with that, if you'd like.

pliablepixels commented 7 years ago

I'm closing this for now - I need to re-assess my approach for this problem - thank you for helping! I'll reopen this once I figure out exactly what I need to track to meet my goals.