Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transforming accelerometer's data from device's coordinates to real world coordinates

I'm really sorry if this is a very basic question, but I have not choice but ask it: How do you translate the accelerometer data from the device coordinates to real world coordinates?

I mean, assuming that the accelerometer is giving me somenting like (Ax,Ay,Az) -in device's coordinates-, what transformations should I apply to transform the values into (Ax',Ay',Az') -in real world's coordinates-, so I can use the acceleration vector in real worlds coordinates to calculate if the device is accelerating north, east, south-west,etc?

I have been working around this issue during the past few days. At first I thought that it shound't be difficult, but after searching dozens of pages I haven't come up with anything functional.

By the way, here is some code with what I've implemented so far:

    private SensorEventListener mSensorEventListener = new SensorEventListener() {

    public void onAccuracyChanged(Sensor sensor, int accuracy){
}

    public void onSensorChanged(SensorEvent event) {
        switch(event.sensor.getType()){
        case Sensor.TYPE_ACCELEROMETER:
            accelerometervalues = event.values.clone();
            AX.setText(accelerometervalues[0]+"");
            AY.setText(accelerometervalues[1]+"");
            AZ.setText(accelerometervalues[2]+"");
            break;
        case Sensor.TYPE_ORIENTATION:
            orientationvalues = event.values.clone();
            azimuth.setText(orientationvalues[0]+"");
            pitch.setText(orientationvalues[1]+"");
            roll.setText(orientationvalues[2]+"");
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomagneticmatrix =event.values.clone();
            TAX.setText(geomagneticmatrix[0]+"");
            TAY.setText(geomagneticmatrix[1]+"");
            TAZ.setText(geomagneticmatrix[2]+"");
            break;
        }
        if (geomagneticmatrix != null && accelerometervalues != null) {
            float[] R = new float[16];
            float[] I = new float[16];
            SensorManager.getRotationMatrix(R, I, accelerometervalues, geomagneticmatrix);
            //What should I do here to transform the components of accelerometervalues into real world acceleration components??
        }
   }
};

I have:

A vector of accelerations in native coordinates in accelerometervalues.

A vector of magnetic field values in geomagneticmatrix.

Azimuth, pitch and roll in orientationvalues.

Rotation matrix R. Inclination matrix I.

I think all the necessary information is there, azimuth, pitch and roll should describe the displacement of the device's coordinate system in relation with the real world coordinate system. Also, I believe that R is/can even be used as a true north vector inside the devices coordinates.

It seems to me that obtaing the values of acceleration in real world is just a mathematical transformation away from those data. I just can't figure it out.

Thanks in advance.

Edited:

I have tried directly multipliying the components of accelerometervalues with the rotation matrix R (trueaccel=accel*R) but it didn't work.

                    trueacceleration[0]= accelerometervalues[0]*R[0]+accelerometervalues[1]*R[1]+accelerometervalues[2]*R[2];
                trueacceleration[1]= accelerometervalues[0]*R[1]+accelerometervalues[1]*R[4]+accelerometervalues[2]*R[7];
                trueacceleration[2]= accelerometervalues[0]*R[2]+accelerometervalues[1]*R[5]+accelerometervalues[2]*R[8];

I have also tried multipliying accelerometervalues with the inclination matrix I. Also multipliying with both R and I (trueaccel=accel*R*I) and that didn't work either. Neither does calling to remapcoordinates() and then multiply in any of the previous forms.

Does anybody have an idea about what am I doing wrong?

like image 762
Tommy Avatar asked Mar 28 '11 20:03

Tommy


1 Answers

Oki, I have worked this out mathematically myself so please bear with me.

If you want to translate an acceleration vector accelerationvalues into an acceleration vector trueacceleration expressed in real world's coordinates, once you have azimuth,pitch and roll stored in a orientationvalues vector, just do the following:

                trueacceleration[0] =(float) (accelerometervalues[0]*(Math.cos(orientationvalues[2])*Math.cos(orientationvalues[0])+Math.sin(orientationvalues[2])*Math.sin(orientationvalues[1])*Math.sin(orientationvalues[0])) + accelerometervalues[1]*(Math.cos(orientationvalues[1])*Math.sin(orientationvalues[0])) + accelerometervalues[2]*(-Math.sin(orientationvalues[2])*Math.cos(orientationvalues[0])+Math.cos(orientationvalues[2])*Math.sin(orientationvalues[1])*Math.sin(orientationvalues[0])));
            trueacceleration[1] = (float) (accelerometervalues[0]*(-Math.cos(orientationvalues[2])*Math.sin(orientationvalues[0])+Math.sin(orientationvalues[2])*Math.sin(orientationvalues[1])*Math.cos(orientationvalues[0])) + accelerometervalues[1]*(Math.cos(orientationvalues[1])*Math.cos(orientationvalues[0])) + accelerometervalues[2]*(Math.sin(orientationvalues[2])*Math.sin(orientationvalues[0])+ Math.cos(orientationvalues[2])*Math.sin(orientationvalues[1])*Math.cos(orientationvalues[0])));
            trueacceleration[2] = (float) (accelerometervalues[0]*(Math.sin(orientationvalues[2])*Math.cos(orientationvalues[1])) + accelerometervalues[1]*(-Math.sin(orientationvalues[1])) + accelerometervalues[2]*(Math.cos(orientationvalues[2])*Math.cos(orientationvalues[1])));
like image 91
Tommy Avatar answered Sep 28 '22 05:09

Tommy