how to getRotationMatrix having only accelerometer sensor in device - android

I want to get device rotation and i have achieved somehow but the code is not working which device is not present with Magentic sensor,Orientation sensor and Gyroscope sensor. But i have seen some app those are working like XClinometer and iHandy level free on device .Having device htc Explorer not giving value as not present with these sensor.please tell me how i can achieve this task.
I have use this code but as sensor not available so not getting any value so no rotation matrix as well.
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
// copy new accelerometer data into accel array and calculate
// orientation
System.arraycopy(event.values, 0, accel, 0, 3);
calculateAccMagOrientation();
break;
case Sensor.TYPE_GYROSCOPE:
// process gyro data
gyroFunction(event);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
// copy new magnetometer data into magnet array
System.arraycopy(event.values, 0, magnet, 0, 3);
break;
}
}
and the method is
public void calculateAccMagOrientation() {
if (SensorManager.getRotationMatrix(rotationMatrix, null, accel,
magnet)) {
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X,
SensorManager.AXIS_Y, mValuesOrientation);
SensorManager.getOrientation(rotationMatrix, mValuesOrientation);
}else{
//float[] array = new float[9];
if(magnet[0]<=0){
System.out.println("herr.....");
System.out.println();
}else{
System.out.println("null so herr.....");
}
/*on htc device it is coming here so i need code here to get angle as only received accelerometer sensor data.
*/
}
}

The examples you link to only need the tilt angles, not the rotation matrix. It is enough to have accelerometers to get the tilt angles.
The rotation matrix contains more information than the tilt angles and it requires gyroscopes as well.

Related

How to use TYPE_ROTATION_VECTOR to get acceleration in global Z

In my app I am using the accels sensor to calculate whether user is jumping irregardless of phones orientation. So I am trying to use TYPE_ROTATION_VECTOR to create rotation matrix, but after I multiple it against vector, values do not come out correctly. As a test I am actually using the TYPE_GRAVITY_SENSOR values, as if the transforms are correct, Z should always show the gravity. What am I doing wrong here?
switch(event.sensor.getType()) {
case Sensor.TYPE_GRAVITY:
if (mRotationMatrix[0] != 0) {
Matrix.multiplyMV(transformedGravity, 0,
mRotationMatrix, 0,
new float[]{event.values[0], event.values[1], event.values[2], 0}, 0);
// If I tilt phone, and break in debugger, transformedGravity[2] is not 9.8, and [0] is something like 6mps.
}
break;
case Sensor.TYPE_ROTATION_VECTOR:
SensorManager.getRotationMatrixFromVector(mRotationMatrix,
event.values);
break;
}

Measuing car rotation with Android phone

I have found many threads about how to handle the device' rotation,orientation with motion and position sensors.
I would like to create an app which i will use in my car, first i would like to measure the rotation degree of the car.
So i put my phone to a phone case and for example when i turn left with the car i would like to see the car' turning degree on the phone.
Is it possible by magnetic and accelero meter?
I post a code that for first i think okay. (let's say that i hold my phone "portait" mode so not landscape for first)
private static SensorManager sensorService;
//magnetic
private Sensor mSensor;
//accelerometer
private Sensor gSensor;
private float[] mValuesMagnet = new float[3];
private float[] mValuesAccel = new float[3];
private float[] mValuesOrientation = new float[3];
private float[] mRotationMatrix = new float[9];
#Override
public void onCreate(Bundle savedInstanceState) {
nf.setMaximumFractionDigits(2);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sensorService = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
this.mSensor = sensorService.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
this.gSensor = sensorService.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorService.registerListener(this, gSensor, SensorManager.SENSOR_DELAY_NORMAL);
sensorService.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
// double azimuth = Math.toDegrees(mValuesOrientation[0]); //azimuth, rotation around the Z axis.
// double pitch = Math.toDegrees(mValuesOrientation[1]); // pitch, rotation around the X axis.
double roll = Math.toDegrees(mValuesOrientation[2]); //roll, rotation around the Y axis.
//normalize
// azimuth = azimuth>0?azimuth:azimuth+360;
roll = roll>0?roll:roll+360;
String txt = "roll= "+Math.round(roll);
((EditText)findViewById(R.id.szog)).setText(txt);
}
Questions:
- How accurate will this app in a car? (what can i do to be more accurate?)
- What should i do when i hold my phone at "landscape" mode?
Is the roll from orientation still okay?
Please note that this is a very first try so there are so much to do!
But first i want to see how can i achive that
Thanks!
If you had your Android device set up like a compass, then there would be an arrow that always pointed to magnetic north. So by measuring the change in the direction of that arrow, you could measure the rotation of your car.
To get a better indication of the orientation of your Android device, use
Sensor.TYPE_GRAVITY and Sensor.TYPE_MAGNETIC_FIELD, instead of Sensor.TYPE_ACCELEROMETER and Sensor.TYPE_MAGNETIC_FIELD. This is better because Sensor.TYPE_GRAVITY tries to filter out the effects due to the movement of the device.
If the Android device is lying flat on a surface, then the direction of magnetic north is defined by the azimuth that comes out of SensorManager.getOrientation(...). When it's standing up or when it's on its side then it's a bit more complicated. However, I suggest starting with the device lying flat first because that's the easiest case, and then you can progress to more difficult cases.

Get tilt angle from the android accelerometer

I have a class that implements SensorEventListener and I would like to get
the tilt Angle of my device using the Accelerometer.
I looked for examples on the internet but they use
Sensor.TYPE_MAGNETIC_FIELD.
I believe my device doesn't have this sensor because when I do the
following check
manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size(), I get zero.
Is there a way to get the tilt Angle by just using
Sensor.TYPE_ACCELEROMETER values?
As people suggested you can use the accelerometer and magnetic sensor to do this.
Here is a blog post with a complete solution.
http://www.ahotbrew.com/how-to-detect-forward-and-backward-tilt/
Try this,
SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
final SensorEventListener mEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
break;
}
};
};
setListners(sensorManager, mEventListener);
SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
final CharSequence test;
test = ","+mValuesOrientation[0] +","+mValuesOrientation[1]+ ","+ mValuesOrientation[2];
You can use the accelerometer to get a tilt reading. If you set up an accelerometer you will notice it includes the force of gravity. So if you phone is face-up on a table the z-axis will register somewhere close to 9.81 (the force of gravity) and the x and y axes will be at 0. As you tilt the phone the force of gravity will be projected onto the x and/or y axis. Thus you the x and y values will tell you the tilt of the phone.

