iOS - 计算距离、方位角、俯仰角和相对位置(增强现实)

9
我正在开发一个增强现实应用程序,您可以在增强现实相机视图上放置图像,并将其保留在地球上的该位置上,因此其他人使用他们的相机视图可以看到它。为此,我知道我需要计算某种距离因素以及方位角和俯仰角。
因此,我已经找出了如何将对象图形发送到服务器并检索回来,但是我该如何将其放回原始位置,相对于地球呢?我知道我需要计算它的:
- 海拔高度 - 坐标 - 方位角 - 俯仰角 - 距离
但是我应该如何计算它们,以及如何考虑它们/组合它们。希望您理解我的意思。
为了更好地理解,请让我给您演示一下应用程序:
一个男人在家里,他决定在其中一面墙上放置一幅画的图像。他打开应用程序,该应用程序默认为增强现实屏幕,然后按下加号按钮并从他的照片库中添加一个图像。在幕后,它将位置和位置数据保存到服务器,使用该应用程序及其增强现实屏幕的某个人经过时,它会上载到服务器并查找附近保存的图像,然后下载该图像并将其放置在墙上,以便其他人可以用手机看到它。
为了实现这一点,我应该采取什么方法?有任何概述、链接、资源、教程、想法、经验等。谢谢!这是一个相对困难的问题,我希望您能理解。如果不能,请告诉我,我会重新措辞。
罗翰

它实际上是基于您当前位置和目标位置计算投影。您可以在此处了解一些想法:https://github.com/abm-adnan/Radar/blob/master/Radar/Controllers/RadarViewController.m#L104 - Adnan
@MCKapur 你是如何获取图像的位置数据并将其发送到服务器的?就像我知道图像的初始位置,如果用户将图像拖动到AR屏幕视图中的新位置,现在如何识别图像的新经纬度? - rootcoder
2个回答

19
我正在开发两款AR iOS应用程序,可以将方位角(指南针、水平角度)和俯仰角(陀螺仪、垂直角度)转换为三维空间中的位置(例如,从球面坐标系到笛卡尔坐标系)。
你需要使用以下框架:
- CoreLocation - CoreMotion
获取地理位置(坐标)对于纬度、经度和海拔高度来说非常简单。你可以在几个在线资源中轻松找到这些信息,但这是你从 `CLLocationManagerDelegate`调用了 `startUpdatingLocation` 后需要的主要调用:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    latitude = (float) manager.location.coordinate.latitude;
    longitude = (float) manager.location.coordinate.longitude;
    altitude = (float) manager.location.altitude;
}

获取方位角也非常简单,只需在调用 startUpdatingHeading 后使用与位置相同的委托即可:

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
    azimuth  = (float) manager.heading.magneticHeading;
}

高度数据是从陀螺仪中提取的,它没有代理,但也很容易设置。调用看起来像这样(注意:这适用于我在横屏模式下运行的应用程序,请检查您的应用程序):

elevation = fabsf(self.motionManager.deviceMotion.attitude.roll);

最后,您可以像这样将定位坐标转换为3D点:

- (GLKVector3)sphericalToCartesian:(float)radius azimuth:(float)theta elevation:(float)phi
{
    // Convert Coordinates: Spherical to Cartesian
    // Spherical: Radial Distance (r), Azimuth (θ), Elevation (φ)
    // Cartesian: x, y, z

    float x = radius * sinf(phi) * sinf(theta);
    float y = radius * cosf(phi);
    float z = radius * sinf(phi) * cosf(theta);
    return GLKVector3Make(x, y, z);
}

在最后一部分,要非常小心角度和轴线的命名惯例,因为它们因来源而异。在我的系统中,θ是水平面上的角度,φ是垂直面上的角度,x是左右,y是上下,z是前后。

至于距离,我不确定你是否真的需要使用它,但如果需要,只需将其替换为“半径”。

希望这有所帮助。


2
谢谢,非常有价值的回答。我会更深入地研究并与您联系。我可能需要距离,这样当您离得更远时,我可以缩小图像。但是,你说的用"半径"替代它是什么意思?那样行吗?如果可能的话,您是否可以指向一个使用了这个类似代码的资源,这样我就可以看到它实际上是如何使用的? - MCKapur
1
我正在使用半径来驱动一个定向光围绕一个3D对象旋转,所以根据您提供的新信息,我认为半径对您来说是无关紧要的。从我的理解来看,您正在寻找的距离将被计算为地球上两个点之间的差异,是吗?(如果是这样,我就无能为力了!)此外,AR相对于应用程序来说还比较新,因此您很难找到有用的信息,但我在我的MSc论文和一款目前正在被Apple审核的后续应用程序中实现了这种技术。这两个项目都是在过去6个月内开发的,我一直在努力寻找相关的代码示例! - Ricardo RendonCepeda
2
什么是定向光?我知道这与我无关,但只是问一下(听起来很酷)...所以我有我的3D点,如何获取我的3D点并在区域/位置上绘制图像?我检索坐标、高度角、方位角和俯仰角,然后如何将其绘制回去?另一件事是,图像可能是屏幕中心的小图像。那么我如何将图像绘制回地球上的位置,同时也相对于屏幕的位置?还有一个问题,这些计算会非常准确吗?如果我将其绘制回去,它会给出准确的位置吗? - MCKapur
1
另外,我如何将GLKVector3转换为NSData对象?这可能吗? - MCKapur
2
一个定向光是一种常见的3D CG对象,它紧密地模拟了直射阳光 - 它是无限远并且仅发射平行光线。听起来你还有很多设计工作要做,所以除非我开始查看你实现和最终目标的细节,否则很难给出更多建议。从个人经验来看,相对于屏幕的位置是最棘手的,这将大大取决于您如何定义比例尺和距离(例如,用户何时足够“接近”?)。数学就是数学,任何不准确之处都在于传感器 :) - Ricardo RendonCepeda
显示剩余10条评论

1

Swift 3

陀螺仪代码更新:

import CoreMotion
...
        motionManager.deviceMotionUpdateInterval = 0.1
        motionManager.startDeviceMotionUpdates(to: OperationQueue.current!) { deviceManager, error in
            guard let dm = deviceManager else { return }
            let roll = dm.attitude.roll
            let pitch = dm.attitude.pitch
            let yaw = dm.attitude.yaw

            print("r: \(roll), p: \(pitch), y: \(yaw)")
        }

仰角如何? - user924

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接