So, I’ve got a magnetometer on the front hanger, and another on the rear hanger. 2x sensors providing 3-axis XYZ data about the magnetic field.
What’s the best way to calculate a single variable (angle of the deck) from these six magnetic field strengths?
This is all about building a pipeline for calibration. Everything I explained here is done entirely behind the scenes… To redo calibration, all that’s required is running the Magnetic TITS Calibration Tool and (slowly) sweeping the board across the range of motion.
Why it’s a complicated problem
Measuring rotation from a magnetic field is a very common engineering problem, even in esk8. There’s plug-and-play integrated circuits that output degrees of rotation. In fact, most hall effect remotes use these.
However, sensing 3-link truck angles isn’t that simple.
- 3-links don’t rotate around a static axis (like channel trucks do). Their axis of rotation changes throughout the rotation, so it’d be impossible to properly locate a sensor/magnet for simple rotation (because it constantly changes)
- This axis also changes when linkage angles change, so even if it was possible, I’d need to re-glue magnets and re-mount the sensor whenever I changed linkage setup.
- I don’t trust my magnets to be high-quality enough to be uniform
- My magnet and sensor mounting is never going to be perfect
I decided that using XYZ magnetometers is going to get me the more accurate measurement possible because of the lower-level control and increased data throughput (at the cost of increase software complexity).
So, calibration?
Calibration is the process of correlating sensor values with a “ground truth”
Then, during operation, you go the opposite direction, calculating the truth from the sensor value.
Because this is going to need to be repeated anytime I change linkages or touch the sensors, I wanted to automate the process as much as possible.
Introducing, the Magnetic TITS Calibration Tool
This Matlab software runs on my PC. It connects to TITS over USB, which reads sensor values.
On the TITS PCB, I have a high-accuracy IMU that measures acceleration and rotational rate. If the IMU is not moving and the board is on a flat surface, the angle of gravity will be equal to the angle of the deck. Easy to calculate with some basic trigonometry!
X-Axis Offset
You might have noticed the accelerometer zero button on the tool.
Ever since my collision with Redbeard at Apex, Ankle Wreacher’s front box has been.. not straight.
Only a few degrees, but enough to be significant. To avoid this affecting the accuracy of my calibration, I do a coordinate transform (defined by the accelerometer’s zero calibration) to rotate all measured accelerations to the deck’s reference frame, correcting for this misalignment.
A nice side effect of this reference frame transform is that it would allow TITS to be mounted on an angle-tipped deck in the future, if I ever wanted to.
If I then record the measured magnetometer values in the same instant, I’ve got a record of what magnetic field strength to expect that that amount of deck lean.
This is what the Magnetic TITS calibration tool does! It automatically records data, tossing out anything where the the board is moving (which would throw off the calculated gravity vector).
Rotating the board full left and right, this is what the raw data looks like.
Great! There’s a strong correlation between deck angle and the measured magnetic field, on all axis’s. Sone cool things to notice:
- For a given amount of deck lean, the front sensor measurements change way more then the rear sensor. This makes sense, because my steering is front-biased
- The measured magnitudes are not sinusoidal in shape. This reinforces my hunch that I wouldn’t be able to use a simple rotational encoder (and that selecting magnetometers was the right choice)
- The rear data shows some interesting hysteresis on the Z axis(yellow). Speculation on this later.
Because we exist in the real world, we’ve got to deal with the sensor noise.
This is where the real math arrives.
Calibration algorithm
I spent a long time thinking about this algorithm. It needed to be
- Accurate and repeatable
- Robust to interference from stray magnetic feilds
- Shouldn’t break if something slightly shifts while I’m riding
- Feedback about the quality of calibration (and if re-calibration is needed)
I can use the XYZ magnetic field magnitudes as coordinates in a 3D XYZ plot, color is the deck angle. Hopefully you’re able to see that all the points exits on a single line through the space, and that the deck angle (represented here by the color) changes continuously along the line.
After some processing, I’ve get a single “idealized line” through magnetic state space that defines the relationship between deck angle and measured magnetometer values.
Now, when I measure the magnetometers and want to know the angle of my deck;
- Plot the point in the XYZ magnetometer state space
- Snap the point to the nearest location on the idealized line
- The calibrated “deck angle” at that point of the idealized line is almost certainly the current angle of the deck
Here’s a graph that kinda visualizes the process;
Because there will always be a “closest” location on the line, this means that it should never fail to find a solution.
Even cooler, the distance correlates to the calibration quality!
If something changes that makes the calibration invalid, suddenly the distances of any new measurements to the idealized line will be very far. Should make it easy to implement fault detection down the line (allowing TITS to detect and compensate for a fault sensor/broken magnets)
Checking my work
Using my recorded calibration data to test the accuracy of this algorithm, I get a graph of how accurate the calibration is. These graphs are so fucking cool, you have no idea.
- The front sensor is incredibly accurate, calculating the deck angle to within ±0.5 degrees!
- The front sensor also shows a nearly perfect Gaussian distribution. This makes me think that this is the maximum accuracy I can expect to achieve without a sensor upgrade (as sensor noise is almost always gaussian)
- Rear sensor is less accurate (±1 degree), It shows a bimodal distribution of data.
Bimodal distribution?
Basically, showing two distinct peaks (example from google)
Looking at the raw data, it has hysteresis(as I mentioned before). Basically, the measured data depends on the direction you approach it from. This would explain the bimodal distribution, as the ““theoretically true”” magnetic value is either over or under measured by the magnetometers. (another example from google)
I scratched my head for awhile trying to figure out the source of this.
Multiple recalibrations showed the same thing. Try to guess, its fucking cool.
- The “true” value of deck angle comes from the accelerometer at the front of the board.
- The front trucks don’t show a bimodal distribution because they’re much closer to this “truth” sensor
- I stood on the board during the calibration, and swept it from full left, full right, then full left.
- Drag on the wheels/gears caused the chassis to twist, causing the rear trucks to lag slightly behind the front trucks.
In other words, my sensors are so accurate that they’re able to pick up the torsional twist of a chrome-oly steel V5 Chassis
Standing on the board and… yeah. That looks like a degree or two of twist ![]()
Now what?
I still need to write the C++ version of the algorithm that will actually run on TITS, but that’s probably going to take a day or two of work.
Once I get that written, not entirely sure. I want to start analyzing on-track data (see how it looks). I’m very excited to see truck angle data correlated with other stuff like GPS, accelerations, turning radius, power, etc. Should be really cool.