Compass and Accelerometer precision

i made my own application in Android that use compass and accelerometer sensors to display the degrees of rotation and inclination of my device. I initialized all the listener and objects i needed (i followed some tutorials), and now i can catch the degrees as i wished. The problem is that the measures that sensors return aren't accurate. I mean even if i try to round the values of degrees i catch from the sensor, they oscillate between -/+ 7 (or 8) degrees every fraction of a second, even if i stay in a grass field away from any disturbing source. What i want to have is a accurate measure of the degrees, something like a method to round the values i recieve from the sensors.
float[] mags = null;
float[] accels = null;
float[] R = new float[matrix_size];
float[] outR = new float[matrix_size];
float[] I = new float[matrix_size];
float[] values = null;
private void startSensor() {
sensorMan.registerListener(this, sensorMan.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
sensorMan.registerListener(this, sensorMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return;
}
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
mags = event.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER:
accels = event.values.clone();
break;
}
if (mags != null && accels != null) {
SensorManager.getRotationMatrix(R, I, accels, mags);
// Correct if screen is in Landscape
SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X,
SensorManager.AXIS_Z, outR);
SensorManager.getOrientation(outR, values);
azimuth = (float) Math.round((Math.toDegrees(values[0]))*7)/7;
azimuth = ( azimuth + 360)%360;
//here is inclination. The problem is just the same with compass
//inclination=-Math.round((float) (values[1]*(360/(2*Math.PI))));
//other code to update my view
//in azimuth i have the degree value. It changes continuously
//even if i aim still the same direction
}
}
See my answer here: Smoothing data from a sensor
I run this filter on both the accelerometer and magetometer event values before passing them to SensorManager.getRotationMatrix(). I think this algorithm has the advantage of not having to keep a large array of historic values, just the prior low-pass output array.
The algorithm was derived from this Wikipedia entry: http://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation
What you're seeing is the real thing- the orientation sensors on most phones are only good enough to give you a rough compass heading.
If you want to smooth the displayed value out so it gives you something that's doesn't appear to change randomly I recommend implementing a http://en.wikipedia.org/wiki/Moving_average or other smoothing filter in Java on that orientation result.
For the highest performance you could write the filter using the NDK and use the Boost Accumulators library: http://www.boost.org/doc/libs/1_46_1/doc/html/accumulators.html
I did this using a Kalman filter from here:
Greg Czerniak's Website
I'm sending data to a udp port and smoothing it on the PC using python.
But I guess you can find a Kalman filter implementation for java/android out there.

Question about the rotation of X axis on Android

I want to detect the correct rotations around X axis with Android sensors. After googling, I find this code:
public void onSensorChanged(SensorEvent event) {
Sensor sensor = event.sensor;
switch(sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
mAcc = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mMag = event.values.clone();
break;
}
if (mAcc == null || mMag == null) return;
float R[] = new float[9];
if (SensorManager.getRotationMatrix(R, null, mAcc, mMag)) {
SensorManager.getOrientation(R, mOrientation);
}
}
mOrientation[1] represents the radians around the X axis. However, the value is very odd.
When the phone lies flat top up on the table, it's 0.
When the head of the phone pointing to the ground, it's PI/2.
When the phone lies flat bottom up on the table, it's 0 again.
When the head of the phone pointing to the sky, it -PI/2.
The states between 1,2 have the same rotation values of those between 2,3. How could I tell which state my phone is in?
Please verify your readings.
The signs & range you report are completely out of sync with
what is expected on an android device.
developer.android.com/reference/android/hardware/Sensor.html#TYPE_ORIENTATION
Note: This sensor type exists for legacy reasons, please use getRotationMatrix() in conjunction with remapCoordinateSystem() and getOrientation() to compute these values instead.
Regards
CVS#2600Hertz

Categories

Resources