Skip to main content

Coordinate Frames

A stream can be perfectly valid and still produce a pose that is upside down, mirrored, or facing the wrong way. Rotations are only meaningful relative to a frame, and nothing in the numbers says which frame they came from. These settings supply that missing information.

Four things have to be right, and each fails differently — which is what makes them diagnosable.

1. Axis conversion — which way is up

Axis conversion tells LABO the coordinate convention your sender uses.

OptionConventionTypical source
NedToUnity+X north, +Y east, +Z downInertial sensors with magnetometers
EnuToUnity+X east, +Y north, +Z upInertial sensors, the other common convention
OpenSimGroundToUnity+X forward, +Y up, +Z rightBiomechanics pipeline output
NoneAlready Unity's conventionA sender that converts before sending

Symptom when wrong: the body is upside down, lying down, or mirrored. Not subtly off — grossly wrong, and wrong the same way every frame.

Work it out from your data, not from the label

If your sensors also record accelerometer data, you can determine the convention instead of guessing. A stationary sensor measures gravity. Rotate a still sensor's accelerometer reading by its own reported orientation and see which world axis the result lands on: a value near (0, 0, -1) g means +Z points down, which is NED.

Column headers named for body segments tell you where a sensor was taped, not what frame its numbers are in. Those are different facts and they are easy to conflate — a recording processed by a biomechanics tool can carry that tool's segment names while the quaternions are still in the sensors' own frame.

2. Calibration reference — cancelling the mounting

A sensor is strapped to a limb at whatever angle the strap happened to sit. Nobody knows that angle, and it differs for every sensor and every session.

Neutral reference solves this without measuring anything. Have the participant hold a known static pose, capture what every sensor reads in that pose, and express everything afterwards relative to it. The unknown mounting angle is present in both the reference and the live data, so it cancels — exactly, not approximately. Rotating a sensor arbitrarily on the limb before the session changes the resulting pose by nothing.

That cancellation is worth understanding, because it also explains what the reference cannot fix. It removes everything on the body side of the measurement: how the sensor sat on the limb, which strap it used, which way the palm faced. It removes nothing on the world side, which is why heading remains a separate setting below.

SettingWhat to do with it
Neutral referenceLeave on. Off means raw orientations, which still carry the mounting angle.
Reference average (s)How long to average. 1 second is the default; longer is steadier.
RecaptureCapture again, in Play mode, while the participant holds the pose.

The reference comes from the first packets that arrive. So whatever you send first must be the participant holding still. Enter Play mode before starting your sender — if LABO joins a stream already in progress it takes its reference from the middle of a movement, and everything afterwards is offset by whatever pose they happened to be in.

Symptom when wrong: every joint carries a constant offset. The motion is right; the resting pose is not.

3. Calibration pose — which pose they were holding

Calibration pose says which static pose the participant held while the reference was captured.

OptionThe pose
NPoseStanding, arms down at the sides, palms forward.
TPoseStanding, arms straight out to the sides at shoulder height, palms down.

This is not a label — it changes the result. The reference records a deviation from the pose the participant held, and LABO composes that onto the matching pose in the skeleton. Say T-pose when they were standing with their arms down and both arms carry a constant 90° of shoulder abduction for the entire session.

Symptom when wrong: arms held out sideways when the participant's arms are down, or the reverse. The motion still happens, 90° out.

N-pose is the more common choice for clinical work, because participants with restricted range of motion often cannot reach a T-pose.

4. Heading offset — which way they were facing

Heading offset is yaw: which direction the participant faced relative to the sender's world frame.

Why it is a setting and not a measurement

An inertial sensor fixes its world frame from two references, and they do different amounts of work.

Gravity gives it two axes. Every sensor can feel which way is down, at rest and on average during movement. That pins the vertical, and with it pitch and roll — enough to know a limb is horizontal rather than vertical.

It gives no third axis. Rotation about the vertical is exactly the direction gravity cannot distinguish, because turning on the spot does not change which way down is. So gravity alone leaves yaw free.

Magnetometers fill that in with magnetic north, which is why quaternions from a sensor with a magnetometer are north-referenced. That makes the readings consistent between sensors and stable over time — but north is a fact about the room, not about the participant. Knowing a limb points north-north-east says nothing about whether that is in front of the person or behind them, and no amount of sensor data answers it. The one missing number is the angle between north and the participant's forward, and it has to come from you.

Which also makes it per-session. Re-seat the participant, turn the chair, run in a different room, and it changes. It is not a property of the equipment.

What it is not

Two things get blamed for this and neither can cause it.

Not the sensor mounting. A sensor taped on crooked, a palm rotated in the strap — none of it matters, because the mounting appears in both the calibration reference and the live data and cancels exactly when one is expressed relative to the other. Rotating a sensor arbitrarily on the limb moves the resulting pose by nothing at all. That cancellation is what makes casual taping acceptable, and it is also why heading survives: the mounting is on the body side of the equation and cancels, while heading is on the world side and does not.

Not the calibration pose. That one is worth checking, but its symptom is different and unmistakable — a constant 90° at the shoulders, described above.

Getting the number

Point the estimator at your recordings:

pip install numpy
python estimate_imu_heading.py --dataset path/to/recordings

It finds the yaw that puts the participant's plane of movement where the avatar's is, then prints it. Or sweep the slider in Play mode until a movement whose direction you know — a forward reach is ideal — moves the avatar the same way.

Which movement it measures matters more than it looks. The estimate comes from a movement that stays in one anatomical plane, and the fitted axis is only as horizontal as the movement was planar. Trunk flexion is excellent for this; the shoulder is poor, because it is a ball joint and few people flex it without some abduction or rotation creeping in. On one six-sensor upper-body dataset, fits taken from the humerus landed 16–17° off horizontal and disagreed with each other by 54°, while fits from the trunk came out under 1° off and agreed within 9°. The estimator reports that elevation figure for every trial it fits and answers only from the ones that pass, so read the table rather than the headline number.

Symptom when wrong: the pose is upright, correctly handed and correctly proportioned; every joint bends by the right number of degrees; but the whole plane of movement is rotated. A forward reach travels across the body instead. A drink to the mouth arrives beside the ear. Because nothing about the pose is broken, this reads as a rigging or retargeting fault, and that is the trap — it is one number in one field.

Judge heading by direction, never by a joint angle

Peak elbow flexion, or any other joint-angle magnitude, reads the same whatever the heading is set to — the maths makes those magnitudes independent of the frame. A number that cannot change cannot confirm anything. Use a direction instead: a forward reach should move the avatar forward, with little sideways drift.

Diagnosing in order

The four fail in distinguishable ways, so work top to bottom and each step's result is unambiguous:

What you seeSetting to check
Scrambled — not a plausible body at allQuaternion order (Wire format)
Upside down or mirroredAxis conversion
Constant offset at every jointNeutral reference — was it captured while they were still?
Arms 90° from where they should restCalibration pose
Correct pose, but reaches land in the wrong directionHeading offset

There is no point sweeping heading until the body is the right way up — a wrong axis conversion makes the heading impossible to judge. Fix in the order above and each setting is testable on its own.