IMU Coordinate Frame (Proto0)

Proto0 carries a Bosch BMI270 6-axis IMU (3-axis accelerometer + 3-axis gyroscope) on SPI. See fw/docs/proto0-board-pinout.md for its pin assignments and fw/src/imu/imu.cpp for the driver integration (samples both accel and gyro at 25 Hz off the BMI270 data-ready interrupt).

The frame is the raw chip frame

The BMI270 devicetree node (fw/boards/others/rgb_sunglasses_proto0/rgb_sunglasses_proto0_nrf5340_cpuapp_common.dts) has no mount-matrix and no rotation applied. The firmware therefore consumes the sensor's axes exactly as the part is soldered on the boardaccel[0]/gyro[0] is the chip's physical +X, and so on. There is no software remap anywhere in the pipeline, so these photos are the authoritative description of what each axis means on the wearer's head. If a future board revision rotates the part, either add a mount-matrix to the devicetree or update this document (and the images).

Axes as worn

Coordinates are given for the glasses worn normally, head upright and level.

Axis Points toward… Anatomical Rotation about it (gyro)
+X (red) the crown / straight up superior yaw — "no". Positive = turning left
+Y (green) out the left temple wearer's left pitch — "yes". Positive = nose down
+Z (blue) out the back of the head posterior roll — ear to shoulder. Positive = crown tips left

This is a right-handed triad (X × Y = Z). Gyro output for each axis is the angular rate about the corresponding accelerometer axis, positive per the right-hand rule.

Annotated views

In every photo the same triad is drawn — red = X, green = Y, blue = Z. The straight arrow(s) lie in the image plane; the curved arrow is the axis pointing roughly along the camera direction (toward or away from the viewer), drawn as an arc because it would otherwise be foreshortened to a dot.

Front — facing the wearer:

Front view of the glasses worn, IMU axes annotated

Back — behind the wearer, showing the rear electronics module:

Back view of the glasses worn, IMU axes annotated

Left side of the wearer:

Left-side view of the glasses worn, IMU axes annotated

Right side of the wearer:

Right-side view of the glasses worn, IMU axes annotated

Top-down — looking down at the crown, eyes at the bottom of the frame pointing at the floor:

Top-down view of the head, IMU axes annotated

Top-up — the same top view with the head tipped back the other way:

Top-up view of the head, IMU axes annotated

Bench verification

Both the accelerometer frame and the gyro polarity were verified on Proto0 hardware (2026-08-24, fw v3.4.0-stable) with the on-device capture path — capture start <seconds>, whose .csv sidecar logs raw ax,ay,az,gx,gy,gz at 25 Hz. The axis directions above are measured, not inferred.

Accelerometer. The glasses were held stationary in six orientations; the axis pointing up reads +1 g. Every reading matched the table (m/s²):

Orientation (as worn) ax ay az
Upright, level +9.95 +0.83 −0.01
Upside down −9.61 −0.49 −0.72
Right temple down −0.10 +9.78 −0.14
Left temple down −0.18 −9.84 −0.52
Face down +0.01 +0.21 +9.87
Face up +0.29 −0.19 −9.84

Off-axis terms are hand-held pose error (≤ 6°); every vector magnitude fell in 9.65–9.98 m/s², i.e. 1.00 g.

Gyroscope. Measured directly by sweeping briskly in the named direction and returning slowly: gx peaked +6.6…+8.2 rad/s on left yaws, gy +10.6…+13.9 on nose-down pitches, gz +5.4…+6.6 on left rolls — each with the slow return reading the opposite sign.

Those signs were then cross-checked against the accelerometer's own gravity reading — a test that does not depend on the motions having been performed as intended — agreeing with median cosine similarity 0.92 (X), 0.91 (Y), 0.89 (Z). The gyro triad is therefore right-handed with respect to the accelerometer axes above, which pins the polarity by the right-hand rule.

Method, and the two ways it silently produces a false negative: fw/CLAUDE.md, "Validating the IMU coordinate frame on hardware".