質問

I'm in a little bit weird situation. The situation I currently have is typically a good one - no gyro drift at all - but I have no clue why this is the case. I expected the gyroscope to drift a lot as reported everywhere. Therefore this question to find the reason why I do not see any drift.

I use a Galaxy Nexus (Android 4.0.3) and its gyroscope to do some orientation change detection in the end. In the first place, I just wanted to log the sensor readings and expected to see large drifting values as for example here. Also on other websites I read of drifting of about 1 degree per second or similar measurements.

My code to log the sensor data is very basic:

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);
LogSensorEventListener listener = new LogSensorEventListener(
       SensorLoggerActivity.this, Sensor.TYPE_GYROSCOPE);
sm.registerListener(listener, sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
       SensorManager.SENSOR_DELAY_FASTEST);

LogSensorEventListener is also a very basic implementation of the SensorEventListenerInterface:

@Override
public void onSensorChanged(SensorEvent event) {

    final float dT = (event.timestamp - mTimestamp) / 1000000000.f;
    if (dT < 1) { // just a fix for the first step

        mRelZ += event.values[2] * dT;
        list.add(mRelZ);
        list2.add(event.timestamp);
    }
    mTimestamp = event.timestamp;

mRelZ is initially set to 0 and the two lists should keep track of time and measured value. If finished with my measurement (clicking a button) the values are written to file:

    try {

        for (int i = 0; i < list.size(); i++) {

            long time = list2.get(i);

            if (mStartTime < 0) {
                mStartTime = time;
                time = 0;
            } else {
                time = time - mStartTime;
            }

            float timef = time / 1000000000.0f;
            sb.append(timef);
            sb.append(";");
            sb.append(Math.toDegrees(list.get(i)));
            sb.append("\n");
        }

        mOutFileStream.write(sb.toString().getBytes());

        mOutFileStream.flush();
        mOutFileStream.close();
    } catch (IOException e) {
    }

Everything works fine but the only drift I can see (for example when having the device lying on a table and logging values for let's say 60 seconds) is about 0.2 degree. If I move the device to get something like in the screenshot above no drift can be observed at all...

What I'm I doing wrong (or right?)??

Thanks for any advice!

役に立ちましたか?

解決

the gyro you have might be a post-filtered one, i found this in some of the SAMSUNG I9100 devices. they use gyros produced by INVENSENSE CORP.

edit 2014/12/10 for commenting @Lourenço Castro i believe @Lourenço Castro was right about the 'factory drift'(or zero-drift) and 'accumulated drift';

Concerning to complementary/kalman filters, on Android, the 6dof(ACC+GYRO) impl. works fine, it can remove both factory and accumulated drift of gyroscope thanks to accelerometer's calibration;

However, the 9dof impl., or adding a magnetometer sensor into consideration, filter runs into status you dont want. According to my tests, it is caused by uncalibed status of magnetometer which need guys to shake (known as drawing 'eight')the phone to remove before fusion.

9dof provides a full rotation estimation while 6dof can not handle the accumulated drift of rotating around y axis(see android's ref. for axis definition). And I dont think that 'shaking-and-drawing-number-8' before one starts an app is a good UE, so we have to go back to 6dof method and try to find a way to remove factory drift of rotation around y-axis.

(a lot of boring but amazing content about complementary/kalman filter should be here. but i guess those come here already know it.)

You can try a 360 panorama app included in Google Camera which can be downloaded from market. This app use a visual-aid(image processing based motion estimation) for calibrating the sensor before we really start to capturing, it's easy to verify this. And no use of Magnetometer, i guess.

So my advice to use sensor-fusion on Android is: 1. no magnetometer; (dont know if this is a hardware problem or can be solved by software.) 2. accelerometer+gyroscope provides smooth and stable 6dof motion estimation; 3. try to solve the drift around y-axis, mainly means that visual-method should be added to; 4. try 3 and try 3...

Maybe someone will run into this question and i hope all above might be helpful. thanks to those posts related to this questions on StackOverflow. i dont remember your names exactly but you all helped me a lot. :)

他のヒント

I was browsing for this subject and, although this is an old question, I don't believe the accepted answer is correct. The drift that is "reported everywhere" is caused by the integration of noisy gyroscope data (as seen on the link provided by the O.P.), not by simply outputting the sensor data. You will need this integration to calculate orientation changes over time.

Longer integration periods will contain larger noise amounts which will accumulate drift fairly quickly. I believe the internal filtering of the signal which happens on Invensense hardware is used to remove drift caused by their own pre-processing of the gyroscope.

In Android's case, in API 18 (Jelly Bean MR2), a GYROSCOPE_UNCALIBRATED sensor was added, in which you can (presumably) verify this factory drift calibration. Anyway, when you try to integrate either the calibrated and uncalibrated sensor events, you will get drift, since both are pretty noisy. To reduce this issue you will have to delve into complementary or Kalman filters.

(Sorry about not posting more informational links, not enough reputation).

Hope this helps future users.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top