iPhone AR ToolKit背后的数学

时间:2011-10-06 10:23:40

标签: iphone augmented-reality iphone-ar-toolkit

我正在使用iPhone ARToolkit,我想知道它是如何工作的。

我想知道如何使用目的地位置,用户位置和指南针,此工具包可以知道用户正在寻找该目的地。

我怎么知道这个计算背后的数学?

2 个答案:

答案 0 :(得分:7)

AR ToolKit使用的数学是基本的三角学。它没有使用托马斯描述的技术,我认为这是一种更好的方法(除了第5步。见下文)

所涉步骤概述。

iPhone的GPS提供设备的位置,您已经拥有了想要查看的位置的坐标。

首先,它计算两点的纬度和经度值之间的差值。这两个差异测量意味着您可以构建一个直角三角形并计算另一个给定位置与当前位置的角度。这是相关的代码:

- (float)angleFromCoordinate:(CLLocationCoordinate2D)first toCoordinate:(CLLocationCoordinate2D)second {
    float longitudinalDifference = second.longitude - first.longitude;
    float latitudinalDifference = second.latitude - first.latitude;
    float possibleAzimuth = (M_PI * .5f) - atan(latitudinalDifference / longitudinalDifference);
    if (longitudinalDifference > 0) return possibleAzimuth;
    else if (longitudinalDifference < 0) return possibleAzimuth + M_PI;
    else if (latitudinalDifference < 0) return M_PI;

    return 0.0f;
}

此时,您可以从手机中读取罗盘值,并确定设备指向的特定罗盘角度(方位角)。从罗盘读取的角度将直接在摄像机视图的中心。然后,AR ToolKit计算当前显示在屏幕上的整个角度范围,因为iPhone的视野为known

特别是它通过计算视图最左边部分的角度来显示:

double leftAzimuth = centerAzimuth - VIEWPORT_WIDTH_RADIANS / 2.0;

if (leftAzimuth < 0.0) {
    leftAzimuth = 2 * M_PI + leftAzimuth;
}

然后计算最合适的:

double rightAzimuth = centerAzimuth + VIEWPORT_WIDTH_RADIANS / 2.0;

if (rightAzimuth > 2 * M_PI) {
    rightAzimuth = rightAzimuth - 2 * M_PI;
}

我们现在有:

  1. 相对于我们想要显示的内容的当前位置的角度
  2. 屏幕上当前可见的一系列角度
  3. 这足以将屏幕上的标记绘制在正确的位置(有点......见下面的问题部分)

    它也做了与设备倾向相关的类似计算,所以如果你看天空,你希望看不到那里的城市标记,如果你指向你的脚,你理论上应该看到对面的城市星球。但是,在这个工具包中存在这些计算的问题。

    问题......

    设备定位不完善

    我刚刚解释的计算值假设您将设备保持在相对于地球的精确位置。即完美的风景或肖像。您的用户可能不会一直这样做。如果您稍微倾斜设备,您的水平线将不再在屏幕上水平。

    地球实际上是3D!

    地球是三维的。工具包中很少有计算可以解释这一点。当您将设备指向地平线时,它执行的计算才真正准确。

    例如,如果您尝试在地球的另一侧(直接在脚下)绘制一个点,则此工具包的行为非常奇怪。用于计算屏幕方位角范围的方法仅在查看地平线时有效。如果您将相机对准地板,您实际上可以看到每个指南针点。但是,该工具包认为您仍然只关注compass reading ± (width of view / 2)。如果您在现场旋转,您将看到标记移动到屏幕边缘,消失然后再次出现在另一侧。您希望看到的是旋转时标记停留在屏幕上。

    解决方案

    我最近使用AR实现了一个应用程序,我最初希望AR Toolkit可以为我做繁重的工作。我遇到了刚刚描述的问题,这些问题对我的应用程序来说是不可接受的,所以不得不自己滚动。

    托马斯的方法是一个很好的方法,直到第5点,正如我上面所解释的那样,只有在指向地平线时才有效。如果你需要绘制除此之外的任何东西,它就会崩溃。在我的情况下,我必须绘制开销的对象,因此它完全不适合。

    我通过使用OpenGL ES在3D空间中绘制我的标记来实现这一点,并根据陀螺仪的读数移动OpenGL视口,同时不断地重新校准指南针。 3D引擎处理决定屏幕内容的所有艰苦工作。

    希望这足以让你开始。我希望我能提供更多细节而不是发布很多的hacky代码我不能。然而,这种方法确实解决了上述两个问题。我希望在某些时候开源我的代码部分,但它非常粗糙,并且目前与我的问题域相关联。

答案 1 :(得分:3)

  • 这是所需的全部信息。通过iphone-location和destination-location,您可以计算目标角度(相对于真北)。
  • 唯一缺少的是知道iPhone当前正在查看罗盘返回的位置(磁北+当前位置 - &gt;真北)。

编辑:计算:(这只是一个想法:如果没有很多坐标转换,可能会有更好的解决方案)

  1. convert当前和目的地位置ecef-coordinates
  2. transform目的地ecef坐标到enu(东,北,上)本地坐标系,当前位置为参考位置。您也可以使用this
  3. 忽略高度值并使用enu坐标获取方向:atan2(deast, dnorth)
  4. 指南针已经返回angle the iPhone is looking at
  5. 如果是dest_angle - 10° <= compass_angle <= dest_angle + 10°
    ,则在屏幕上显示目的地 关于循环角度空间。常量10°只是一个猜测值。你应该尝试一些值来找出一个有用的值,或者你必须分析iPhone相机的一些属性。
  6. 如果假设地球是球体而不是椭圆体,则坐标变换方程变得更加简单。大多数链接如果有postet假设一个wgs-84椭球,因为gps也做afaik)。