Ios 相对于世界的设备运动-倍数与振幅

Ios 相对于世界的设备运动-倍数与振幅,ios,core-motion,Ios,Core Motion,使用Cmatitude的正确方法是什么:multiplyByInverseOfAttitude 假设iOS5设备平放在桌子上,在启动CMMotionManager后: CMMotionManager *motionManager = [[CMMotionManager alloc]init]; [motionManager startDeviceMotionUpdatesUsingReferenceFrame: CMAttitudeReferenceFrameXTrueNorthZVer

使用Cmatitude的正确方法是什么:multiplyByInverseOfAttitude

假设iOS5设备平放在桌子上,在启动CMMotionManager后:

CMMotionManager *motionManager = [[CMMotionManager alloc]init];
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:
    CMAttitudeReferenceFrameXTrueNorthZVertical];
稍后,将获取CMDeviceMotion对象:

CMDeviceMotion *deviceMotion = [motionManager deviceMotion];
我希望[设备运动姿态]反映设备从正北方向的旋转

通过观察,[deviceMotion userAcceleration]报告设备参考框架中的加速度。也就是说,将设备左右移动(使其平放在工作台上)会记录x轴上的加速度。将设备旋转90°(仍为平面)并将设备左右移动,仍报告x加速度

转换[deviceMotion userAcceleration]以获得南北/东西加速而不是左右/前后加速的正确方法是什么


Cmatitude multiplyByVerseOfattude似乎是不必要的,因为已经指定了一个参考坐标系,并且文档中不清楚如何将姿态应用于Cmax加速度。

参考坐标系与姿态值相关,请查看偏航角的姿态值;如果不使用参考帧,则在启动应用程序时,该值始终为零,而如果使用参考帧CmatitureReferenceFramextrueNorthzVertical,则偏航值指示x轴与正北之间的角度。
通过这些信息,您可以确定手机在地球坐标系中的姿态,从而确定加速度计轴相对于基点的位置。

在阅读了上面链接的文章后,我尝试实施一个解决方案

步骤如下:

  • 每次更新时获取姿态旋转矩阵
  • 计算逆矩阵
  • 乘以用户加速度向量的逆矩阵
结果向量将是向量的投影

-x北+x南

-y东,+y西


我的代码还不完善,我正在研究它。

如果CMDeviceMotion在参考坐标系的坐标中有一个userAcceleration的访问器,这个问题就不会出现。因此,我使用了一个类别来添加所需的方法:

在CMDeviceMotion+TransformToReferenceName.h中:

#import <CoreMotion/CoreMotion.h>

@interface CMDeviceMotion (TransformToReferenceFrame)
-(CMAcceleration)userAccelerationInReferenceFrame;
@end
在斯威夫特3

extension CMDeviceMotion {

    var userAccelerationInReferenceFrame: CMAcceleration {
        let acc = self.userAcceleration
        let rot = self.attitude.rotationMatrix

        var accRef = CMAcceleration()
        accRef.x = acc.x*rot.m11 + acc.y*rot.m12 + acc.z*rot.m13;
        accRef.y = acc.x*rot.m21 + acc.y*rot.m22 + acc.z*rot.m23;
        accRef.z = acc.x*rot.m31 + acc.y*rot.m32 + acc.z*rot.m33;

        return accRef;
    }
}

现在,以前使用[deviceMotion userAcceleration]的代码可以改为使用[deviceMotion UserAccelerationReferenceFrame]。

