Parsing LSM6DSL raw values
Asked Answered
C

1

8

I'm trying to parse the values given from a device with a LSM6DSL chip (gyroscopic and acc.) and I'm having a hard time parsing the data properly for positioning and angle.

From the vendor I've received the information that the unit is running on a resolution of 2000 for the gyro, 8g for the acc.

I receive the data in bytes that are converted by the following to shorts;

public int[] BufferToMotionData(byte[] buffer, int segments = 2)
{
    int[] motionDataArray = new int[segments * 3];
    int offset = Constants.BufferSizeImage + Constants.CommandLength;

    for (int i = 0; i < 6; i++)
    {
        motionDataArray[i] = BitConverter.ToInt16(buffer, offset + (i * 2));
        if (motionDataArray[i] >= Int16.MaxValue)
            motionDataArray[i] -= 65535;
    }

    return motionDataArray;
}

(Edit; Cleaned up version)

This returns values in the range of (example) 961, -16223, -1635, 664, -269, -597.

According to the spec sheet I'm supposed to multiply each vector with it's corresponding value.. * 70f for gyro, .448f for acc.

From the documentation I understand that for the G forces these are in milliG's and gyro in millidegrees per sec?

// Gyro X,Y,Z
gx = Mathf.Deg2Rad * (motionData[0] * 70f / 1000f);
gy = Mathf.Deg2Rad * (motionData[1] * 70f / 1000f);
gz = Mathf.Deg2Rad * (motionData[2] * 70f / 1000f);

// Acc X,Y,Z
ax = motionData[3] * 0.488f / 1000f;
ay = motionData[4] * 0.488f / 1000f;
az = motionData[5] * 0.488f / 1000f;

Update(gx, gy, gz, ax, ay, az);

Update(..) is Madgwick's quaternion formula, although for velocity I use the acceleration vectors.

G force values that I'm getting at this moment after calculation;

X 0.047824 Y -0.320128 Z  0.006344
X 0.07076  Y -0.2562   Z  0.020008
X 0.099552 Y -0.063928 Z -0.13664

These look awfully low, and if applied as velocity it just runs off in a given direction, I know I'm missing a gravity correct although not entirely sure how to apply this.

I'm under the assumption that I do not need to apply drag to my velocity vector since values should be negated by the acceleration values received?

Anyone with experience with this type of chip and actually applying the values to yaw/pitch/roll (or quaternion) and applying the G forces as linear acceleration.

Combs answered 20/6, 2019 at 13:26 Comment(8)
BitConverter.ToInt16(new[] { buffer[offset + 0], buffer[offset + 1] }, 0); is an unnecessarily complicated way of writing BitConverter.ToInt16(buffer, offset + 0) (aside from whether these results are correct in the first place).Embark
The buffer contains 320016 bytes of data in total, the offset defines where to start (int offset = Constants.BufferSizeImage + Constants.CommandLength;), so yes - that would work, but passing a 320kb buffer to a method (non-ref) is not really performance oriented.Combs
Yes, and my point is that explicitly newing up an array with just two bytes that you always read from the beginning is functionally the same thing (but less efficient) than just reading those two bytes directly from offset. (byte[] is a reference type and BitConverter doesn't copy anything, so I'm not sure what your remark about performance is about.)Embark
I do not have the budget to allow 2MB of GC pressure per pass (6x passing 320KB copies), the memory usage of creating 6 new arrays with a few lookups takes less than a KB).Combs
I may be confused here, but what's the type of buffer? Are you using unsafe code and a pointer so you can't call BitConverter.ToInt16(buffer, ...) directly? Otherwise, you seem to be under the impression that passing an array to a method copies it -- it does not.Embark
I was under that impression indeed. Assumption that a value typed array was itself still a value typeCombs
If you convert the two bytes to an Int16 (short), how can it ever be bigger than Int16.MaxValue? Did you want to convert to UInt16? Other question: is the byte order correct? (big vs. little endian)Fission
Was converted out of python code - yeh might be a bit useless. Byte order should be correct (LSB,MSB ->)Combs
N
2

By looking on existing code on GitHub, it's looks like the sensitivity factor for 8g is 244 µg/digit and not 488 µg/digit as you coded it.

Also it look's like raw values are shifted and are in [-r/2,r/2] instead of [0, r]. So you have to add 500µg or 500µdps to it. (But maybe it's linked to a uint/int issue, anyway are you sure about the endianness?)

See here for acc data and here for gyro data.

Based on that, the code should look likes this:

// Gyro X,Y,Z (in rad/s)
gx = Mathf.Deg2Rad * (motionData[0] * 70000f + 500) / 1000000;
gy = Mathf.Deg2Rad * (motionData[1] * 70000f + 500) / 1000000;
gz = Mathf.Deg2Rad * (motionData[2] * 70000f + 500) / 1000000;

// Acc X,Y,Z (in g)
ax = (motionData[3] * 244f + 500) / 1000000;
ay = (motionData[4] * 244f + 500) / 1000000;
az = (motionData[5] * 244f + 500) / 1000000;

Update(gx, gy, gz, ax, ay, az);
Noise answered 26/6, 2019 at 15:0 Comment(3)
I've tried pretty much all sensitivities in case the reported value by the vendor was wrong. So far I've gotten nowhere :x, will try this, thanks!Combs
This has pushed me in the right direction and I'm getting way more plausible data values, thank you :)Combs
Thank @DevionNL, please bring use the correct final code.Noise

© 2022 - 2024 — McMap. All rights reserved.