Transforming accelerometer's data from device's coordinates to real world coordinates
Solution 1
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])));
Solution 2
You need to be able to know the reference coordinate system that also gives you the orientation of your device within 'real' world coordinates. Without that information, it look impossible to transform your data into anything useful.
For example, does your device have a type of 'directional' sensor that would help make sense of the accelerometer data (gyro & compass for example?)
Solution 3
I am dealing with the same problem. What you can do is, as you have the R[] matrix multiply your acceleration vector and voilá.
float resultVec[] = new float[4];
Matrix.multiplyMV(trueacceleration, 0, R, 0, accelerometervalues, 0);
PS: accelerometervalues must be a 4 field vector, just add 0 to the last field.
Solution 4
Try this, its working for me
private float[] gravityValues = null;
private float[] magneticValues = null;
private SensorManager mSensorManager = null;
private void registerSensorListener(Context context) {
mSensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),
SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
public void onSensorChanged(SensorEvent event) {
if ((gravityValues != null) && (magneticValues != null)
&& (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)) {
float[] deviceRelativeAcceleration = new float[4];
deviceRelativeAcceleration[0] = event.values[0];
deviceRelativeAcceleration[1] = event.values[1];
deviceRelativeAcceleration[2] = event.values[2];
deviceRelativeAcceleration[3] = 0;
Log.d("Raw Acceleration::","Values: (" + event.values[0] + ", " + event.values[1] + ", " + event.values[2] + ")");
// Change the device relative acceleration values to earth relative values
// X axis -> East
// Y axis -> North Pole
// Z axis -> Sky
float[] R = new float[16], I = new float[16], earthAcc = new float[16];
SensorManager.getRotationMatrix(R, I, gravityValues, magneticValues);
float[] inv = new float[16];
android.opengl.Matrix.invertM(inv, 0, R, 0);
android.opengl.Matrix.multiplyMV(earthAcc, 0, inv, 0, deviceRelativeAcceleration, 0);
Log.d("Earth Acceleration", "Values: (" + earthAcc[0] + ", " + earthAcc[1] + ", " + earthAcc[2] + ")");
} else if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
gravityValues = event.values;
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticValues = event.values;
}
}
Related videos on Youtube
Tommy
Updated on June 24, 2020Comments
-
Tommy about 4 years
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 matrixI
.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 matrixR
(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 toremapcoordinates()
and then multiply in any of the previous forms.Does anybody have an idea about what am I doing wrong?
-
Tommy over 13 yearsIt has a magnetic field sensor. I can get information about orientation in addition to acceleration. I have already tested and I can obtain the actual azimuth,pitch and roll of my device, the problem is that I don't exacly know what to do once I have a vector of accelerations (ax,ay,az) -in device's coordinate system- and an orientation vector (azimuth, pitch,roll) to get the acceleration of the device in real world coordinates. I have searched in a lot of pages but haven't found anything useful. The official documentation seems to be a little cryptical about this topic. Thanx 4 your response.
-
pzo about 12 yearscan you elaborate on that and provide more details how you obtained that solution? I mean explain the equation because it looks complicated.
-
pzo about 12 yearsI've tested your snippet and all I get is a quite noisy random signal in return.
-
this-Me almost 12 yearsHi. Which formula/matrix you used to convert this to real world co-ordinates ?
-
k8C almost 7 yearsCan you show or point me to other sources with a non-code explanation for this? I mean an explanation in terms of maths?