基于后置摄像头的 CoreLocation 航向(增强现实) [英] CoreLocation heading base on back camera (Augmented reality)

查看:28
本文介绍了基于后置摄像头的 CoreLocation 航向(增强现实)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个增强现实视图,将对象指向一个方向.但是,当您用相机朝上时(例如,当您在一楼时朝向 20 层建筑的顶部),CoreLocation 标题无法正常工作.

I would like to create an augmented reality view that is going to point an object in a direction. However, the CoreLocation heading is not working correctly when you are facing upwards with your camera (say to a top of a 20-storeys building when you are on the ground floor).

它给出了相反的方向(可能是手机顶部指向的方向).

It is giving the opposite direction (probably the direction that is pointing by the top of the phone).

我尝试了一些方法来让它在相机指向的方向上工作,例如:

I have tried a few methods to get it to work for the direction the camera is pointing, such as:

1、+180度,当设备方向>45度时(不够准确,方向突然偏离10~20度)

1, +180 degree when the device orientation is > 45 degree (not accurate enough, suddenly the direction goes off by 10~20 degree)

2,尝试使用 CMMotionManager 和以下教程中的公式进行计算.http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensed-compass-arduino-tutorial.

2, attempted to calculate using CMMotionManager with formula from the below tutorial. http://www.loveelectronics.co.uk/Tutorials/13/tilt-compensated-compass-arduino-tutorial.

3、尝试使用ios deviceMotion.magneticField和deviceMotion.gravity从android模拟逻辑.

3, attempted to simulate logic from android using ios deviceMotion.magneticField and deviceMotion.gravity.

4、使用旋转矩阵(堆栈溢出中的其他一些帖子,但不准确)

4, use rotation matrix (some other post in stack overflow, but not accurate)

    double heading = M_PI + atan2(self.altitudeData.rotationMatrix.m22, self.altitudeData.rotationMatrix.m12);
    heading = heading*180/M_PI;

我不知道还有什么办法可以使它正确.我知道有一些应用程序(一些可以看到太阳和星星的应用程序)可以正确执行.

I am running out of idea what else could I try to get it right. I know there are some apps out there (some app that can see the sun and star) that is doing it correctly.

推荐答案

经过大量研究和测试.我最终使用 GLKit 进行计算,因为它也为我省去了很多麻烦.把它留在这里给任何碰巧遇到这个问题的人.

After much of research and testing. I ended up using GLKit for the calculation, as it saves me lots of trouble as well. Just leave it here for anyone who happen to get to this question.

首先,我使用 CMAttitudeReferenceFrameXTrueNorthZVertical 启动 CMMotionManager 设备运动更新.

First, I started the CMMotionManager device motion updates with CMAttitudeReferenceFrameXTrueNorthZVertical.

self.hasMotion = NO;
CMMotionManager *cmmotionManager = [[CMMotionManager alloc] init];
[cmmotionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical
                                                     toQueue:[[NSOperationQueue alloc] init]
                                                 withHandler:^ (CMDeviceMotion *motion, NSError *error) {
                                                     self.hasMotion = YES;


                                                 }];
self.motionManager = cmmotionManager;

从我在网上找到的一些代码中,使用 CoreMotion 旋转绘制 openGL 世界并将其与从屏幕到 3D 世界的点混合:

From some codes that I found on the web to draw an openGL world using CoreMotion rotation and mix it with getting a point from screen to 3D world:

float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), aspect, 0.1f, 100.0f);

CMRotationMatrix r = self.motionManager.deviceMotion.attitude.rotationMatrix;
GLKMatrix4 camFromIMU = GLKMatrix4Make(r.m11, r.m12, r.m13, 0,
                                       r.m21, r.m22, r.m23, 0,
                                       r.m31, r.m32, r.m33, 0,
                                       0,     0,     0,     1);

GLKMatrix4 viewFromCam = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, 0);
GLKMatrix4 imuFromModel = GLKMatrix4Identity;
GLKMatrix4 viewModel = GLKMatrix4Multiply(imuFromModel, GLKMatrix4Multiply(camFromIMU, viewFromCam));
bool isInvertible;
GLKMatrix4 modelView = GLKMatrix4Invert(viewModel, &isInvertible);

int viewport[4];
viewport[0] = 0.0f;
viewport[1] = 0.0f;
viewport[2] = self.view.frame.size.width;
viewport[3] = self.view.frame.size.height;

bool success;
//assume center of the view
GLKVector3 vector3 = GLKVector3Make(self.view.frame.size.width/2, self.view.frame.size.height/2, 1.0);     
GLKVector3 calculatedPoint = GLKMathUnproject(vector3, modelView, projectionMatrix, viewport, &success);
if(success)
{
    //CMAttitudeReferenceFrameXTrueNorthZVertical always point x to true north
    //with that, -y become east in 3D world
    float angleInRadian = atan2f(-calculatedPoint.y, calculatedPoint.x);
    return angleInRadian;
}

这篇关于基于后置摄像头的 CoreLocation 航向(增强现实)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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