[Feature] User IMU calibration implementation
We are introducing a builtin routine to calibrate the IMU on all three axes. The user is instructed to place the hub in a particular orientation, and then to rotate the hub towards the user several times. This is repeated for each axis.
The instructions are currently text-only. Ultimately, this should be paired with a visual animation from the Pybricks Code IDE.
To try it out (updated 2024-12-03)
- Install the latest firmware.
- On the REPL, run
import _imu_calibrateand follow the instructions.
To see the results afterwards, do:
print(hub.imu.settings())
The values remain on the hub until you install a new firmware. You can then run the calibration again, or simply restore the values you printed above.
Hub specifics
The SPIKE Prime Hub casing is close enough to a rectangular box. You can just rotate it in place, as in the video below.
The Technic Hub sides aren't really flat enough. You can add some Technic elements like Bert did below.
Video
This video is slightly outdated now, but it shows the gist of the procedure.
https://github.com/user-attachments/assets/b118ad6b-5b84-4ee1-8175-d16cc2676f99
Original post
Click to see original post
The technical aspects of calibration are being discussed in https://github.com/pybricks/support/issues/943, this issue is more about the user routine: How can we make it easy for the user to calibrate their gyro? This is an alternative to https://github.com/pybricks/support/issues/1678 to be ready for 3D. It is a bit simpler too since you don't need an external reference.
This would have to be done just once and the results would be saved persistently on the hub. You'd have to do it again if you updated the firmware. This will calibrate the accelerometer and gyro all in one go.
The procedure is as follows, three times. It takes a bit of practice, but it is easy to do.
- Place the hub in an indicated starting position.
- Roll it towards you 4 times without lifting it up.
We could animate this visually in a Pybricks Code pane. This is roughly what the user would have to do:
https://github.com/user-attachments/assets/b118ad6b-5b84-4ee1-8175-d16cc2676f99
(Video is cut off. This repeats one more time for the final axis.)
Instructions
- Install this firmware.
- Run the following. Rough instructions are shown in Pybricks Code. (We'll clean that up later.)
from pybricks.hubs import ThisHub
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor
from pybricks.parameters import Button, Color, Direction, Port, Side, Stop, Axis
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch, vector
hub = ThisHub()
def wait_for_stationary(side):
while not hub.imu.stationary() or hub.imu.up() != side:
wait(10)
up_sides = {
Side.FRONT: (0, 0, 1),
Side.BACK: (1, 0, -1),
Side.LEFT: (2, 1, 1),
Side.RIGHT: (3, 1, -1),
Side.TOP: (4, 2, 1),
Side.BOTTOM: (5, 2, -1),
}
gravity = [0] * 6
bias_count = 0
bias = vector(0, 0, 0)
_, _, _, old_scale, _, = hub.imu.settings()
def roll_over_axis(axis, new_side, first=False):
global bias, bias_count
if first:
print("Roll it over towards you, without lifting the hub up!")
else:
print("Roll towards you again!")
angle_start = hub.imu.rotation(axis)
while hub.imu.up() != new_side or not hub.imu.stationary():
x, y, z = hub.imu.orientation() * axis
if abs(z) > 0.05:
print(hub.imu.orientation() * axis)
raise RuntimeError("Oops, lifted it!")
wait(100)
rotation = abs(hub.imu.rotation(axis)-angle_start)
if abs(rotation - 90) > 10:
raise RuntimeError("Rotated too far or not far enough!")
print("Nice work. Calibrating now...")
hub.speaker.beep(1000)
wait(10)
rotation_start = vector(
hub.imu.rotation(Axis.X),
hub.imu.rotation(Axis.Y),
hub.imu.rotation(Axis.Z)
)
COUNT = 1000
acceleration = vector(0, 0, 0)
for i in range(COUNT):
acceleration += hub.imu.acceleration(calibrated=False)
bias += hub.imu.angular_velocity(calibrated=False)
bias_count += 1
wait(1)
acceleration /= COUNT
rotation_end = vector(
hub.imu.rotation(Axis.X),
hub.imu.rotation(Axis.Y),
hub.imu.rotation(Axis.Z)
)
if abs(rotation_end - rotation_start) > 1:
raise RuntimeError("Too much rotation while calibrating")
side_index, axis_index, axis_direction = up_sides[new_side]
# Store the gravity value for the current side being up.
# We will visit each side twice. The second time the gravity value will
# already be nonzero, so we can take the average between two to get
# slightly better results while we're here anyway.
acceleration_previous = gravity[side_index]
acceleration_now = acceleration[axis_index]
if abs(acceleration_previous) > 1:
acceleration_now = (acceleration_now + acceleration_previous) / 2
gravity[side_index] = acceleration_now
# Todo, expose unscaled version in api?
unadjusted_rotation = rotation * old_scale[axis_index] / 360
hub.speaker.beep(500)
return unadjusted_rotation
calibrate_x = """
We're going to calibrate X now!
- Put the hub on the table in front of you.
- top side (display) facing up
- right side (ports BDF) towards you.
"""
calibrate_y = """
We're going to calibrate Y now
- Put the hub on the table in front of you.
- top side (display) facing up
- back side (speaker) towards you.
"""
calibrate_z = """
We're going to calibrate Z now!
- Put the hub on the table in front of you.
- front side (USB port) facing up
- left side (ports ACE) towards you
"""
print(calibrate_x)
wait_for_stationary(Side.TOP)
hub.speaker.beep()
rotation_x = roll_over_axis(Axis.X, Side.LEFT, first=True)
rotation_x += roll_over_axis(Axis.X, Side.BOTTOM)
rotation_x += roll_over_axis(Axis.X, Side.RIGHT)
rotation_x += roll_over_axis(Axis.X, Side.TOP)
print(calibrate_y)
wait_for_stationary(Side.TOP)
hub.speaker.beep()
rotation_y = roll_over_axis(Axis.Y, Side.FRONT, first=True)
rotation_y += roll_over_axis(Axis.Y, Side.BOTTOM)
rotation_y += roll_over_axis(Axis.Y, Side.BACK)
rotation_y += roll_over_axis(Axis.Y, Side.TOP)
print(calibrate_z)
wait_for_stationary(Side.FRONT)
hub.speaker.beep()
rotation_z = roll_over_axis(Axis.Z, Side.RIGHT, first=True)
rotation_z += roll_over_axis(Axis.Z, Side.BACK)
rotation_z += roll_over_axis(Axis.Z, Side.LEFT)
rotation_z += roll_over_axis(Axis.Z, Side.FRONT)
print("old: ", hub.imu.settings())
print("applying")
print(bias[0] / bias_count, bias[1] / bias_count, bias[2] / bias_count)
print(rotation_x, rotation_y, rotation_z)
print(gravity)
hub.imu.settings(
angular_velocity_bias = (bias[0] / bias_count, bias[1] / bias_count, bias[2] / bias_count),
angular_velocity_scale = (rotation_x, rotation_y, rotation_z),
acceleration_correction = gravity
)
print("new: ", hub.imu.settings())
To see the "before" and "after" situation, try running the following script before and after doing the calibration routine:
from pybricks.hubs import ThisHub
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor
from pybricks.parameters import Button, Color, Direction, Port, Side, Stop, Axis
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch, vector
from umath import acos, degrees, pi, sqrt
hub = ThisHub()
startx = hub.imu.rotation(Axis.X)
starty = hub.imu.rotation(Axis.Y)
startz = hub.imu.rotation(Axis.Z)
while True:
if hub.buttons.pressed():
startx = hub.imu.rotation(Axis.X)
starty = hub.imu.rotation(Axis.Y)
startz = hub.imu.rotation(Axis.Z)
while hub.buttons.pressed():
wait(10)
x = hub.imu.rotation(Axis.X) - startx
y = hub.imu.rotation(Axis.Y) - starty
z = hub.imu.rotation(Axis.Z) - startz
print(f"{x:10.3f}", f"{y:10.3f}", f"{z:10.3f}", f"{hub.imu.heading():10.3f}")
wait(100)
You might find that before, a flat rotation around each of the axis is not a perfect 360-degree turn. After calibration, it should be. In one of my hubs, this corrects a y-axis rotation from 354 to 360, which is quite a win.
Before calibration: ~364.something and after 360.9. Great.
Was a bit tricky to see what side of the robot inventor has the speaker due to the lighting this time of day. To remind me I added "(under the center button)"
Quite doable calibration scenario.
'naughty ON:' Curious how you will suggest to do the Technic hub 😜 'naughty OFF'
Even if a beam is added at the TechnicHub sides it wobbles on the small ridges on the sides. (not LEGO like)
Tried the Technichub anyway (ignore if I am out of line) see picture below.
All goes well until calibration of the Z side:
We're going to calibrate Z now!
- Put the hub on the table in front of you.
- front side (USB port) facing up
- left side (ports ACE) towards you
Roll it over towards you, without lifting the hub up!
Matrix([
[ 0.082],
[ -0.995],
[ 0.053],
])
Traceback (most recent call last):
File "tool_issue_1907_calibrate_3d.py", line 164, in <module>
File "tool_issue_1907_calibrate_3d.py", line 47, in roll_over_axis
RuntimeError: Oops, lifted it! abs(z) 0.05343884
The z is just a small bit over 0.05.
testhub:
Great step forwards, thank you!
Bert
Stubborn as I am, got a Technic hub calibrated. From 367.069 and after calibration -360.862. That ~~might be~~ is a matchwinner.
I have set the z allowance from 0.05 to 0.06 and used this support for the technichub with 3L axle and "connectors number 1" with half pins in them:
[EDIT] These settings that are automatically retrieved and applied, might make debugging later a bit harder. Should we have a debugging program that shows version / git hash / those settings and indicates the difference from default?
And maybe a program to print the settings to re-load after a firmware change.
The routine is now built into the latest firmware. I have updated the testing instructions. API updates are to follow...
Technic hub:
Pybricks MicroPython ci-build-3625-v3.6.0b2-24-g77eb7529 on 2024-12-03; LEGO Technic Hub with STM32L431RC
Type "help()" for more information.
>>> import _imu_calibrate
Going to calibrate X now!
- Put the hub on the table in front of you.
- top side (display) facing up
- right side (ports BDF) towards you.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_imu_calibrate.py", line 134, in <module>
File "_imu_calibrate.py", line 125, in roll_hub
TypeError: beep() takes 1 positional arguments but 0 were given
>>>
Well sure enough the Technic hub has no speaker :smile:
Fixed now. Nightly firmware has been updated.
Technic hub at ci-build-3628-v3.6.0b2-25-g9e5cd4ca:
Result: (2.0, 2500.0, (-1.053093, 0.2765429, 0.01441465), (361.6532, 361.6852, 365.6783), (9984.508, -9751.642, 9935.678, -9673.925, 10030.06, -9721.781), 360.0)
(Primehub is in a model and the RI-hub still is in "LEGO-mode")
I'm having issues. Could someone help me please? I have tried multiple times.
Pybricks MicroPython ci-build-3643-v3.6.0b2-35-gcc5521fc on 2024-12-10; SPIKE Prime Hub with STM32F413VG
Type "help()" for more information.
>>> import _imu_calibrate
Going to calibrate X now!
- Put the hub on the table in front of you.
- top side (display) facing up
- right side (ports BDF) towards you.
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Going to calibrate Y now
- Put the hub on the table in front of you.
- top side (display) facing up
- back side (speaker) towards you.
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Going to calibrate Z now!
- Put the hub on the table in front of you.
- front side (USB port) facing up
- left side (ports ACE) towards you
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Roll it towards you, without lifting the hub up!
Calibrating...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_imu_calibrate.py", line 146, in <module>
ValueError: Invalid argument
>>>
Thanks for reporting! We should be able to update the test files in a few days.
Thanks for reporting! We should be able to update the test files in a few days.
I studied the code a bit, I can't figure out the error right now. Possibly lack of knowledge in python. Anyway... I'm using the pybrciks code online editor now. Is there a handy way that I can help find the error? E.g. IDE with step through debugging option?
It seems that the calibration passes but it does not succeed in saving it. It does some value checks to avoid saving bad values. For example, it will reject gyro corrections of more than 10 degrees as this might be a user error. But maybe on some hubs the errors are truly 11 degrees, for example.
So could you try running the following adapted script? You can just run it from the online editor. It is the same as before but now it will print the values you found before trying to save it. It should give the same error, but then we have an indication as to why it might be. And then we can relax the tolerances.
Click to see adapted script.
from pybricks.hubs import ThisHub
from pybricks.parameters import Side, Axis
from pybricks.tools import wait, vector
hub = ThisHub()
def beep(freq):
try:
hub.speaker.beep(freq, 100)
except AttributeError:
# Technic hub does not have a speaker.
pass
wait(10)
def wait_for_stationary(side):
while not hub.imu.stationary() or hub.imu.up() != side:
wait(10)
up_sides = {
Side.FRONT: (0, 0),
Side.BACK: (1, 0),
Side.LEFT: (2, 1),
Side.RIGHT: (3, 1),
Side.TOP: (4, 2),
Side.BOTTOM: (5, 2),
}
gravity = [0] * 6
bias = vector(0, 0, 0)
STATIONARY_COUNT = 1000
def roll_over_axis(axis, new_side):
global bias, bias_count
print("Roll it towards you, without lifting the hub up!")
angle_start = hub.imu.rotation(axis, calibrated=False)
while hub.imu.up() != new_side or not hub.imu.stationary():
_, _, z = hub.imu.orientation() * axis
if abs(z) > 0.07:
print(hub.imu.orientation() * axis)
raise RuntimeError("Lifted it!")
wait(100)
uncalibrated_90_deg_rotation = abs(hub.imu.rotation(axis, calibrated=False) - angle_start)
if abs(uncalibrated_90_deg_rotation - 90) > 10:
raise RuntimeError("Not 90 deg!")
print("Calibrating...")
beep(1000)
rotation_start = vector(
hub.imu.rotation(Axis.X, calibrated=False),
hub.imu.rotation(Axis.Y, calibrated=False),
hub.imu.rotation(Axis.Z, calibrated=False),
)
acceleration = vector(0, 0, 0)
for i in range(STATIONARY_COUNT):
acceleration += hub.imu.acceleration(calibrated=False)
bias += hub.imu.angular_velocity(calibrated=False)
wait(1)
acceleration /= STATIONARY_COUNT
rotation_end = vector(
hub.imu.rotation(Axis.X, calibrated=False),
hub.imu.rotation(Axis.Y, calibrated=False),
hub.imu.rotation(Axis.Z, calibrated=False),
)
if abs(rotation_end - rotation_start) > 1:
raise RuntimeError("Moved it!")
side_index, axis_index = up_sides[new_side]
# Store the gravity value for the current side being up.
# We will visit each side several times. We'll divide by the number
# of visits later.
gravity[side_index] += acceleration[axis_index]
beep(500)
return uncalibrated_90_deg_rotation
calibrate_x = """
Going to calibrate X now!
- Put the hub on the table in front of you.
- top side (display) facing up
- right side (ports BDF) towards you.
"""
calibrate_y = """
Going to calibrate Y now
- Put the hub on the table in front of you.
- top side (display) facing up
- back side (speaker) towards you.
"""
calibrate_z = """
Going to calibrate Z now!
- Put the hub on the table in front of you.
- front side (USB port) facing up
- left side (ports ACE) towards you
"""
REPEAT = 2
# For each 3-axis run, we will visit each side twice.
SIDE_COUNT = REPEAT * 2
def roll_hub(axis, message, start_side, sides):
print(message)
wait_for_stationary(start_side)
beep(500)
rotation = 0
for _ in range(REPEAT):
for side in sides:
rotation += roll_over_axis(axis, side)
return rotation / REPEAT
rotation_x = roll_hub(
Axis.X, calibrate_x, Side.TOP, [Side.LEFT, Side.BOTTOM, Side.RIGHT, Side.TOP]
)
rotation_y = roll_hub(
Axis.Y, calibrate_y, Side.TOP, [Side.FRONT, Side.BOTTOM, Side.BACK, Side.TOP]
)
rotation_z = roll_hub(
Axis.Z, calibrate_z, Side.FRONT, [Side.RIGHT, Side.BACK, Side.LEFT, Side.FRONT]
)
print("angular_velocity_bias=", tuple(bias / SIDE_COUNT / STATIONARY_COUNT / 6))
print("angular_velocity_scale=", (rotation_x, rotation_y, rotation_z))
print("acceleration_correction=", [g / SIDE_COUNT for g in gravity])
hub.imu.settings(
angular_velocity_bias=tuple(bias / SIDE_COUNT / STATIONARY_COUNT / 6),
angular_velocity_scale=(rotation_x, rotation_y, rotation_z),
acceleration_correction=[g / SIDE_COUNT for g in gravity],
)
print("Result: ", hub.imu.settings())
See below, I cut out the obvious.
Going to calibrate X now!
- Put the hub on the table in front of you.
- top side (display) facing up
- right side (ports BDF) towards you.
Roll it towards you, without lifting the hub up!
Calibrating...
Going to calibrate Y now
- Put the hub on the table in front of you.
- top side (display) facing up
- back side (speaker) towards you.
Roll it towards you, without lifting the hub up!
Calibrating...
Going to calibrate Z now!
- Put the hub on the table in front of you.
- front side (USB port) facing up
- left side (ports ACE) towards you
Roll it towards you, without lifting the hub up!
Calibrating...
angular_velocity_bias= (0.07558279, -3.181849, 1.326638)
angular_velocity_scale= (366.9297, 349.4564, 363.9098)
acceleration_correction= [9898.266, -9692.415, 9925.33, -9830.211, 9589.978, -10110.9]
Traceback (most recent call last):
File "test.py", line 150, in <module>
ValueError: Invalid argument
When I look at the results and look at the code. It looks like something with the acceleration_correction is not within limits.
I have installed firmware: primehub-firmware-build-3643-gitcc5521fc.zip
Thank you, this is very helpful!
Your hub is reporting the following amount of degrees for each full x, y, z rotation respectively:
366.9297, 349.4564, 363.9098
This is further off the ideal 360 value than I have seen in any of our hubs. We had set the limits at 350-370, so this explains the issue: yours is just outside it.
We will increase the tolerances since this is clearly necessary, so that calibration will pass on your hub too.
When we do that and you complete this procedure again, you should get a massive improvement for measuring rotation around the Y axis for your hub!
Thank you, this is very helpful!
Your hub is reporting the following amount of degrees for each full x, y, z rotation respectively:
366.9297, 349.4564, 363.9098This is further off the ideal 360 value than I have seen in any of our hubs. We had set the limits at 350-370, so this explains the issue: yours is just outside it.
We will increase the tolerances since this is clearly necessary, so that calibration will pass on your hub too.
When we do that and you complete this procedure again, you should get a massive improvement for measuring rotation around the Y axis for your hub!
Thanks for explaining this. Could you give an indication when you have new firmware as a beta? Furthermore I am curious when this feature will officially come as a release.
I started reading the C code and I played with:
print("Result: ", hub.imu.settings()) before the calibration.
Result is:
Result: (2.0, 2500.0, (0.07558279, -3.181849, 1.314846), (366.9297, 360.0, 360.0), (9806.65, -9806.65, 9806.65, -9806.65, 9806.65, -9806.65), 360.0)
PS when this is working I will also share my results of https://github.com/pybricks/support/issues/1962 apparently i have a hub that has a bit more deviation than tested so far. Maybe this can help.
Just increased the tolerances from 10 to 15 degrees, which should cover your hub. You can follow the original instructions to get the new, latest build.
Thank you for trying this and reporting this. Now we could fix the tolerances before releasing it!
I have seen a mega improvement. THANKS!
Before:
(2.0, 2500.0, (0.1462465, -3.244734, 1.333473), (360.0, 360.0, 360.0), (9806.65, -9806.65, 9806.65, -9806.65, 9806.65, -9806.65), 360.0)
After
(2.0, 2500.0, (0.08115859, -3.275208, 1.323259), (367.2673, 349.2709, 364.027), (9900.773, -9687.63, 9936.37, -9823.288, 9620.516, -10081.91), 360.0)
Simple test
0.000 -0.000 -0.000 0.000
-90.253 -1.432 -8.037 8.037
-180.402 0.514 -7.243 7.243
-270.290 0.985 -5.475 5.475
-360.067 -0.480 -4.675 4.675
Would It help if I would share the same measurement results as on https://github.com/pybricks/support/issues/1962#issuecomment-2516984193
We haven't used the IMU calibration yet, but I want to show it to the kids this summer. But first I want to run some tests so I can see what to expect. I understand that the calibration settings survive a reboot, so what I'd like to know is there a way to delete the settings once it has been calibrated? I want the kids to calibrate "uncalibrated" hubs so they can see the difference.
Also, how would I calibrate the hub when it is installed in a robot? Our robot is not very flat on top. https://github.com/FLL-Team-24277/FLL-Fall-2024-Submerged/blob/main/help/images/Robot_summer_2023_CompetitionBot.png
We could take that "L" piece off the top (it's just a safety to keep us from accidentally hitting the button) and just hold it flat when it is time to go top-down, but we'd have to continuously hold it while doing that step.
I'm going to look through the _imu_calibrate code, but is there anything you can say about what the code actually does and how it is used, say, when I use a drive() command after calibration?
Calibration is needed only once, so hopefully taking it out of your robot is not an issue.
However, there will also be a way to adjust the gyro value without doing that. I am currently working on the documentation for all of this 🙂
is there a way to delete the settings once it has been calibrated?
This will erase settings and your program:
hub.system.reset_storage()
Unfortunately, getting the hub out of the robot is quite an ordeal. Serious Lego-finger! But if that is what we have to do, then we will do it.
You can make your own routine that doesn't require disassembly. Have it make 10 rotations, starting and ending aligned with a wall. Could even make a little program that just does that. Measure hub.imu.rotation(Axis.Z) at the start and at the end and take the difference. You might find something like 3574 instead of the perfect 3600 for 10 rotations. Also display hub.imu.heading().
Then you can do:
hub.imu.settings(heading_correction=357.4)
You should now find that when repeating this a second time, hub.imu.heading() should give you a value much closer to 360 for a full rotation than before.
This setting has been available for a while and will remain there even after we enable calibration. It can augment calibration, or just replace it if all you ever need is a single axis like in this robot.
Hello @laurensvalk is this correct import _imu_calibrate and then see the results with import _imu_calibrate
>>> print(hub.imu.settings())
(2.0, 2500.0, (0.08999829, -2.871182, 1.170795), (367.9688, 349.4978, 363.1353), (9888.416, -9705.651, 9926.816, -9822.398, 9580.736, -10112.13), 360.0)
Then I do a hub.system.reset_storage()
Still I would like the results from before.
To put 367.9688 in heading correction in the program?
If you successfully ran the calibration routine like you did, you shouldn’t have to manually set the heading correction. The heading should already be very consistently close to 360 now.
The manual heading correction can be used if you don’t want to (or can’t) run the calibration routine. They can be used together technically but this should rarely be needed.
On Sun, 2 Mar 2025 at 20:37, Roy Krikke @.***> wrote:
Hello @laurensvalk https://github.com/laurensvalk is this correct import _imu_calibrate and then see the results with import _imu_calibrate
print(hub.imu.settings()) (2.0, 2500.0, (0.08999829, -2.871182, 1.170795), (367.9688, 349.4978, 363.1353), (9888.416, -9705.651, 9926.816, -9822.398, 9580.736, -10112.13), 360.0)
Then I do a hub.system.reset_storage()
Still I would like the results from before. Capture.PNG (view on web) https://github.com/user-attachments/assets/f57744fd-590e-4626-af67-ccb2d26e9193
To put 367.9688 in heading correction in the program?
— Reply to this email directly, view it on GitHub https://github.com/pybricks/support/issues/1907#issuecomment-2692873141, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC6BKYIQRLC2X5TKJ3ICE532SNMX3AVCNFSM6AAAAABQZ57QLKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDMOJSHA3TGMJUGE . You are receiving this because you were mentioned.Message ID: @.***> [image: roykrikke]roykrikke left a comment (pybricks/support#1907) https://github.com/pybricks/support/issues/1907#issuecomment-2692873141
Hello @laurensvalk https://github.com/laurensvalk is this correct import _imu_calibrate and then see the results with import _imu_calibrate
print(hub.imu.settings()) (2.0, 2500.0, (0.08999829, -2.871182, 1.170795), (367.9688, 349.4978, 363.1353), (9888.416, -9705.651, 9926.816, -9822.398, 9580.736, -10112.13), 360.0)
Then I do a hub.system.reset_storage()
Still I would like the results from before. Capture.PNG (view on web) https://github.com/user-attachments/assets/f57744fd-590e-4626-af67-ccb2d26e9193
To put 367.9688 in heading correction in the program?
— Reply to this email directly, view it on GitHub https://github.com/pybricks/support/issues/1907#issuecomment-2692873141, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC6BKYIQRLC2X5TKJ3ICE532SNMX3AVCNFSM6AAAAABQZ57QLKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDMOJSHA3TGMJUGE . You are receiving this because you were mentioned.Message ID: @.***>
Calibration is needed only once, so hopefully taking it out of your robot is not an issue.
Does this mean I do not need to re-calibrate after each firmware upgrade?
If you successfully ran the calibration routine like you did, you shouldn’t have to manually set the heading correction. The heading should already be very consistently close to 360 now.
The manual heading correction can be used if you don’t want to (or can’t) run the calibration routine. They can be used together technically but this should rarely be needed. …
I think I didn’t explain my question before not clearly enough. What I meant is exactly what @zoligyenge is asking as well. I believe I read somewhere that the calibration data is lost after a firmware update.
@laurensvalk see my previous message. Is the calibration data indeed lost after a firmware update?
Yes, but technically speaking it is only lost if you update to a different version.
If you reinstall the same version, it can't tell the difference so it keeps all user data.
Hi all,
Quick question — I'm currently on holiday so I can't test it myself, but I was wondering: is this feature now part of the stable release by default?
Just curious and trying to stay up to date even while away 😄 Thanks in advance!
Quick question — I'm currently on holiday so I can't test it myself, but I was wondering: is this feature now part of the stable release by default?
Yes, 3D heading and calibration were implemented in https://github.com/pybricks/pybricks-micropython/releases/tag/v3.6.0b3 and therfore part of subsequent versions such as the current stable release 3.6.1. Calibration data is still lost after firmware update, so you need to back your settings up and reinstall after the update. I believe this is intentional, because people could choose to install custom versions of the firmware with different memory layout e.g. to have more space for userprogram and drop ununsed pybricks build-in libraries.
Quick question — I'm currently on holiday so I can't test it myself, but I was wondering: is this feature now part of the stable release by default?
Yes, 3D heading and calibration were implemented in https://github.com/pybricks/pybricks-micropython/releases/tag/v3.6.0b3 and therfore part of subsequent versions such as the current stable release 3.6.1. Calibration data is still lost after firmware update, so you need to back your settings up and reinstall after the update. I believe this is intentional, because people could choose to install custom versions of the firmware with different memory layout e.g. to have more space for userprogram and drop ununsed pybricks build-in libraries.
Thanks for sharing, is of great help!
Another question: I've noticed that features in the repo keep their status open. I'm used to them being closed. Is there a house rule for this in the Pybrick repos?