DeviceMotion相对于world - multiplyByInverseOfAttitude [英] DeviceMotion relative to world - multiplyByInverseOfAttitude

查看:122
本文介绍了DeviceMotion相对于world - multiplyByInverseOfAttitude的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  CMMotionManager * motionManager = [[CMMotionManager alloc] init]; 
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:
CMAttitudeReferenceFrameXTrueNorthZVertical];

稍后,获取CMDeviceMotion对象:

  CMDeviceMotion * deviceMotion = [motionManager deviceMotion]; 

我希望[deviceMotion attitude]反映设备从True North的旋转。



通过观察,[deviceMotion userAcceleration]报告设备参考框架中的加速度。也就是说,将设备左右移动(保持平放在桌面上)可以记录x轴上的加速度。将设备旋转90°(仍然是平坦的)并将设备左右移动仍然会报告x加速度。



将[deviceMotion userAcceleration]转换为获取North的正确方法是什么 - 南/东西加速而不是左右/前后?



CMAttitude multiplyByInverseOfAttitude似乎没必要,因为已经指定了一个参考系,并且不清楚记录如何将态度应用于CMAcceleration。

解决方案

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



在CMDeviceMotion + TransformToReferenceFrame.h中:

  #import< CoreMotion / CoreMotion.h> 

@interface CMDeviceMotion(TransformToReferenceFrame)
- (CMAcceleration)userAccelerationInReferenceFrame;
@end

以及CMDeviceMotion + TransformToReferenceFrame.m:

  #importCMDeviceMotion + TransformToReferenceFrame.h

@implementation CMDeviceMotion(TransformToReferenceFrame)

- ( - CMAcceleration)userAccelerationInReferenceFrame
{
CMAcceleration acc = [self userAcceleration];
CMRotationMatrix rot = [self attitude] .rotationMatrix;

CMAcceleration accRef;
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;

返回accRef;
}

@end

和Swift 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;

返回accRef;
}
}

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


What is the correct way to use CMAttitude:multiplyByInverseOfAttitude?

Assuming an iOS5 device laying flat on a table, after starting CMMotionManager with:

CMMotionManager *motionManager = [[CMMotionManager alloc]init];
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:
    CMAttitudeReferenceFrameXTrueNorthZVertical];

Later, CMDeviceMotion objects are obtained:

CMDeviceMotion *deviceMotion = [motionManager deviceMotion];

I expect that [deviceMotion attitude] reflects the rotation of the device from True North.

By observation, [deviceMotion userAcceleration] reports acceleration in the device reference frame. That is, moving the device side to side (keeping it flat on the table) registers acceleration in the x-axis. Turning the device 90° (still flat) and moving the device side to side still reports x acceleration.

What is the correct way to transform [deviceMotion userAcceleration] to obtain North-South/East-West acceleration rather than left-right/forward-backward?

CMAttitude multiplyByInverseOfAttitude seems unnecessary since a reference frame has already been specified and it is unclear from the documentation how to apply the attitude to CMAcceleration.

解决方案

The question would not have arisen if CMDeviceMotion had an accessor for the userAcceleration in coordinates of the reference frame. So, I used a category to add the required method:

In CMDeviceMotion+TransformToReferenceFrame.h:

#import <CoreMotion/CoreMotion.h>

@interface CMDeviceMotion (TransformToReferenceFrame)
-(CMAcceleration)userAccelerationInReferenceFrame;
@end

and in CMDeviceMotion+TransformToReferenceFrame.m:

#import "CMDeviceMotion+TransformToReferenceFrame.h"

@implementation CMDeviceMotion (TransformToReferenceFrame)

-(CMAcceleration)userAccelerationInReferenceFrame
{
    CMAcceleration acc = [self userAcceleration];
    CMRotationMatrix rot = [self attitude].rotationMatrix;

    CMAcceleration accRef;
    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;
}

@end

and in Swift 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;
    }
}

Now, code that previously used [deviceMotion userAcceleration] can use [deviceMotion userAccelerationInReferenceFrame] instead.

这篇关于DeviceMotion相对于world - multiplyByInverseOfAttitude的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