Adds the Balance Bot's IMU, its filter and the two derived sensors
Mounts the BMI323 where it actually sits on the board, nests a Mahony filter
in it to fuse an orientation, and adds the two sensors that turn that
orientation into joint configurations the rest of the robot can use:
BB.NSK.Sensor.Lean on :lean and BB.NSK.Sensor.Heading on :ground.
After this BB.Robot.State carries a lean that means something, which is
what bb_nsk.add_balance closes its loop around.
Why the mounting is two joints
The chip publishes in its own axes and a sensor has no origin of its own —
the link it hangs off is its frame — so the mounting is a pair of links, and
everything downstream gets the transform from the kinematics rather than
hard-coding an axis swap.
Where it sits and how it is turned are separate joints because
BB.Math.Transform.from_origin/1 composes the rotation before the
translation, so one origin carrying both would place the chip at its own
offset seen through its own quarter turn — 29.5mm forward of the wheel axis
instead of 29.5mm above it.
The rotation itself was read off the gravity vector in two attitudes rather than off the silkscreen: on its back the whole g lands on the chip's +Z, and on its wheels it lands on -Y.
Why Mahony rather than Madgwick
Both fuse the same two signals, and both have one gain saying how hard the accelerometer may pull the estimate around. That gain has to be small here: an accelerometer cannot tell leaning from accelerating, and this robot accelerates hardest exactly when it most needs the lean to be right. At Madgwick's default of 0.1 the robot balanced for one to two seconds no matter what else was tuned.
But a small gain also washes gyroscope bias out slowly, and bias moves with
temperature and time since power-on — which reads as a balance point that
wanders between attempts. Madgwick has no answer to that; its only dial is
the one already needed low. Mahony estimates the bias separately with ki,
so the two jobs stop fighting over one number.
Example
mix bb_nsk.add_imu
Options
--robot- The robot module (defaults to{AppPrefix}.Robot).