Question

It's past several days since I started using this function and have not yet succeeded in obtaining valid results.

What i want is basically convert acceleration vector from device's coordinates system, to real world coordinates. I' know that is possible because i have acceleration in relative coordinates and i know the orientation of the device in real world system.

Reading Android developers seems that using getRotationMatrix() i get R = rotation matrix.

So if i want A (acceleration vector in world system) from A' (acceleration vector in phone system) i must do simply:

  A=R*A'

But i cant'n understand why the vector A has ALWAYS the first and the second component zero (example: +0,00;-0,00;+6,43)

My current code is similar to this:

  public void onSensorChanged(SensorEvent event) {
     synchronized (this) {   
        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) {
            float[] Rs = new float[16];
            float[] I = new float[16];
            SensorManager.getRotationMatrix(Rs, I, accelerometervalues, geomagneticmatrix);
            float resultVec[] = new float[4];
            float relativacc[]=new float [4];
                relativacc[0]=accelerationvalues[0];
                relativacc[1]=accelerationvalues[1];
                relativacc[2]=accelerationvalues[2];
                relativacc[3]=0;
            Matrix.multiplyMV(resultVec, 0, Rs, 0, relativacc, 0);

            //resultVec[] is the vector acceleration relative to world coordinates system..but doesn't WORK!!!!!

        }
      }
   }

This question is very similar to this one Transforming accelerometer's data from device's coordinates to real world coordinates but there i can't find the solution...i had tried all the ways..

Please help me, i need help!!!

UPDATE:

Now my code is below, i had tried to explain matrix product, but nothing change:

            float[] Rs = new float[9];
            float[] I = new float[9];
            SensorManager.getRotationMatrix(Rs, I, accelerationvalues, geomagneticmatrix);
            float resultVec[] = new float[4];

            resultVec[0]=Rs[0]*accelerationvalues[0]+Rs[1]*accelerationvalues[1]+Rs[2]*accelerationvalues[2];
            resultVec[1]=Rs[3]*accelerationvalues[0]+Rs[4]*accelerationvalues[1]+Rs[5]*accelerationvalues[2];
            resultVec[2]=Rs[6]*accelerationvalues[0]+Rs[7]*accelerationvalues[1]+Rs[8]*accelerationvalues[2];

Here some example of data read and result:

Rs separated by " " Rs[0] Rs[1]....Rs[8]
Av separated by " " accelerationvalues[0] ...accelerationvalues[2]
rV separated by " " resultVec[0] ...resultVec[2]

Data from CAT manager

As you can notice the component on x and y axes in real world are zero (around) even if you move speddy the phone. Instead the relative acceleration vector detect correctly each movement!!!

SOLUTION The errors in the numberrs are relative to float vars multiplication that is not the same as a double multyplication. This sums to the fact that rotation matrix isn't costant if the phone, even if with the same orientation, is accelerating. So is impossible translate acceleration vector to absolute coordinates during motion... It's hard but it's the reality.

Was it helpful?

Solution

Finnaly i found the answer:

The errors in the numbers are relative to float vars multiplication that is not the same as a double multyplication. Here there is the solution. This sums to the fact that rotation matrix isn't costant if the phone, even if with the same orientation, is accelerating. So is impossible translate acceleration vector to absolute coordinates during motion... It's hard but it's the reality.

FYI the orientation vector is made from magnetomer data AND gravity vector. This cause a ciclic problem: convert relative acc needs oirentation needs magnetic field AND gravity, but we know gravity only if the phone is stop by relative acc..so we are return to begin.

This is confirmed in Android Developers where is explained that rotation matrix give true result only when the phone isn't accelerate (e.g. they talk of free fall, infact there shouldn't be gravity mesaurement) or when it isn't in a non regulare magnetic field.

The matrices returned by this function are meaningful only when the device is not free-falling and it is not close to the magnetic north. If the device is accelerating, or placed into a strong magnetic field, the returned matrices may be inaccurate.

In others world, fully un-useful... You can trust this thing doing simple experiment on the table with Android Senor or something like this..

OTHER TIPS

You must track down this arithmetic error before you worry about rotation, acceleration or anything else.

You have confirmed that

resultVec[0]=Rs[0]*accelerationvalues[0];

gives you

Rs[0]: 0.24105562
accelerationValues[0]: 6.891896
resultVec[0]: 1.1920929E-7

So once again, simpify. Try this:

Rs[0] = 0.2;
resultVec[0] = Rs[0] * 6.8

EDIT:
The last one gave resultVec[0]=1.36, so let's try this:

Rs[0] = 0.2;
accelerationValues[0] = 6.8
resultVec[0] = Rs[0] * accelerationValues[0];

If you do the sums, using the printed values you have appended, I get

`(0.00112, -0.0004, 10)`

which is not as small as what you have. Therefore there is an arithmetic error!

Could the problem be that you are using accelerationvalues[] in the last block, and accelerometervalues[] later?

I have developed several applications that make use of android sensors, so I am answering to one of your questions according to my experience:

But i cant'n understand why the vector A has ALWAYS the first and the second component zero (example: +0,00;-0,00;+6,43)

I have observed this problem with the acceleration sensor and the magnetic field sensor, too. The readings are zero for some of the axis (two as you point, or just one in other occasions). This problem happens when you have just enabled the sensors (registerListener()) and I assume that it is related to some kind of sensor initialization. In the case of the acceleration sensor, I have observed that just a small shaking of the device makes it to start giving correct sensor readings.

The correct solution would be the method onAccuracyChanged() giving the correct information about the sensor state. It should be returning a staus of SensorManager.SENSOR_STATUS_UNRELIABLE, but instead of that, it permanently returns SensorManager.SENSOR_STATUS_ACCURACY_HIGH on all physical devices that I have tested so far. With the method onAccuracyChanged() properly implemented, you could ignore bad readings or ask the user to wait while the sensor is being initialized.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top