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
Source: Tips4all
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.
ReplyDeleteWith 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.
These are some orientations handlers u can use
ReplyDeleteConstants
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.
I assume you are referring to the Magnetometer inside the Hero.
ReplyDeleteCallibrating 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.