234 lines
7.6 KiB
Java
234 lines
7.6 KiB
Java
/**
|
|
* CompassSensor.java
|
|
* @date Mar 2, 2011
|
|
* @author ricky barrette
|
|
* @author Twenty Codes, LLC
|
|
*/
|
|
package com.TwentyCodes.android.location;
|
|
|
|
import android.content.Context;
|
|
import android.hardware.GeomagneticField;
|
|
import android.hardware.Sensor;
|
|
import android.hardware.SensorEvent;
|
|
import android.hardware.SensorEventListener;
|
|
import android.hardware.SensorManager;
|
|
import android.location.Location;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.util.Log;
|
|
import android.view.Display;
|
|
import android.view.Surface;
|
|
import android.view.WindowManager;
|
|
|
|
import com.TwentyCodes.android.debug.Debug;
|
|
import com.TwentyCodes.android.debug.LocationLibraryConstants;
|
|
|
|
/**
|
|
* A simple convince class that accesses the compass sensor on another thread
|
|
* @author ricky barrette
|
|
*/
|
|
public class CompassSensor{
|
|
|
|
/**
|
|
* A simple listener interface to get updates from CompassSensor
|
|
* @author ricky barrette
|
|
*/
|
|
public interface CompassListener {
|
|
|
|
/**
|
|
* Called when there is an update from the Compass Sensor
|
|
* @param bearing
|
|
* @author ricky barrette
|
|
*/
|
|
public void onCompassUpdate(float bearing);
|
|
}
|
|
|
|
public static final String TAG = "CompassSensor";
|
|
private static final int BEARING = 0;
|
|
private final Display mDisplay;
|
|
private final Handler mHandler;
|
|
private final SensorManager mSensorManager;
|
|
private final Context mContext;
|
|
private CompassListener mListener;
|
|
private float mDelination = 0;
|
|
|
|
private final SensorEventListener mCallBack = new SensorEventListener() {
|
|
|
|
private float[] mRotationMatrix = new float[16];
|
|
// private float[] mRemapedRotationMatrix = new float[16];
|
|
private float[] mI = new float[16];
|
|
private float[] mGravity = new float[3];
|
|
private float[] mGeomag = new float[3];
|
|
private float[] mOrientVals = new float[3];
|
|
|
|
private double mAzimuth = 0;
|
|
// double mPitch = 0;
|
|
// double mRoll = 0;
|
|
// private float mInclination;
|
|
|
|
public void onSensorChanged(final SensorEvent sensorEvent) {
|
|
if(Debug.DEBUG){
|
|
switch (sensorEvent.accuracy){
|
|
case SensorManager.SENSOR_STATUS_UNRELIABLE:
|
|
Log.v(TAG , "UNRELIABLE");
|
|
break;
|
|
case SensorManager.SENSOR_STATUS_ACCURACY_LOW:
|
|
Log.v(TAG , "LOW");
|
|
break;
|
|
case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:
|
|
Log.v(TAG , "MEDIUM");
|
|
break;
|
|
case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:
|
|
Log.v(TAG , "HIGH");
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// If the sensor data is unreliable return
|
|
if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
|
|
return;
|
|
|
|
// Gets the value of the sensor that has been changed
|
|
switch (sensorEvent.sensor.getType()) {
|
|
case Sensor.TYPE_ACCELEROMETER:
|
|
mGravity = sensorEvent.values.clone();
|
|
break;
|
|
case Sensor.TYPE_MAGNETIC_FIELD:
|
|
mGeomag = sensorEvent.values.clone();
|
|
break;
|
|
}
|
|
|
|
// If gravity and geomag have values then find rotation matrix
|
|
if (mGravity != null && mGeomag != null) {
|
|
|
|
// checks that the rotation matrix is found
|
|
boolean success = SensorManager.getRotationMatrix(mRotationMatrix, mI, mGravity, mGeomag);
|
|
if (success) {
|
|
|
|
// switch (mDisplay.getOrientation()){
|
|
// case Surface.ROTATION_0:
|
|
// Log.v(TAG , "0");
|
|
// // SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Y, mRemapedRotationMatrix);
|
|
// break;
|
|
// case Surface.ROTATION_90:
|
|
// Log.v(TAG , "90");
|
|
// // SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Y, mRemapedRotationMatrix);
|
|
// break;
|
|
// case Surface.ROTATION_180:
|
|
// Log.v(TAG , "180");
|
|
// // SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_MINUS_X, SensorManager.AXIS_MINUS_Y, mRemapedRotationMatrix);
|
|
// break;
|
|
// case Surface.ROTATION_270:
|
|
// Log.v(TAG , "270");
|
|
// // SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_MINUS_X, SensorManager.AXIS_Y, mRemapedRotationMatrix);
|
|
// break;
|
|
// }
|
|
|
|
/*
|
|
* remap cords due to Display.getRotation()
|
|
*/
|
|
SensorManager.getOrientation(mRotationMatrix, mOrientVals);
|
|
// mInclination = SensorManager.getInclination(mI);
|
|
mAzimuth = Math.toDegrees(mOrientVals[0]);
|
|
// mPitch = Math.toDegrees(mOrientVals[1]);
|
|
// mRoll = Math.toDegrees(mOrientVals[2]);
|
|
|
|
/*
|
|
* compensate for magentic delination
|
|
*/
|
|
mAzimuth += mDelination;
|
|
|
|
/*
|
|
* compensate for device orentation
|
|
*/
|
|
switch (mDisplay.getOrientation()){
|
|
case Surface.ROTATION_0:
|
|
break;
|
|
case Surface.ROTATION_90:
|
|
mAzimuth = mAzimuth + 90;
|
|
break;
|
|
case Surface.ROTATION_180:
|
|
mAzimuth = mAzimuth +180;
|
|
break;
|
|
case Surface.ROTATION_270:
|
|
mAzimuth = mAzimuth - 90;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
mHandler.sendMessage(mHandler.obtainMessage(BEARING, (float) mAzimuth));
|
|
}
|
|
|
|
@Override
|
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Creates a new CompassSensor
|
|
* @author ricky barrette
|
|
*/
|
|
public CompassSensor(final Context context) {
|
|
mContext = context;
|
|
mDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
|
mHandler = new Handler(){
|
|
@Override
|
|
public void handleMessage(Message msg){
|
|
if(mListener != null)
|
|
if(msg.what == BEARING)
|
|
mListener.onCompassUpdate((Float) msg.obj);
|
|
}
|
|
};
|
|
|
|
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
|
}
|
|
|
|
/**
|
|
* Disables compass updates
|
|
* @author ricky barrette
|
|
*/
|
|
public void disable(){
|
|
mListener = null;
|
|
mSensorManager.unregisterListener(mCallBack);
|
|
}
|
|
|
|
/**
|
|
* Attempts to register the listener for compass updates
|
|
* @param listener
|
|
* @author ricky barrette
|
|
*/
|
|
public void enable(CompassListener listener){
|
|
if(mListener == null) {
|
|
mListener = listener;
|
|
if(mSensorManager != null)
|
|
new Thread(new Runnable(){
|
|
@Override
|
|
public void run() {
|
|
// Register this class as a listener for the accelerometer sensor
|
|
mSensorManager.registerListener(mCallBack, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), LocationLibraryConstants.COMPASS_UPDATE_INTERVAL);
|
|
// ...and the orientation sensor
|
|
mSensorManager.registerListener(mCallBack, mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), LocationLibraryConstants.COMPASS_UPDATE_INTERVAL);
|
|
}
|
|
}).start();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the Geomagnetic Field Declination based off of the provided location
|
|
* @param location last known (lat,lon,altitude), null will reset
|
|
* @author ricky barrette
|
|
*/
|
|
public void setDeclination(final Location location){
|
|
if (location != null) {
|
|
final GeomagneticField geomagneticField = new GeomagneticField(new Double(location.getLatitude()).floatValue(),
|
|
new Double(location.getLongitude()).floatValue(),
|
|
new Double(location.getAltitude()).floatValue(),
|
|
System.currentTimeMillis());
|
|
mDelination = geomagneticField.getDeclination();
|
|
} else {
|
|
mDelination = 0;
|
|
}
|
|
}
|
|
} |