What is the alternative to android orientation sensor? - android

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]));
}
}
}

Related

To get accurate Orientaion on android phone

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.

How to use sensors rotation matrix in min3d to rotate parsed object

I want to rotate objects parsed from .obj file in min3d.
I need to use a rotation matrix got from sensors. I know how to do this in pure OpenGL but I can't figure out what to use (min3d.core.Renderer probably?) and how in min3d.
I like min3d and it parses .obj files very nicely so I don't really want to abandon it and use pure openGL.
I know i can use the rotate() method but it uses Eulers angles and i need to use rotation matrix.
Here's the code:
public class HurleyLoading extends RendererActivity implements SensorEventListener{
private Object3dContainer hurleyModel;
private SensorManager sensorManager;
private Sensor sensorAcc;
private Sensor sensorMagnetic;
private float[] accelData = new float[3];
private float[] magnetData = new float[3];
private final float[] rotationMatrix = new float[16];
float[] orientation = new float[3];
#Override
public void onCreate(Bundle b){
super.onCreate(b);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorAcc = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
public void onResume()
{
super.onResume();
sensorManager.registerListener(this, sensorAcc, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, sensorMagnetic, SensorManager.SENSOR_DELAY_GAME);
}
public void onStart()
{
super.onStart();
sensorManager.registerListener(this, sensorAcc, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, sensorMagnetic, SensorManager.SENSOR_DELAY_GAME);
//this.onResume();
}
public void onPause()
{
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void initScene() {
scene.lights().add(new Light());
scene.lights().add(new Light());
scene.lights().add(new Light());
scene.lights().add(new Light());
scene.lights().add(new Light());
scene.lights().add(new Light());
scene.lights().add(new Light());
IParser parser = Parser.createParser(Parser.Type.OBJ,
getResources(), "ie.tyndall.hurleyopengl:raw/hurley_obj", true);
parser.parse();
hurleyModel = parser.getParsedObject();
hurleyModel.scale().x = hurleyModel.scale().y = hurleyModel.scale().z = 1.4f;
hurleyModel.position().y = -1.8f;
hurleyModel.position().x = .4f;
scene.addChild(hurleyModel);
}
#Override
public void updateScene() {
/**some rotation code can go here but rotation() method has to use
* eulers angles (X/Y/Z euler rotation of object, using Euler angles.
* Units should be in degrees, to match OpenGL usage)which is no use for me
* as i need to use rotation matrix
**/
}
//#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
loadSensorData(event);
SensorManager.getRotationMatrix(rotationMatrix, null, accelData,
magnetData);
}
private void loadSensorData(SensorEvent event) {
final int type = event.sensor.getType();
if (type == Sensor.TYPE_ACCELEROMETER) {
accelData = event.values.clone();
}
if (type == Sensor.TYPE_MAGNETIC_FIELD) {
magnetData = event.values.clone();
}
}
}
I think you have to calculate angle from your rotation matrix and set it in updateScene() like this:
obj.rotation().x = ?
obj.rotation().y = ?
obj.rotation().z = ?

Android compass issue

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 :)

android - tilt to scroll the text?

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!!

SensorManager.getRotationMatrix always return false on Android Emulator

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

Categories

Resources