How to calculate the phones rotation around the y axis (roll) while it's laying flat?
Asked Answered
C

3

9

This few lines of C# code calculate the phone's rotation around the y axis using the accelerometer:

private float GetRoll() {
    /*
     * Sum up the accelerometer events
     */
    Vector3 accelerationVector = Vector3.zero;
    for (int i=0; i < Input.accelerationEventCount; i++) {
        AccelerationEvent accEvent = Input.GetAccelerationEvent(i);
        accelerationVector += accEvent.acceleration * accEvent.deltaTime;
    }
    accelerationVector.Normalize();

    int inclination = (int) Mathf.Round(Mathf.Rad2Deg * Mathf.Acos(accelerationVector.z));
    float roll = 0;
    if (inclination < 25 || inclination > 155) {
        /*
         * How to calculate the rotation here?
         */
    } else {
        roll = Mathf.Round(Mathf.Rad2Deg * Mathf.Atan2(accelerationVector.x, accelerationVector.y));
    }
    return roll;
}

Do you know the math to make it work if the phone is laying flat on the table? I.e. if inclination is less than 25 or more than 155 degree? The code originates from this SO post which mentions that the compass can be used. Unfortunately I don't know how, so your advise is very appreciated. Also, if possible, I'd like to avoid using the gyroscope and rather stick with the accelerometer.

Any advise is welcome. Thank you.

Carbarn answered 12/7, 2017 at 13:8 Comment(4)
You cannot know the rotation of the phone unless you have the acceleration history from before the phone was laid down. This is a coordinate singularity intrinsic to Euler angles.Hate
Yes, I agree with #meowgoesthedog. if the phone is lying flat, then rotation with respect to which XY plane? The phone has its own absolute system of coordinates, so you have to give it a reference. you can get the compass data using Sensor.TYPE_MAGNETIC_FIELD check out these two posts: 1. #4820126 2. #8626304Bellman
What's your issue with using the gyroscope?Ephraim
@cdo256: Old (ancient) Android devices could lack a gyroscope, hence I wanted to stick with the accelerometer.Caridadcarie
M
4

Why don't you use the gyroscope?

If you think it over it seems physically impossible to get any kind of rotation info from acceleration vectors if the axis of the rotation is completely parallel with the sum of accelerations.

(Maybe you can get it's speed from the centripetal force but nothing else.)

Macaluso answered 25/7, 2017 at 17:32 Comment(1)
Thank you, I'll take a look at the gyroscope.Caridadcarie
I
1

You're request is practically impossible

It boils down to gyroscopes measure absolute orientation in space while accelerometers measure change of velocity (acceleration). When you use calculus to go from acceleration (m/s^2) to location (m), you get distance displaced - this makes sense intuitively, too. Because accelerometers are triggered on change of velocity, it won't even trigger 400mph constant velocity while on an airplane.

Not only would you need entire accelerometer history, you would also need original location and orientation Not to mention all the error extrapolated over such an error, a 1% sensor error becomes much greater in this calculation.

To get some type of sensor data about orientation, gyroscope (or maybe compass) must be used. In fact, to directly answer your question, no accelerometer is needed, since it is a question of finding position. However, your actual needs may benefit from accelerometer, if you want to react to user gestures, or something.

Input.gyro.attitude should give you your absolute orientation values. Get these values for when it's laying flat with no roll, then get these values again with some amount of roll. After this, you should have some data on what range of values meet your criteria and some error margin on that condition.

https://docs.unity3d.com/ScriptReference/Gyroscope.html

Integrated answered 27/7, 2017 at 13:37 Comment(0)
C
0

You can use

 onSensorChanged(SensorEvent event)

In this event you can detect the type of sensor and calculate Roll, Azimut and Pitch as in given example

  float azimuthVal = event.values[0];
  float pitchVal = event.values[1];
  float rollVal = event.values[2];

Which Sensor values you have to read you can get from

event.sensor.getType()

And the orientation in order to find the tilt you can get from method

SensorManager.getOrientation

and can get angles as

azimutOrt = orientation[0];
pitchOrt = orientation[1];
rollOrt = orientation[2];

For Unity the below three can be used

Input.acceleration: Accelerometer
Input.gyro.rotationRate:
Input.gyro.attitude
Input.gyro.gravity:
Caines answered 27/7, 2017 at 6:34 Comment(2)
Thank you for sharing this. Unfortunately I can't use the Android API, as the project is done in Unity.Caridadcarie
no issues . How about this Input.gyro.rotationRate.y. I have updated the answer for UNITYCaines

© 2022 - 2024 — McMap. All rights reserved.