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.

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
DevionNL
  • 142
  • 1
  • 12
  • 1
    `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). – Jeroen Mostert Jun 20 '19 at 13:38
  • 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. – DevionNL Jun 20 '19 at 13:54
  • 1
    Yes, and my point is that explicitly `new`ing 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.) – Jeroen Mostert Jun 20 '19 at 13:59
  • 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). – DevionNL Jun 20 '19 at 14:04
  • 2
    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. – Jeroen Mostert Jun 20 '19 at 14:09
  • I was under that impression indeed. Assumption that a value typed array was itself still a value type – DevionNL Jun 20 '19 at 14:11
  • 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) – slfan Jun 26 '19 at 15:47
  • Was converted out of python code - yeh might be a bit useless. Byte order should be correct (LSB,MSB ->) – DevionNL Jun 27 '19 at 08:26

1 Answers1

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);
Orace
  • 7,822
  • 30
  • 45
  • 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! – DevionNL Jun 27 '19 at 08:19
  • This has pushed me in the right direction and I'm getting way more plausible data values, thank you :) – DevionNL Jun 27 '19 at 14:25
  • 1
    Thank @DevionNL, please bring use the correct final code. – Orace Jun 27 '19 at 15:08