3
\$\begingroup\$

I want to rotate an object with respect to the phone's position. I use the accelerometer output to detect orientation:

float roll = Gdx.input.getRoll();
float pitch = Gdx.input.getPitch();
float azimuth = Gdx.input.getAzimuth();

Vector3 accel=new Vector3(accelX, accelY, accelZ);
bat.transform.setToRotation(0f, -1f, 0f, pitch);

bat.transform.setFromEulerAngles(azimuth, -pitch, -roll);

However, the accelerometer data fluctuates so strongly that the object jitters.

How can I deal with this?

\$\endgroup\$
5
\$\begingroup\$

I don't know if it is because of a poor component that causes the false readings or a extremely precise component that registers the spinning of the earth, as it orbits the sun, as our solar system spirals through the galaxy. Either way, this is a common problem. The solution is to use some type of filter to smooth out the "extra" readings. There are several methods that you can use.

DeadZone - simply track the last "valid" event and compare it to each new accelerometer event . If the difference between the two is greater than an threshold value then count the new reading as a valid event. This is simple to implement, but can make a blocky response since the readings will only move by the threshold value or greater.

Low Pass Filter - This works by only allowing a value to change by a percentage(alpha) of the difference between the previous value and the new value. Simply output = previousValue + alpha * (newValue - previousValue) This works well, but might require some tweaking of the alpha to find a value that works well for your needs. A low alpha will give you a consistent value while the device is idle, and a very fluid motion reading, however it will cut down any sharp peaks in movement. A higher alpha will give a more responsive feedback but will not remove all the noise.

Infinite Impulse Response filter (IIR) - It works by combining a percentage(alpha) of the previous value with the opposite percentage of the new value. ouput = previousValue * alpha + (1.0f - alpha) * newValue. This can produce similar results as a low pass filter, however the alpha value is just the opposite. In this case, a higher alpha will give you a smoother response and a flatter line, while a lower value will give you a more more responsive result, but also might still have a bit of noise.

Rolling Average - Combine the last X number of sensor events and then divide by X. This creates a smooth response while the device is in motion. The few reading averaged the more noise you will see, while the more values that you average the more "sluggish" the response will appear. If you want to try this I would suggest starting with averaging the last 5 value and then go from there.

FPS - For lack of a better term, let's call this "frames per second." You can simply only accept a sensor event if a given amount of time has passed thus only allowing so many valid sensor event per second. While this is very easy to implement, I would caution that this can produce a very blocky and sluggish response. To get this method to acceptably quiet any idle time noise there is usually too few readings per second. This causes the blockiness and sluggishness.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.