ARCore 中文文档 下载 App

三种 Geospatial Anchor 类型详解

Geospatial Anchor 的坐标体系

普通 ARCore Anchor 用的是会话内本地坐标系(Session World Coordinates)——原点在 Session 启动时的手机位置,单位是米。

Geospatial Anchor 用的是全球坐标系(WGS84,World Geodetic System 1984)——也就是 GPS 使用的经纬度和海拔高度。单位是:

维度单位范围
纬度(Latitude)度-90 ~ +90(南 ~ 北)
经度(Longitude)度-180 ~ +180(西 ~ 东)
海拔(Altitude)米相对 WGS84 椭球表面

不同类型的 Geospatial Anchor 对"垂直位置"的定义不同——这就是三种 Anchor 的区别所在。

类型一:WGS84 Anchor

最常用的类型。海拔直接用 WGS84 椭球参考高度(不是海平面高度,也不是地面高度)。

// 创建 WGS84 Anchor
val earth = arSession.earth
earth.createAnchor(
    latitude = 37.7749,    // 旧金山纬度
    longitude = -122.4194, // 旧金山经度
    altitude = 50.0,        // WGS84 椭球以上 50 米
    eastUpSouthQTarget = GeospatialAnchorQuatTarget.EQUATORIAL_NORTH
)

特点

注意事项:海拔的参考系

WGS84 海拔不是海平面海拔,而是相对于一个椭球(WGS84 椭球)的高度。这个椭球是对地球形状的数学近似,不同地区和真正的海平面/地面之间可能有几十米的差异。这意味着:

用 WGS84 Anchor 放置 AR 内容时,海拔值可能需要根据具体区域做校正——否则 AR 内容可能悬浮在空中或埋入地下。

类型二:Terrain Anchor

最适合大多数场景的类型。海拔相对于当地地形表面(地面或地板),而不是 WGS84 椭球。

// 创建 Terrain Anchor
earth.createAnchor(
    latitude = 37.7749,
    longitude = -122.4194,
    altitudeAboveTerrain = 1.5,  // 地面以上 1.5 米(人的视线高度)
    eastUpSouthQTarget = ...
)

特点

为什么首选 Terrain Anchor

WGS84 Anchor 的海拔定义不直观——开发者需要知道某个位置的 WGS84 椭球海拔才能让 AR 内容刚好放在地面上。Terrain Anchor 直接用"地面以上 X 米"这个人人都懂的概念。

绝大多数场景应该用 Terrain Anchor。

类型三:Rooftop Anchor

专门用于建筑物屋顶的 Anchor 类型。海拔相对于目标建筑的屋顶表面。

// 创建 Rooftop Anchor
earth.createAnchor(
    latitude = 37.7749,
    longitude = -122.4194,
    altitudeAboveRoof = 3.0,  // 屋顶以上 3 米
    eastUpSouthQTarget = ...
)

特点

Rooftop Anchor 的限制

不是所有建筑都有 Rooftop 数据。如果你在一个没有 Rooftop 数据的位置创建 Rooftop Anchor,ARCore 会返回一个无效的 Anchor(Anchor.trackingState == STOPPED 或 Anchor.pose 不更新)。

三种 Anchor 对比

对比项WGS84TerrainRooftop
海拔参考系WGS84 椭球地形表面建筑屋顶
开发难度高(需查椭球海拔)低(直接地面以上)中(需有 Rooftop 数据)
海拔精度中(受椭球差异影响)好中
覆盖范围全球(有街景)全球(有 Elevation 数据)仅大/中城市主要建筑
推荐使用开发者有精确 WGS84 坐标绝大多数室外场景屋顶相关场景

朝向(Orientation):eastUpSouthQTarget

三种 Geospatial Anchor 都需要一个朝向参数——决定虚拟物体在水平面上的方向(南北朝向):

// 几种常用朝向
GeospatialAnchorQuatTarget.EQUATORIAL_NORTH  // 朝北(物体正面朝向正北)
GeospatialAnchorQuatTarget.EQUATORIAL_SOUTH  // 朝南
GeospatialAnchorQuatTarget.EQUATORIAL_EAST    // 朝东
GeospatialAnchorQuatTarget.EQUATORIAL_WEST    // 朝西

自定义朝向:

// 用一个四元数指定朝向
// 从地理北偏东 45 度
val rotation = Quaternion.fromAxisAngle(Vector3.Up(), Math.toRadians(45.0))
val target = GeospatialAnchorQuatTarget(rotation)

在 Unity 中创建 Geospatial Anchor

var anchorManager = GetComponent<ARAnchorManager>();

// Terrain Anchor 示例
var pose = EarthApi.CreateAnchor(
    latitude: 37.7749,
    longitude: -122.4194,
    altitudeAboveTerrain: 1.5f,
    orientation: Quaternion.identity  // 朝北
);

var anchor = anchorManager.AddAnchor(pose);
// anchor 就是普通的 ARAnchor,可以像其他 Anchor 一样用

验证 Anchor 的实际位置

创建 Geospatial Anchor 后,ARCore 会异步地计算精确位置。你需要等到 Anchor 的 TrackingState 变成 TRACKING 且 Transform 稳定后再使用它:

// 在每帧检查
if (geospatialAnchor.trackingState == TrackingState.TRACKING) {
    // Anchor 位置已精确,可以放置虚拟物体了
    placeContentAtAnchor(geospatialAnchor)
}

初始时 Anchor 可能会有几秒的位置抖动——这是 VPS 正在迭代求精,属于正常行为。