# How to align 2 IMUs' quaternions?

Suppose I have 2 IMUs that output 2 quaternions.

I place one IMU on my left hand and another one on my right hand.

I put both my hands flat on the table and point it forward to the same direction. What I expect is that they should give very similar quaternion. But it turns out that the IMUs reading differs about 10-20 degrees around the Y axis when plotted in Unity3D.

This means I cannot just apply the quaternion to the hand model inside Unity directly. I need to know the exact offset of this 10-20 degrees error in order to make the hand model point in the same direction.

How do I figure out this offset automatically? Or is there another way that I can align both IMUs? How do people deal with this IMU problem?

PS. Putting the IMU on the hand is just an example. I can put them both directly on the table near each other and they still give slightly different quaternions.

• Is this offset between them consistent, like a calibration error? eg. if I measure the offset, then pick up both IMUs and dance around with them for a bit, then put them back down in the same orientations as before, will I measure the exact same offset, or has some drift occurred? Also, are these 6-axis IMUs (accel + gyro) or 9-axis MARGs (accel + gyro + compass)? Nov 15 '18 at 11:12
• It is 9-axis. The offset is quite fixed like a calibration error. If I know the offset and I dance around with it the offset will probably change but very little. But I will be satisfied if I know that starting offset or even better if I also know the new offset all the time. But this offset will change a lot in different sessions so I cannot just find the offset first time and use it all the time because it will drift. I need to find a way to detect the offset in each session or find how people deal with this another way. Nov 15 '18 at 12:35
• Do your IMUs offer any type of calibration process for the compass? (Ever see Google Maps ask you to steer your phone around in a figure-8 pattern a few times? That's what it's doing there) Nov 15 '18 at 12:38
• Yes it offer a calibration but only by the developer. User cannot do it after it's in production. Nov 15 '18 at 12:44
• Maybe I need to create a way for user to calibrate it but this seems like a universal problem on how to figure out the offset. I think someone might have already figured it out. Am I right? Nov 15 '18 at 12:46

The resting yaw rotation is determined by the magnetometer - it's the only one of the three sensors that has an absolute reference direction in the horizontal plane.

Unfortunately, it's also the most fiddly of the sensors. Metal components inside the device can cause its detected magnetic field vector to be shifted (hard iron distortion) or stretched/rotated/skewed (soft iron distortion).

The most robust way to solve this is to calibrate the device prior to use.

If you ask the user to tumble the sensor around in all directions, the magnetic field vector that you read from the magnetometer will trace out an ellipsoid. Once you have enough samples around the whole surface of the ellipsoid, you can estimate its shape. You can then compute a minimal transformation that maps the ellipsoid to a unit sphere centered at the origin.

This can be as simple as keeping track of the min & max you've observed on each axis, shifting the result by - (min+max)/2 and scaling it by 2/(max - min), though if you have substantial soft iron distortions that skew/rotate your ellipsoid, or misalignments of the sensor chip itself, you may need a more sophisticated correction.

Now you can apply this calibrating transformation to your magnetic field samples before passing them as input to your routine to estimate the device orientation. This should minimize the differences in the two devices' estimates.

A simpler but less robust calibration you can try is to ask the user to set the two devices on a flat surface in a standard orientation (it helps if the devices have a flat bottom to rest on, and a clear line somewhere to point forward).

Wait a moment for the orientation estimate to settle, then compare the quaternions you get from each device.

// Total difference in orientation.
// (Optionally, you can filter this to consider only the difference in yaw)
Quaternion AtoB = deviceB.rotation * Quaternion.Inverse(deviceA.rotation);

// We'll average-out the two and meet in the middle:
// correcting A halfway to B's orientation,
// and B halfway to A's.
Quaternion aCorrection = Quaternion.Lerp(Quaternion.identity, AtoB, 0.5f);
Quaternion bCorrection = Quaternion.Inverse(aCorrection);


Now you can apply this correction as

Quaternion correctedA = aCorrection * deviceA.orientation;
Quaternion correctedB = bCorrection * deviceB.orientation;


The reason I say this is less robust is because it assumes the same yaw offset applies all the time - but this can be sensitive to the orientation of the device. You could repeat the calibration process in multiple orientations (standing on end, on its side, etc...), saving multiple different correction quaternions, and then blend between them depending on the current device orientation. We're still treating the symptom here (differing yaw estimates) rather than the root cause (differently-biased magnetometer readings).

• Does the user need to align 2 devices when calibrating or they can just put it on the table pointing anywhere? Nov 16 '18 at 6:59
• They need to align the devices "in a standard orientation" as described above. We're using the user as our source of truth to isolate the offset between the two devices' readings. Without that, we can't distinguish what component of the rotation data is error versus what part is legitimately the direction the real device is oriented. Nov 16 '18 at 9:09
• For example, the user needs to point the IMU exactly in the same direction and then calibrate right? That's what I've been doing but it's hard to instruct the user to point the IMU in the same direction or some standard specific direction. Nov 16 '18 at 9:55
• You either need to fix the bias at its source (the first method) or estimate the offset symptom and correct for that (second method). To estimate the the offset, we need to know how much of the difference between the rotations is this error, and how much is because the user is literally pointing them in different directions. Otherwise we risk "correcting" an error offset that was actually a real rotational difference in how the user was holding the devices. We can't use an internal measure for this, because we know our internal measure is untrustworthy — that's exactly the problem we're fixing Nov 16 '18 at 12:53