I am doing a project about video stabilization. Now, I am trying to get the accurate Orientation first. I already read about the sensors event. I know that I can't only use the SensorManager.getOrientation() to get the accurate orientation. Also, I know using accelerometer and integrate of gyroscope can get the correct pitch and roll.
Now,I want to know how can I get the correct yaw too?
Thank you for your time!
With this code you get a accurate orientation by using the accelerometer and the magnetic field sensor. (What is the alternative to android orientation sensor?)
public class OrientationTestActivity extends Activity implements SensorEventListener
{
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
private float[] mLastAccelerometer = new float[3];
private float[] mLastMagnetometer = new float[3];
private boolean mLastAccelerometerSet = false;
private boolean mLastMagnetometerSet = false;
private float[] mR = new float[9];
private float[] mOrientation = new float[3];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
protected void onResume() {
super.onResume();
mLastAccelerometerSet = false;
mLastMagnetometerSet = false;
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
mLastAccelerometerSet = true;
} else if (event.sensor == mMagnetometer) {
System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
mLastMagnetometerSet = true;
}
if (mLastAccelerometerSet && mLastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
SensorManager.getOrientation(mR, mOrientation);
Log.i("OrientationTestActivity", String.format("Orientation: %f, %f, %f",
mOrientation[0], mOrientation[1], mOrientation[2]));
}
}
}
With this you get mOrientation which contains azimuth, pitch and roll.
As explained here https://math.stackexchange.com/questions/296799/azimuth-vs-yaw yaw is the change in azimuth.
Related
SO im trying to make a App that tracks which direction the phone is pointed VIA the compass and once a button is hit on the screen it displays the number of where it is pointed in degrees. So far i understand how the compass is created but can not find which values are the pointed direction in relation to North. Here is what i have so far.
public class compass extends Activity implements OnClickListener, SensorEventListener{
private final SensorManager DirPoint;
float var;
TextView theNumber;
Button DirectionIn;
public compass(){
DirPoint = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theNumber = (textView) findViewById(R.id.output);
DirectionIn =(Button) findViewById(R.Id.Buton);
DirectionIn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
//gets direction of phone compass
// ((TextView)findViewById(R.id.output)).setText(var);
}
}
}
}
Any help would be welcomed or if im headed in the right direction even would be nice.
You have to implement a "compass". You can do this like this:
Let your activity implement the SensorEventListener and add the necessary fields:
public class CompassActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private Sensor magnetometer;
private float[] lastAccelerometer = new float[3];
private float[] lastMagnetometer = new float[3];
private boolean lastAccelerometerSet = false;
private boolean lastMagnetometerSet = false;
private float[] rotationMatrix = new float[9];
private float[] orientation = new float[3];
private float currentDegree = 0f;
In the onCreate method of the activity get and start the two sensors, the accelerometer and the magnetometer:
// onCreate method stub ...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
sensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
// more onCreate method stub ....
In the method of the SensorEventListener you can now calculate the heading of the phone and calculate the bearing between the current location and a other location:
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor == this.accelerometer) {
System.arraycopy(event.values, 0, this.lastAccelerometer, 0, event.values.length);
this.lastAccelerometerSet = true;
} else if (event.sensor == this.magnetometer) {
System.arraycopy(event.values, 0, this.lastMagnetometer, 0, event.values.length);
this.lastMagnetometerSet = true;
}
if (this.lastAccelerometerSet && this.lastAccelerometerSet) {
SensorManager.getRotationMatrix(this.rotationMatrix,null, this.lastAccelerometer, this.lastMagnetometer);
SensorManager.getOrientation(this.rotationMatrix, this.orientation);
float azimuthInRadiands = this.orientation[0];
// this is now the heading of the phone. If you want
// to rotate a view to north don´t forget that you have
// to rotate by the negative value.
float azimuthInDegrees = (float) Math.toDegrees(azimuthInRadiands);
}
}
But don´t forget that there is much more behind a compass. You have to show the user if the magnetic field sensor is uncalibrated. You have to calculate the difference between the magnetic and the geographic north...
I have created a small compass helper class. The HowTo is in the readme. It will provide you all the information you need to present a compass on the screen:
Compass Assistant on GitHub
It provides you the current heading of the device. Please don´t hesitate to ask me if you have problems.
For Details look here
Use a compination of TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD.
Sensor beschleunigung = sensor.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
Sensor magnetometer = sensor.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(0);
sensor.registerListener(handler, beschleunigung, SensorManager.SENSOR_DELAY_NORMAL, null);
sensor.registerListener(handler, magnetometer, SensorManager.SENSOR_DELAY_NORMAL, null);
and
handler = new SensorEventListener() {
float[] mGravity;
float[] mGeomagnetic;
#Override
public void onSensorChanged( SensorEvent event ) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
azimut = orientation[0]; // orientation contains: azimut, pitch and roll
}
}
NavigationArrow.this.setOffsetFromNorth((float) Math.toDegrees(azimut));
}
#Override
public void onAccuracyChanged( Sensor sensor, int accuracy ) {
}
};
Hope that helps :)
I am working on an app in which i need to make text scroll based on device tilt information. I have tried few solutions but nothing seems to be working. I am able to get the tilting information using the following code :-
public class SensorActivity extends Activity implements SensorEventListener {
float[] mMagnetValues = new float[3];
float[] mAccelValues = new float[3];
float[] mOrientationValues = new float[3];
float[] mRotationMatrix = new float[9];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
TextView txt1 = (TextView) findViewById(R.id.textView1);
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mAccelValues, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mMagnetValues, 0, 3);
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mAccelValues, mMagnetValues);
SensorManager.getOrientation(mRotationMatrix, mOrientationValues);
Log.e("Values", mOrientationValues[0] + " " + mOrientationValues[1] + " " + mOrientationValues);
};
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
public void scrollTextUp() {
ScrollView scrollView = (ScrollView)findViewById(R.id.scroll);
scrollView.scrollBy(0, 5);
}
public void scrollTextBottom() {
ScrollView scrollView = (ScrollView)findViewById(R.id.scroll);
scrollView.scrollBy(0, -5);
}
}
I assume that mOrientationValues[1] needs to be used to scroll but how to use this value is a big question for me right now. Please help.
Any help would be really appreciated. If you have found any good tutorial or example please share it.
Thanks.
So after playing around for few hours, this is the solution i used. Requirements for my apps was to make text scroll in a readable speed, that is why i used a constant scroll speed but i welcome everyone to improve this answer based on tilt speed etc so it could help others as well.
TiltScrollController Class -
public class TiltScrollController implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelSensor;
private Sensor mMagnetSensor;
private float mCurrentPosition;
private boolean isCurrentPositionSet = false;
private int count = 0;
private ScrollListener mListener;
float[] mMagnetValues = new float[3];
float[] mAccelValues = new float[3];
float[] mOrientationValues = new float[3];
float[] mRotationMatrix = new float[9];
public TiltScrollController(SensorManager sensorManager, ScrollListener listener) {
mSensorManager = sensorManager;
mListener = listener;
mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mAccelValues, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mMagnetValues, 0, 3);
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mAccelValues, mMagnetValues);
SensorManager.getOrientation(mRotationMatrix, mOrientationValues);
if (!isCurrentPositionSet) {
mCurrentPosition = mOrientationValues[1];
count += 1;
if(count == 2) {
isCurrentPositionSet = true;
}
}
if(mCurrentPosition + 0.25 < mOrientationValues[1]) {
//Scroll to Top
mListener.onTiltUp();
}
else if (mCurrentPosition - 0.25 > mOrientationValues[1]) {
//Scroll to Bottom
mListener.onTiltDown();
}
};
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void requestAllSensors() {
mSensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void killAllSensors() {
mSensorManager.unregisterListener(this, mAccelSensor);
mSensorManager.unregisterListener(this, mMagnetSensor);
}
public interface ScrollListener {
public void onTiltUp();
public void onTiltDown();
}
}
Your activity class -
public class SensorActivity extends Activity {
private ScrollView mScrollView;
private TiltScrollController mTiltScrollController;
private SensorManager mSensorManager;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mScrollView = (ScrollView)findViewById(R.id.scroll);
mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
mTiltScrollController = new TiltScrollController(mSensorManager, new TiltScrollListener());
}
public void scrollTextUp() {
mScrollView.smoothScrollBy(0, 6);
}
public void scrollTextBottom() {
mScrollView.smoothScrollBy(0, -6);
}
#Override
protected void onPause() {
mTiltScrollController.killAllSensors();
super.onPause();
}
public class TiltScrollListener implements TiltScrollController.ScrollListener {
#Override
public void onTiltUp() {
scrollTextUp();
}
#Override
public void onTiltDown() {
scrollTextBottom();
}
}
}
Cheers!!
I try to get orientation on my Android Emulator by SensorManager.getOrientation. Before this i use SensorManager.getRotationMatrix to get rotation matrix, but this always return false.
Here is code of my Activity:
public class MainActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener{
public final static String DEBUG_TAG = "MainActivity";
private SensorManager sensorManager;
private SurfaceView preview;
private float[] mGravs;
private float[] mGeoMags;
private float[] mRotationM;
private float[] mOrientation;
private Sensor mAccelerometer;
private Sensor mMagneticField;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
preview = (SurfaceView)findViewById(R.id.SurfaceView1);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mGravs = new float[3];
mGeoMags = new float[3];
mRotationM = new float[16];
mOrientation = new float[3];
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (int nI = 0; nI < sensorList.size(); nI++) {
Log.d(DEBUG_TAG, sensorList.get(nI).getName());
}
}
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event)
{
synchronized (this) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
default:
return;
}
if (mGravs != null && mGeoMags != null) {
boolean bSuccess = SensorManager.getRotationMatrix(mRotationM, null, mGravs, mGeoMags);
if (bSuccess) {
SensorManager.getOrientation(mRotationM, mOrientation);
}
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
private boolean openHardware()
{
sensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, mMagneticField, SensorManager.SENSOR_DELAY_NORMAL);
return true;
}
private void closeHardware()
{
sensorManager.unregisterListener(sensorEventListener);
}
#Override
protected void onResume()
{
super.onResume();
openHardware();
}
#Override
protected void onPause()
{
super.onPause();
closeHardware();
}
#Override
protected void onStop()
{
closeHardware();
super.onStop();
}
}
Ok, this problem occur because magnetic field sensor always return [0.0, 0.0, 0.0].
How can i make magnetic field sensor return something else?
I had the same problem. Everything got false
This answer has helped me: https://stackoverflow.com/a/14224122/1549127
In my app i wanted to show device direction such as north, south, east, west. For that i am using accelerometer and magnetic sensor and tried with following code.
public class MainActivity extends Activity implements SensorEventListener
{
public static float swRoll;
public static float swPitch;
public static float swAzimuth;
public static SensorManager mSensorManager;
public static Sensor accelerometer;
public static Sensor magnetometer;
public static float[] mAccelerometer = null;
public static float[] mGeomagnetic = null;
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event)
{
// onSensorChanged gets called for each sensor so we have to remember the values
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
mAccelerometer = event.values;
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
{
mGeomagnetic = event.values;
}
if (mAccelerometer != null && mGeomagnetic != null)
{
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mAccelerometer, mGeomagnetic);
if (success)
{
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
// at this point, orientation contains the azimuth(direction), pitch and roll values.
double azimuth = 180 * orientation[0] / Math.PI;
//double pitch = 180 * orientation[1] / Math.PI;
//double roll = 180 * orientation[2] / Math.PI;
Toast.makeText(getApplicationContext(), "azimuth: "+azimuth, Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(), "pitch: "+pitch, Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(), "roll: "+roll, Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
#Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this, accelerometer);
mSensorManager.unregisterListener(this, magnetometer);
}
}
I read some artical and come to know that azimuth value is use for getting direction. But it not shows proper value i.e it always shows value between 103 to 140 in any direction. I am using samsung galaxy s for test purpose. where i goes wrong.
Any help will be appreciated...thank you
EDIT: I'm going to keep this answer up because there are no other answers here, but my gut feeling looking at this code again is it probably doesn't work well. Use at your own risk, and if anyone ever gives a decent answer I'll delete this
Here's a compass sensor I wrote for my own use. It works, somewhat. In reality it needs better filtering- the results from the sensor are very noisy, I built a filter on top of it to slow the updates and it improved things, but it needs a much better filter if it was to be used in production
package com.gabesechan.android.reusable.sensor;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
public class CompassSensor {
SensorManager sm;
int lastDirection = -1;
int lastPitch;
int lastRoll;
boolean firstReading = true;
HashSet<CompassListener> listeners = new HashSet<CompassListener>();
static CompassSensor mInstance;
public static CompassSensor getInstance(Context ctx){
if(mInstance == null){
mInstance = new CompassSensor(ctx);
}
return mInstance;
}
private CompassSensor(Context ctx){
sm = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
onResume();
}
public void onResume(){
sm.registerListener(sensorListener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
sm.registerListener(sensorListener, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
firstReading = true;
//Restart the timer only if we have listeners
if(listeners.size()>0){
handler.sendMessageDelayed(Message.obtain(handler, 1),1000);
}
}
public void onPause(){
sm.unregisterListener(sensorListener);
handler.removeMessages(1);
}
private final SensorEventListener sensorListener = new SensorEventListener(){
float accelerometerValues[] = null;
float geomagneticMatrix[] = null;
public void onSensorChanged(SensorEvent event) {
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
accelerometerValues = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
geomagneticMatrix = event.values.clone();
break;
}
if (geomagneticMatrix != null && accelerometerValues != null && event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
float[] R = new float[16];
float[] I = new float[16];
float[] outR = new float[16];
//Get the rotation matrix, then remap it from camera surface to world coordinates
SensorManager.getRotationMatrix(R, I, accelerometerValues, geomagneticMatrix);
SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
float values[] = new float[4];
SensorManager.getOrientation(outR,values);
int direction = normalizeDegrees(filterChange((int)Math.toDegrees(values[0])));
int pitch = normalizeDegrees(Math.toDegrees(values[1]));
int roll = normalizeDegrees(Math.toDegrees(values[2]));
if((int)direction != (int)lastDirection){
lastDirection = (int)direction;
lastPitch = (int)pitch;
lastRoll = (int)roll;
}
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
//Normalize a degree from 0 to 360 instead of -180 to 180
private int normalizeDegrees(double rads){
return (int)((rads+360)%360);
}
//We want to ignore large bumps in individual readings. So we're going to cap the number of degrees we can change per report
private static final int MAX_CHANGE = 3;
private int filterChange(int newDir){
newDir = normalizeDegrees(newDir);
//On the first reading, assume it's right. Otherwise NW readings take forever to ramp up
if(firstReading){
firstReading = false;
return newDir;
}
//Figure out how many degrees to move
int delta = newDir - lastDirection;
int normalizedDelta = normalizeDegrees(delta);
int change = Math.min(Math.abs(delta),MAX_CHANGE);
//We always want to move in the direction of lower distance. So if newDir is lower and delta is less than half a circle, lower lastDir
// Same if newDir is higher but the delta is more than half a circle (you'd be faster in the other direction going lower).
if( normalizedDelta > 180 ){
change = -change;
}
return lastDirection+change;
}
public void addListener(CompassListener listener){
if(listeners.size() == 0){
//Start the timer on first listener
handler.sendMessageDelayed(Message.obtain(handler, 1),1000);
}
listeners.add(listener);
}
public void removeListener(CompassListener listener){
listeners.remove(listener);
if(listeners.size() == 0){
handler.removeMessages(1);
}
}
public int getLastDirection(){
return lastDirection;
}
public int getLastPitch(){
return lastPitch;
}
public int getLastRoll(){
return lastPitch;
}
private void callListeners(){
for(CompassListener listener: listeners){
listener.onDirectionChanged(lastDirection, lastPitch, lastRoll);
}
}
//This handler is run every 1s, and updates the listeners
//Static class because otherwise we leak, Eclipse told me so
static class IncomingHandler extends Handler {
private final WeakReference<CompassSensor> compassSensor;
IncomingHandler(CompassSensor sensor) {
compassSensor = new WeakReference<CompassSensor>(sensor);
}
#Override
public void handleMessage(Message msg)
{
CompassSensor sensor = compassSensor.get();
if (sensor != null) {
sensor.callListeners();
}
sendMessageDelayed(Message.obtain(this, 1), 1000);
}
}
IncomingHandler handler = new IncomingHandler(this);
public interface CompassListener {
void onDirectionChanged(int direction, int pitch, int roll);
}
}
Hi I am building a 3D game for Android.
I am currently trying to add a sensor to my game that allows the player to tilt the android as its controls.
Ideally I would like to use the ORIENTATION sensor, but I noticed it has been deprecated. Does anyone know how to detect tilt in the android and doesn't use this sensor?
There is no actual "orientation" sensor - this is (was) actually a composite sensor, generated from a combination of the accelerometer and the magnometer.
From http://developer.android.com/reference/android/hardware/SensorEvent.html
"This sensor type exists for legacy reasons, please use getRotationMatrix() in conjunction with remapCoordinateSystem() and getOrientation() to compute these values instead."
public class OrientationTestActivity extends Activity implements SensorEventListener
{
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
private float[] mLastAccelerometer = new float[3];
private float[] mLastMagnetometer = new float[3];
private boolean mLastAccelerometerSet = false;
private boolean mLastMagnetometerSet = false;
private float[] mR = new float[9];
private float[] mOrientation = new float[3];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
protected void onResume() {
super.onResume();
mLastAccelerometerSet = false;
mLastMagnetometerSet = false;
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
mLastAccelerometerSet = true;
} else if (event.sensor == mMagnetometer) {
System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
mLastMagnetometerSet = true;
}
if (mLastAccelerometerSet && mLastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
SensorManager.getOrientation(mR, mOrientation);
Log.i("OrientationTestActivity", String.format("Orientation: %f, %f, %f",
mOrientation[0], mOrientation[1], mOrientation[2]));
}
}
}