Android 传感器:getRotationMatrix() 返回错误值,为什么?

发布于 2024-12-14 10:48:26 字数 3093 浏览 3 评论 0原文

我开始使用这个功能已经过去几天了,但还没有成功获得有效的结果。

我想要的是基本上将加速度矢量从设备的坐标系转换为现实世界坐标。我知道这是可能的,因为我有相对坐标的加速度,并且我知道设备在现实世界系统中的方向。

阅读Android开发人员似乎使用getRotationMatrix()我得到 R = 旋转矩阵。

因此,如果我想要 A'(电话系统中的加速度矢量)中的 A(世界系统中的加速度矢量),我必须简单地做:

  A=R*A'

但我无法理解为什么矢量 A 的第一个和第二个分量始终为零< /strong> (示例:+0,00;-0,00;+6,43)

我当前的代码与此类似:

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

        }
      }
   }

这个问题与这个问题非常相似 将加速度计数据从设备坐标转换为现实世界坐标但我找不到解决方案...我已经尝试了所有方法..

请帮助我,我需要帮助!

更新:

现在我的代码在下面,我试图解释矩阵乘积,但没有任何变化:

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

这里是一些数据读取和结果的示例:

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

“来自

您可以注意到,即使您快速移动手机,现实世界中 x 轴和 y 轴上的分量也为零(左右)。相反,相对加速度矢量正确检测每个运动!

解决方案 编号中的错误与浮点变量乘法相关,与双倍乘法不同。 综上所述,如果手机正在加速,即使方向相同,旋转矩阵也不是恒定的。 所以在运动过程中不可能将加速度矢量转换为绝对坐标... 这很难,但这就是现实。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无畏 2024-12-21 10:48:26

最后我找到了答案:

数字中的错误与浮点变量乘法相关,与双乘法不同。 这里有解决方案。
综上所述,如果手机正在加速,即使方向相同,旋转矩阵也不是恒定的。所以不可能在运动过程中将加速度矢量转换为绝对坐标......这很难,但这是现实。

仅供参考,方向矢量由磁力数据和重力矢量组成。这导致了一个循环问题:转换相对加速度需要方向需要磁场和重力,但只有当手机通过相对加速度停止时我们才知道重力。所以我们回到开始。

这在Android 开发人员在哪里解释旋转矩阵给出 true仅当手机未加速(例如,他们谈论自由落体,实际上不应该进行重力测量)或不在非常规磁场中时才会产生结果。

此函数返回的矩阵仅在以下情况下才有意义
设备不是自由落体并且不靠近磁北。
如果设备正在加速,或置于强磁场中,
返回的矩阵可能不准确。

在其他世界中,完全没有用......
你可以相信这个东西在桌子上用 Android Senor 或类似的东西做简单的实验。

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

病毒体 2024-12-21 10:48:26

在担心旋转、加速度或其他任何问题之前,您必须先找出这个算术错误。

您已经确认这

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

给了您

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

所以再次简化。试试这个:

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

编辑:
最后一个给出 resultVec[0]=1.36,所以让我们试试这个:

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

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];
单挑你×的.吻 2024-12-21 10:48:26

如果您使用附加的打印值进行求和,我得到的

`(0.00112, -0.0004, 10)`

值并不像您所拥有的那么小。因此存在算术错误!

问题可能是您在最后一个块中使用了 accelerationvalues[] ,然后又使用了 accelerometervalues[] 吗?

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?

潦草背影 2024-12-21 10:48:26

我开发了几个使用 android 传感器 的应用程序,所以我正在回答其中之一根据我的经验,你的问题是:

但我无法理解为什么向量 A 总是第一个和第一个
第二个分量为零(例如:+0,00;-0,00;+6,43)

我也用加速度传感器和磁场传感器观察到这个问题。某些轴的读数为零(当您指向时为两个,或者在其他情况下仅为一个)。当您刚刚启用传感器 (registerListener()) 时会发生此问题,我认为它与某种传感器初始化有关。
就加速度传感器而言,我观察到,只要设备轻微晃动,它就会开始给出正确的传感器读数。

正确的解决方案是使用提供有关传感器状态的正确信息的方法onAccuracyChanged()。它应该返回 SensorManager.SENSOR_STATUS_UNRELIABLE 的状态,但相反,它在我迄今为止测试过的所有物理设备上永久返回 SensorManager.SENSOR_STATUS_ACCURACY_HIGH。通过正确实现 onAccuracyChanged() 方法,您可以忽略错误的读数或要求用户在传感器初始化时等待。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文