-
-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pybricks.hubs.MoveHub: Increase resolution for imu.acceleration() #88
Conversation
Thanks for the pull request! In Pybricks, all of our measurements use specific units of measurement. For accelerometers, this is currently m/s/s. What is your application that requires higher resolution? |
I'm building a self-balancing bot. If I hold it upright at an angle between -10° and +10°, I only get values between -2 and +2 to work with. |
The consumer accelerometers I've seen maybe go up to 8 or 16 Gs so if we use mm/s/s then the max value would be something like 8G * 9.8 m/s/s/G * 1000 mm/m = 78400 mm/s/s. This still fits in a MP_SMALL_INT. So I would be happy with just using mm/s/s everywhere. The only drawback changing it will break existing programs. But IMU stuff is still considered experimental at this point anyway. @laurensvalk, thoughts? |
I'm not sure if the values returned by |
Gravity causes acceleration on everything on the surface of the earth at a rate of 9.8 m/s/s. So it makes sense that when the hub is standing still, the only force on the hub is due to gravity. And 9.8 rounded to an integer is 10. So this is how you know which what the hub is oriented - by which way gravity is pulling on it! |
But gravity is supposed to be the same when I hold the hub vertically or horizontally. The returned value is not (see the table above). |
I get it now. |
The accelerometer is a 3-axis accelerometer. So it measures the effect in 3 different directions. When one value goes down, another value will go up. In your code, you are only looking at the |
pybricks/hubs/pb_type_movehub.c
Outdated
@@ -185,7 +185,7 @@ STATIC mp_obj_t hubs_MoveHub_IMU_acceleration(mp_obj_t self_in) { | |||
// Convert to appropriate units and return as tuple | |||
mp_obj_t values[3]; | |||
for (uint8_t i = 0; i < 3; i++) { | |||
values[i] = MP_OBJ_NEW_SMALL_INT((data[i] * 10) >> 6); | |||
values[i] = MP_OBJ_NEW_SMALL_INT(((data[i] + 1) * 11) >> 3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this change the unit to mm/s/s, then?
values[i] = MP_OBJ_NEW_SMALL_INT(((data[i] + 1) * 11) >> 3); | |
values[i] = MP_OBJ_NEW_SMALL_INT((data[i] * 10000) >> 6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks right, assuming the existing code was correct.
You could test and see if it reads something close to 9800 if you compile and run the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the datasheet, it looks like the sensor returns a value in mg so if the value is closer to 10000, then we may need to use * 9860
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It reads 10313
Thanks for making this pull request! When very specific new features are requested (like a resolution change), I usually try to dig a little deeper to better understand why we'd need it. It's currently rounded to whole numbers because the Move Hub does not support floating point operations. We've kept it in The justification for rounding it (instead of choosing a movehub-specific resolution) is that the acceleration values are often not that useful without further processing. When they are used as-is (such as for impact or free-fall detection), the low resolution really isn't all that bad, since it's usually just a threshold comparison. But based on what you're describing, I think what we're trying to get here is a gradual tilt value, not acceleration per-se. This was proposed in pybricks/support#539 and I think we can still do this. So, @cschlack would you say the acceleration resolution is okay if we implemented the following method as well?
This can't be done with an accelerometer alone; you'd need a gyroscopic sensor. You could also make one with the color sensor, where the reflection intensity gives you a sense of the robot's angle. |
Thanks @laurensvalk for the background information. |
I thought we were trying not to use floating point in any of our APIs. |
Geometry like rotation matrices would be hard to do (or at least very cumbersome) without floating point math. Maybe we can restrict floating point usage to particular relevant areas only but not rule it out entirely? That said, using mm/s/s for all accelerations (so int) might be fine. |
This has been split into two tasks in pybricks/pybricks-api#94 and pybricks/support#539. When we complete those, we can update this pull request accordingly and merge it. Thanks for your patience :) |
116eb6c
to
c3e8192
Compare
c3e8192
to
6b260a4
Compare
Updated and merged. Thank you! |
Given the following python snippet:
When using the Pybricks firmware, the result of hub.imu.acceleration will return values between -10 and 10. This is a very low resolution. The following table shows the raw values, LEGO and Pybricks values and the values after applying this PR.
I tried to distribute the range of raw values to the range between -90 and 90.