从设备坐标系到绝对坐标系的加速度

Posted

技术标签:

【中文标题】从设备坐标系到绝对坐标系的加速度【英文标题】:Acceleration from device's coordinate system into absolute coordinate system 【发布时间】:2012-07-19 16:30:51 【问题描述】:

从我的 android 设备中,我可以读取一组线性加速度值(在设备的坐标系中)和一组绝对方向值(在地球坐标系中)。我需要的是在后一个坐标中获得线性加速度值。系统。

如何转换它们?

EDIT在阿里回复评论后:

好吧,如果我理解正确的话,当我测量线性加速度时,手机的位置完全无关紧要,因为读数是在地球坐标系中给出的。对吧?

但我刚刚做了一个测试,我将手机放在不同的位置,并在不同的轴上获得加速度。有 3 对图片 - 第一张显示我是如何放置设备的(对不起我的 Paint “大师技能”),第二张显示来自线性 acc 提供的数据的读数。传感器:

    设备放在左侧

    设备仰卧

    设备站立

现在 - 为什么在第三种情况下加速度发生在 Z 轴(而不是 Y),因为设备位置无关紧要?

【问题讨论】:

进行测量时手机是否静止(完全静止)?纵轴是什么?例如 -14 是什么意思? 在测量过程中,我沿着东西轴非常快速地移动手机(正如那些油漆图所示)以创建加速度读数(-14 是以 m/s*s 为单位的加速度)。如这里所示link 测量坐标系是手机的坐标系。 好的,现在我明白你的实验了。我会修正我的答案。 好的,这是我的错误,非常抱歉。我已经确定了我的答案。另外,我赞成你的问题。 @MuhammadBabar 编程将读数保存到设备上的文件中,然后手动导入到 Excel 中。没什么花哨的 【参考方案1】:

我终于设法解决了!因此,要在地球坐标系中获得加速度矢量,您需要:

    SensorManager.getRotationMatrix() (使用SENSOR.TYPE_GRAVITYSENSOR.TYPE_MAGNETIC_FIELD 传感器值作为参数)获取旋转矩阵(float[16] 以便稍后由android.opengl.Matrix 类使用), 在旋转矩阵上使用android.opengl.Matrix.invertM() 来反转它(不是转置!), 使用Sensor.TYPE_LINEAR_ACCELERATION 传感器获取线性加速度矢量(在设备的坐标系中), 使用android.opengl.Matrix.multiplyMV() 将旋转矩阵乘以线性加速度向量。

你有它!我希望我能为别人节省一些宝贵的时间。

感谢 Edward Falk 和 Ali 的提示!!

【讨论】:

在第 4 步中,您不能直接使用传感器数据,因为它的长度为 3,而您需要长度为 4。您是在末尾添加 0 还是在开头添加 1? @NinovanHooff 在第 4 个位置(数组 [3])应该是 0 值 进行反转可能是因为旋转矩阵是根据世界轴而不是手机轴计算的,正如这里提到的(gentlenav.googlecode.com/files/DCMDraft2.pdf)。这是一篇在第 III.A 节中描述相同方法的科学论文 (ece.nus.edu.sg/stfpage/elesohws/PerCom_Pedestrian_Tracking.pdf) @alex 你能发布你将线性加速度校正为世界坐标的代码吗?我的传感器侦听器正在使用 Sensor.TYPE_ROTATION_VECTOR 创建一个旋转矩阵,它工作得很好,但我似乎无法按照您描述的方式纠正 linear_acceleration .. 代码示例会很棒 你为什么在SensorManager.getRotationMatrix()中使用SENSOR.TYPE_GRAVITY?文档 (developer.android.com/reference/android/hardware/…, float[], float[], float[])) 说要使用 TYPE_ACCELEROMETER 的值【参考方案2】:

根据@alex 的回答,这里是代码sn-p:

private float[] gravityValues = null;
private float[] magneticValues = null;

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

            // 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("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;
         
   

【讨论】:

成功了!谢谢@orak!我没有重力传感器类型,所以我只是使用低通滤波器来获得它。 我很抱歉@orak,但什么是“开始”变量?控制流量?我不确定。 @Saeger 你说得对,不需要,我可能是为了流量控制而写的,后来不需要了 @orak 你能解释一下如果我想让 X 轴指向真北和 Z 垂直应该怎么做吗? @pixie 只是交换 x 和 y 值?【参考方案3】:

According to the documentation你得到手机坐标系中的线性加速度。

您可以将任何矢量从手机坐标系转换为地球坐标系,方法是将其与旋转矩阵相乘。可以从getRotationMatrix()获取旋转矩阵。

(也许已经有一个函数为你做这个乘法,但我不做 Android 编程,我不熟悉它的 API。)

关于旋转矩阵的一个很好的教程是Direction Cosine Matrix IMU: Theory 手稿。祝你好运!

【讨论】:

感谢您的回答!看起来它应该可以正常工作,但我不知道为什么它不能正常工作。请看看我对 Edward Falk 回答的评论,我解释了还有什么问题。【参考方案4】:

好的,首先,如果您想在 Android 上进行实际的惯性导航,那么您的工作已经完成。智能手机中使用的廉价小传感器不够精确。虽然,在小距离的内部导航方面已经完成了一些有趣的工作,例如在建筑物内。可能有关于你可以挖掘的主题的论文。谷歌“Motion Interface Developers Conference”,你可能会发现一些有用的东西——这是 Invensense 几个月前举办的一次会议。

第二,不,线性加速度在设备坐标中,而不是世界坐标中。你必须自己转换,这意味着知道设备的 3-d 方向。

您要做的是使用支持虚拟传感器 TYPE_GRAVITY 和 TYPE_LINEAR_ACCELERATION 的 Android 版本。您需要一个带有陀螺仪的设备才能获得相当准确和精确的读数。

在内部,系统结合了陀螺仪、加速度计和磁力计,以便为设备方向提供真实值。这有效地将加速度计设备拆分为重力和加速度分量。

所以您要做的是为 TYPE_GRAVITY、TYPE_LINEAR_ACCELERATION 和 TYPE_MAGNETOMETER 设置传感器侦听器。使用重力和磁力计数据作为 SensorManager 的输入。 getRotationMatrix() 以获取将世界坐标转换为设备坐标的旋转矩阵,反之亦然。在这种情况下,您需要“反之”部分。即通过将线性加速度输入乘以方向矩阵的转置,将其转​​换为世界坐标。

【讨论】:

我确实像你说的那样 - 我通过将旋转矩阵 R(来自getRotationMatrix() 提供的重力和磁场数据)和线性加速度矢量相乘获得了加速度矢量 A(在地球坐标系中) V(来自设备坐标系中的 lin.acc.sensor),如下所示:A=RV。但是我没有得到好的结果。我将手机放在站立位置(Y 轴向上)并上下移动。林。符合。传感器应指示 Y 轴上的运动,而转换后的矢量 - 在 Z 轴上。但我得到了vector V 和vector A。所以..?

以上是关于从设备坐标系到绝对坐标系的加速度的主要内容,如果未能解决你的问题,请参考以下文章

ug8.0为啥我把坐标移动时之前那个图也跟着坐标移动的

UG10.0怎么把坐标系移动到自己想要的位置

OSG坐标系统

UG导入其他软件三维时,客户建模坐标系(左下绝对坐标系)与自己想要出工程图的坐标不一致

裁剪坐标系和标准化设备坐标系(OpenGL)中的裁剪

坐标变换,空间变换的本质