views:

1002

answers:

3

hi there!

im writing an app in google android 2.1 that needs to know which direction (n/w/s/e) the device (htc hero) is facing. the sensor and its listener is working great, but the values i get from the sensor are totally crappy. e.g. it tells me i'd be facing north when the device is facing sw or so...

this seems to be a known problem with android devices. the "solutions" i found on the web look like this: - shake the device around - move the device like an eight - tap on the devices back this is thought to trigger the sensors recalibration. and: the thing with the "moving around" works for me... but that's not very professional i guess...

so - how do i trigger the recalibration of the orientation sensor from the sdk? i need the sensor to be properly calibrated without any fancy stuff that would make users of this app look like complete idiots while they are "manually" recalibrating their phones...

is there any way to do this "right"?

EDIT:

or: is there any way to determine PROGRAMATICALLY, if the device is correctly calibrated or not? as a fallback-option so to speak... then i could warn the user that the device needs "manual" recalibration

+2  A: 

I don't believe there is a way to know programatically if you compass sensor is calibrated correctly unless you use a secondary data source like GPS. If you can use GPS then when the user is moving you can compare the GPS movement with the compass heading and correct. Remember that local magnetic fields can screw up the compass readings and the devices has no idea if you are out in the middle of a forest or next to a transformer.

With these micro devices there is always a bit of skew you'll have to deal with. If you check the values for the accelerometer as well you'll see that at rest they aren't always returning 9.8 m/s^2 (or at least consistently between devices).

In your help you may just need to tell the user to rotate/twist their phone in a figure eight to reset the compass.

Morrison Chang
thanks for your answer, but sadly i cannot use gps within this app at all.problem is, i had my htc hero returning me total nonesense all the time until i get it to recalibrate its sensor. i really need to know how to trigger this by sdk/ndk...
xenonite
Luis Miguel
That GPS calibration method would only work if you instruct the user to point the phone in the direction of motion, right? Or am I missing something?
MatrixFrog
I think only a consistent orientation wrt motion is needed to use GPS calibration of the compass. Say the user is moving northeast and then makes a turn heading west. As long as the user holds the unit in the same orientation (on the dashboard or in the hand) the compass should change appropriately and if it doesn't match the GPS reading well then that's the correction factor.
Morrison Chang
+1  A: 

These are some orientations handlers u can use

Constants int ORIENTATION_UNKNOWN Returned from onOrientationChanged when the device orientation cannot be determined (typically when the device is in a close to flat position). Public Constructors OrientationEventListener(Context context) Creates a new OrientationEventListener. OrientationEventListener(Context context, int rate) Creates a new OrientationEventListener. Public Methods boolean canDetectOrientation() void disable() Disables the OrientationEventListener. void enable() Enables the OrientationEventListener so it will monitor the sensor and call onOrientationChanged(int) when the device orientation changes. abstract void onOrientationChanged(int orientation) Called when the orientation of the device has changed. [Expand] Inherited Methods From class java.lang.Object Object clone() Creates and returns a copy of this Object. boolean equals(Object o) Compares this instance with the specified object and indicates if they are equal. void finalize() Is called before the object's memory is being reclaimed by the VM. final Class getClass() Returns the unique instance of Class which represents this object's class. int hashCode() Returns an integer hash code for this object. final void notify() Causes a thread which is waiting on this object's monitor (by means of calling one of the wait() methods) to be woken up. final void notifyAll() Causes all threads which are waiting on this object's monitor (by means of calling one of the wait() methods) to be woken up. String toString() Returns a string containing a concise, human-readable description of this object. final void wait(long millis, int nanos) Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object or until the specified timeout expires. final void wait(long millis) Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object or until the specified timeout expires. final void wait() Causes the calling thread to wait until another thread calls the notify() or notifyAll() method of this object. Constants public static final int ORIENTATION_UNKNOWN Since: API Level 3

Returned from onOrientationChanged when the device orientation cannot be determined (typically when the device is in a close to flat position). See Also

* onOrientationChanged(int)

Constant Value: -1 (0xffffffff) Public Constructors public OrientationEventListener (Context context) Since: API Level 3

Creates a new OrientationEventListener. Parameters context for the OrientationEventListener. public OrientationEventListener (Context context, int rate) Since: API Level 3

Creates a new OrientationEventListener. Parameters context for the OrientationEventListener. rate at which sensor events are processed (see also SensorManager). Use the default value of SENSOR_DELAY_NORMAL for simple screen orientation change detection. Public Methods public boolean canDetectOrientation () Since: API Level 3

public void disable () Since: API Level 3

Disables the OrientationEventListener. public void enable () Since: API Level 3

Enables the OrientationEventListener so it will monitor the sensor and call onOrientationChanged(int) when the device orientation changes. public abstract void onOrientationChanged (int orientation) Since: API Level 3

Called when the orientation of the device has changed. orientation parameter is in degrees, ranging from 0 to 359. orientation is 0 degrees when the device is oriented in its natural position, 90 degrees when its left side is at the top, 180 degrees when it is upside down, and 270 degrees when its right side is to the top. ORIENTATION_UNKNOWN is returned when the device is close to flat and the orientation cannot be determined.

sagar
http://meta.stackoverflow.com/questions/22186/how-do-i-format-my-code-blocks
MatrixFrog
A: 

I assume you are referring to the Magnetometer inside the Hero.

Callibrating it is a tough one and will/should always require user interaction for a realiable callibration. There are seperate strategies to deal with that. You could ask users to hold there device in north direction and then recallibrate. If the users don't know where north is, you can ask them to direct zhe device towards the sun and based on location and time you can calculate where that is.

Leaving callibration aside, I would guess that your problem is that the readings you get from the sensor are inaccurate. Of course callibration is a prerequisite for accurate readings, but there are also other factors in play.

It is common practice to complement sensor data from one sensor with the data a different sensor to increase accuracy. You could use the GPS to determine a heading when the user is moving. If he's moving slowly however, this is inaccurate as well. You could integrate the data reported by the Accelerometer to guess about orientation changes (not the absolute orientation). But honestly a Gyrometer would be more ideal in this case.

Systems that work like this are sometimes called Inertial Navigation Systems (INS) because they can, given a fixed point in space, determine their subsequent relative position and orientation accurately without further external data. Using a Kalman filter is common practice to recallibrate the system from time to time when an absolute position (e.g. retrieved via GPS) is available.

Although it is unrealistic to implement a full-fledged INS, you can certainly draw a few ideas from how they work to make your orientation readings more accurate.

Johannes Rudolph