根据苹果的文档,
Cmatitude
指的是身体相对于给定参考框架的方向。
userAcceleration
gravity
是设备帧的值。所以为了得到参考系的值。我们应该照@Batti说的做

  • 每次更新时获取姿态旋转矩阵
  • 计算逆矩阵
  • 乘以用户加速度向量的逆矩阵
  • 这是Swift版本

    import CoreMotion
    import GLKit
    
    extension CMDeviceMotion {
    
        func userAccelerationInReferenceFrame() -> CMAcceleration {
    
            let origin = userAcceleration
            let rotation = attitude.rotationMatrix
            let matrix = rotation.inverse()
    
            var result = CMAcceleration()
            result.x = origin.x * matrix.m11 + origin.y * matrix.m12 + origin.z * matrix.m13;
            result.y = origin.x * matrix.m21 + origin.y * matrix.m22 + origin.z * matrix.m23;
            result.z = origin.x * matrix.m31 + origin.y * matrix.m32 + origin.z * matrix.m33;
    
            return result
        }
    
        func gravityInReferenceFrame() -> CMAcceleration {
    
            let origin = self.gravity
            let rotation = attitude.rotationMatrix
            let matrix = rotation.inverse()
    
            var result = CMAcceleration()
            result.x = origin.x * matrix.m11 + origin.y * matrix.m12 + origin.z * matrix.m13;
            result.y = origin.x * matrix.m21 + origin.y * matrix.m22 + origin.z * matrix.m23;
            result.z = origin.x * matrix.m31 + origin.y * matrix.m32 + origin.z * matrix.m33;
    
            return result
        }
    }
    
    extension CMRotationMatrix {
    
        func inverse() -> CMRotationMatrix {
    
            let matrix = GLKMatrix3Make(Float(m11), Float(m12), Float(m13), Float(m21), Float(m22), Float(m23), Float(m31), Float(m32), Float(m33))
            let invert = GLKMatrix3Invert(matrix, nil)
    
            return CMRotationMatrix(m11: Double(invert.m00), m12: Double(invert.m01), m13: Double(invert.m02),
                                m21: Double(invert.m10), m22: Double(invert.m11), m23: Double(invert.m12),
                                m31: Double(invert.m20), m32: Double(invert.m21), m33: Double(invert.m22))
    
        }
    
    }
    

    希望对你有所帮助

    谢谢@batti,我理解几何,问题是关于编码。API似乎不支持应用转换的简单方法。在Cmatitude中,euler角、四元数表示和旋转矩阵都很容易访问,但没有明显的方法将它们应用于Cmatitude加速度。更糟糕的是,CMAcceleration是只读的,所以我不能自己转换它并在发送之前更新对象。问题是加速度计的le轴与设备固定,因此加速度计可以在设备框架中测量加速度。如果传感器没有那么嘈杂,你应该找到加速度的水平面,垂直于重力矢量的平面,看看这个平面上的矢量,计算矢量和北方之间的角度,知道基数坐标系中加速度的方向。你的应用程序是做什么的?这应该是有帮助的,第3节。这是一个有趣的,很好的工作。我假设您正在将其与指南针(CLHeading)一起使用。你怎么处理从加速中得到的数字?你的答案不正确。为了将矢量从参考帧a移动到参考帧B,当给出从B到a的旋转矩阵时,该矢量应乘以逆旋转矩阵。下面是如何计算Vitaly的逆矩阵,感谢您的反馈。守则运作良好,运作良好;你试过了吗?您的链接提供了一种反转任意矩阵的方法,但“旋转矩阵的逆矩阵只是其转置”()。这很微妙,但代码在计算中转换了旋转矩阵。@Zaq,我收回我的话,你说得对。看一下我的旋转矩阵求逆代码,这是一个任意矩阵求逆代码,它产生了转置矩阵。显然,旋转矩阵逆是它的转置,因为有两个事实:a)行列式总是1,因为旋转时向量不缩放;b)旋转矩阵是正交矩阵。@xmkevinchen,谢谢你的兴趣。代码完全按照您的建议执行。正如VitalyStakhov逐渐意识到的那样,代码在计算中转换了旋转矩阵。我可以对俯仰和滚动也这么做吗>?你能分享代码吗?或者解释上述步骤。。我得到的只是存储你想要创建的姿态作为参考,计算当前姿态的倒数
    import CoreMotion
    import GLKit
    
    extension CMDeviceMotion {
    
        func userAccelerationInReferenceFrame() -> CMAcceleration {
    
            let origin = userAcceleration
            let rotation = attitude.rotationMatrix
            let matrix = rotation.inverse()
    
            var result = CMAcceleration()
            result.x = origin.x * matrix.m11 + origin.y * matrix.m12 + origin.z * matrix.m13;
            result.y = origin.x * matrix.m21 + origin.y * matrix.m22 + origin.z * matrix.m23;
            result.z = origin.x * matrix.m31 + origin.y * matrix.m32 + origin.z * matrix.m33;
    
            return result
        }
    
        func gravityInReferenceFrame() -> CMAcceleration {
    
            let origin = self.gravity
            let rotation = attitude.rotationMatrix
            let matrix = rotation.inverse()
    
            var result = CMAcceleration()
            result.x = origin.x * matrix.m11 + origin.y * matrix.m12 + origin.z * matrix.m13;
            result.y = origin.x * matrix.m21 + origin.y * matrix.m22 + origin.z * matrix.m23;
            result.z = origin.x * matrix.m31 + origin.y * matrix.m32 + origin.z * matrix.m33;
    
            return result
        }
    }
    
    extension CMRotationMatrix {
    
        func inverse() -> CMRotationMatrix {
    
            let matrix = GLKMatrix3Make(Float(m11), Float(m12), Float(m13), Float(m21), Float(m22), Float(m23), Float(m31), Float(m32), Float(m33))
            let invert = GLKMatrix3Invert(matrix, nil)
    
            return CMRotationMatrix(m11: Double(invert.m00), m12: Double(invert.m01), m13: Double(invert.m02),
                                m21: Double(invert.m10), m22: Double(invert.m11), m23: Double(invert.m12),
                                m31: Double(invert.m20), m32: Double(invert.m21), m33: Double(invert.m22))
    
        }
    
    }