Geospatiale Anchors verwenden, um reale Inhalte im Android SDK (Kotlin/Java) zu positionieren

Raumbezogene Anker sind eine Art Anker, mit dem Sie 3D-Inhalte in der realen Welt platzieren können.

Arten von raumbezogenen Ankern

Es gibt drei Arten von geografischen Markierungen, die die Höhe unterschiedlich handhaben:

  1. WGS84-Anker:
    Mit WGS84-Ankern können Sie 3D-Inhalte auf einem beliebigen Breiten-, Längengrad und in der Höhe platzieren.

  2. Terrain-Markierungen:
    Mithilfe von Terrain-Markierungen können Sie Inhalte nur mithilfe von Breiten- und Längengrad sowie einer Höhe relativ zum Gelände an dieser Position platzieren. Die Höhe wird relativ zum Boden oder zur Etage bestimmt, wie sie VPS bekannt ist.

  3. Dachdübel:
    Mit Dachankern können Sie Inhalte nur anhand des Breiten- und Längengrads platzieren, wobei die Höhe an dieser Position relativ zum Dach eines Gebäudes relativ zum jeweiligen Gebäude ist. Die Höhe wird relativ zum Dach eines Gebäudes bestimmt, wie es aus der Straßenraumgeometrie hervorgeht. Wird diese Option nicht auf einem Gebäude platziert, wird standardmäßig die Geländehöhe verwendet.

WGS84 Gelände Dach
Horizontale Position Breitengrad, Längengrad Breitengrad, Längengrad Breitengrad, Längengrad
Vertikale Position Relativ zur WGS84-Höhe Relativ zur von Google Maps bestimmten Geländehöhe Relativ zur Dachhöhe (von Google Maps festgelegt)
Muss serverseitig aufgelöst werden? Nein Ja Ja

Voraussetzungen

Aktivieren Sie die Geospatial API, bevor Sie fortfahren.

Georeferenzierte Markierungen platzieren

Für jeden Ankertyp gibt es spezielle APIs, mit denen er erstellt werden kann. Weitere Informationen finden Sie unter Arten von geografischen Markierungen.

Anker aus einem Treffertest erstellen

Sie können einen raumbezogenen Anker auch aus einem Treffertestergebnis erstellen. Verwenden Sie die Pose aus dem Treffertest und wandeln Sie sie in eine GeospatialPose um. Damit können Sie einen der drei beschriebenen Ankertypen platzieren.

Raumbezogene Pose aus AR-Positionen erstellen

Earth.getGeospatialPose() bietet eine weitere Möglichkeit, Breiten- und Längengrad zu bestimmen, indem eine AR-Position in eine raumbezogene Pose umgewandelt wird.

Eine AR-Stellung aus einer raumbezogenen Pose erstellen

Earth.getPose() wandelt eine von der Erde angegebene horizontale Position, Höhe und Quaternionsdrehung bezogen auf einen Koordinatenrahmen (Osten-Oben-Süd) in eine AR-Pose bezogen auf die GL-Weltkoordinate um.

Wählen Sie die Methode aus, die für Ihren Anwendungsfall am besten geeignet ist.

Jede Methode zum Erstellen eines Ankers hat Vor- und Nachteile, die Sie berücksichtigen sollten:

  • Wenn Sie Streetscape-Geometrie verwenden, können Sie Inhalte mithilfe eines Treffertests an ein Gebäude anhängen.
  • Sie sollten Gelände- oder Dachanker gegenüber WGS84-Ankern vorziehen, da sie von Google Maps festgelegte Höhenwerte verwenden.

Breiten- und Längengrad eines Standorts ermitteln

Es gibt drei Möglichkeiten, den Breiten- und Längengrad eines Standorts zu berechnen:

  • Mit dem Geospatial Creator kannst du die Welt mit 3D-Inhalten erweitern, ohne dich persönlich aufsuchen zu müssen. So können Sie im Unity-Editor visuelle 3D-Inhalte mithilfe von Google Maps platzieren. Breiten- und Längengrad, Drehung und Höhe der Inhalte werden automatisch für Sie berechnet.
  • Google Maps verwenden
  • Google Earth verwenden Wenn Sie diese Koordinaten mit Google Earth statt mit Google Maps ermitteln, kann die Fehlertoleranz bis zu mehreren Metern betragen.
  • Zum physischen Standort gehen

Google Maps verwenden

So ermitteln Sie mit Google Maps den Breiten- und Längengrad eines Standorts:

  1. Rufen Sie auf Ihrem Computer Google Maps auf.

  2. Klicken Sie auf Ebenen > Dreipunkt-Menü.

  3. Ändern Sie den Kartentyp in Satellit und entfernen Sie das Häkchen im Kästchen Globusansicht links unten auf dem Bildschirm.

    Dadurch wird eine 2D-Perspektive erzwungen und mögliche Fehler, die durch eine geneigte 3D-Ansicht entstehen können, werden vermieden.

  4. Klicken Sie auf der Karte mit der rechten Maustaste auf den gewünschten Ort und wählen Sie die Längen-/Breitengrade aus, um sie in die Zwischenablage zu kopieren.

Google Earth verwenden

Sie können den Längen- und Breitengrad eines Ortes in Google Earth berechnen, indem Sie in der Benutzeroberfläche auf einen Ort klicken und die Daten der Ortsmarkierungsdetails auslesen.

So rufen Sie mit Google Earth den Breiten- und Längengrad eines Orts ab:

  1. Rufen Sie auf Ihrem Computer Google Earth auf.

  2. Öffnen Sie das Dreistrich-Menü  und wählen Sie Kartenstil aus.

  3. Deaktivieren Sie den Schalter 3D-Gebäude.

  4. Deaktivieren Sie den Schalter 3D-Gebäude und klicken Sie auf das Stecknadelsymbol , um eine Ortsmarkierung für den ausgewählten Ort hinzuzufügen.

  5. Geben Sie ein Projekt an, das Ihre Ortsmarkierung enthalten soll, und klicken Sie auf Speichern.

  6. Geben Sie im Feld Titel einen Namen für die Ortsmarkierung ein.

  7. Klicken Sie im Projektbereich auf den Zurückpfeil  und wählen Sie das Dreipunkt-Menü  Weitere Aktionen aus.

  8. Wählen Sie im Menü die Option Als KML-Datei exportieren aus.

In der KLM-Datei werden Breiten-, Längengrad und Höhe für eine Ortsmarkierung im <coordinates>-Tag wie folgt getrennt durch Kommas angegeben:

<coordinates>-122.0755182435043,37.41347299422944,7.420342565583832</coordinates>

Verwenden Sie nicht den Breiten- und Längengrad aus den <LookAt>-Tags, da diese die Kameraposition und nicht den Standort angeben.

Zum physischen Standort gehen

Sie können die Höhe eines Standorts berechnen, indem Sie sich dorthin begeben und eine lokale Beobachtung vornehmen.

Rotationsquaternion abrufen

GeospatialPose.getEastUpSouthQuaternion() extrahiert die Ausrichtung aus einer geografische Pose und gibt einen Quaternion aus, der die Rotationsmatrix darstellt, die einen Vektor vom Ziel in das Koordinatensystem „Ost-Oben-Süd“ (EUS) transformiert. X+ zeigt nach Osten, Y+ nach oben und Z+ nach Süden. Die Werte werden in der Reihenfolge {x, y, z, w} geschrieben.

WGS84-Anker

Ein WGS84-Anchor ist eine Art Anchor, mit dem Sie 3D-Inhalte an einem beliebigen Breiten-, Längen- und Höhengrad platzieren können. Es benötigt eine Pose und eine Ausrichtung, um in der realen Welt platziert zu werden. Die Position besteht aus einem Breiten- und Längengrad sowie einer Höhe, die im WGS84-Koordinatensystem angegeben sind. Die Ausrichtung besteht aus einer Quaternionrotation.

Die Höhe wird in Metern über dem Referenz-WGS84-Ellipsoid angegeben, sodass der Nullpunkt nicht auf Höhe des Bodens liegt. Ihre App muss diese Koordinaten für jeden erstellten Anker bereitstellen.

WGS84-Anker in der realen Welt platzieren

Höhe eines Standorts bestimmen

Es gibt mehrere Möglichkeiten, die Höhe eines Standorts für das Setzen von Markierungen zu ermitteln:

  • Wenn sich der Ankerort in der Nähe des Nutzers befindet, können Sie eine Höhe verwenden, die der Höhe des Geräts des Nutzers entspricht.
  • Sobald Sie die Breiten- und Längengrade haben, verwenden Sie die Elevation API, um eine Höhe gemäß der EGM96-Spezifikation abzurufen. Sie müssen die EGM96-Höhe der Maps API in WGS84 umrechnen, um sie mit der GeospatialPose zu vergleichen. Weitere Informationen finden Sie unter GeoidEval, das sowohl eine Befehlszeile als auch eine HTML-Benutzeroberfläche hat. Die Maps API gibt standardmäßig Breiten- und Längengrade gemäß der WGS84-Spezifikation zurück.
  • Breiten- und Längengrad sowie Höhe eines Standorts können Sie in Google Earth abrufen. Dadurch erhalten Sie einen Fehlerbereich von bis zu mehreren Metern. Verwenden Sie in der KML-Datei die Breiten- und Längengrade sowie die Höhe aus den <coordinates>-Tags, nicht aus den <LookAt>-Tags.
  • Wenn sich ein vorhandener Anker in der Nähe befindet und Sie sich nicht an einem steilen Hang befinden, können Sie die Höhe von der GeospatialPose der Kamera verwenden, ohne eine andere Quelle wie die Maps API zu verwenden.

Anker erstellen

Sobald Sie Breiten-, Längengrad, Höhe und Rotationsquaternion ermittelt haben, können Sie Earth.createAnchor() verwenden, um Inhalte an den von Ihnen angegebenen geografischen Koordinaten zu verankern.

Java

if (earth != null && earth.getTrackingState() == TrackingState.TRACKING) {
  Anchor anchor =
    earth.createAnchor(
      /* Location values */
      latitude,
      longitude,
      altitude,
      /* Rotational pose values */
      qx,
      qy,
      qz,
      qw);

  // Attach content to the anchor specified by geodetic location and pose.
}

Kotlin

if (earth.trackingState == TrackingState.TRACKING) {
  val anchor =
    earth.createAnchor(
      /* Location values */
      latitude,
      longitude,
      altitude,
      /* Rotational pose values */
      qx,
      qy,
      qz,
      qw
    )

  // Attach content to the anchor specified by geodetic location and pose.
}

Geländeanker

Ein Geländeanker ist eine Art Anker, mit dem Sie AR-Objekte nur anhand des Breiten- und Längengrads platzieren können. Dabei werden Informationen von VPS genutzt, um die genaue Höhe über dem Boden zu bestimmen.

Anstatt die gewünschte Höhe einzugeben, geben Sie die Höhe über dem Gelände an. Wenn dieser Wert null ist, befindet sich der Anker auf einer Höhe des Geländes.

Modus für die Flugzeugsuche festlegen

Die Suche nach der Ebene ist optional und nicht erforderlich, um Anker zu verwenden. Es werden nur horizontale Ebenen verwendet. Horizontale Ebenen erleichtern die dynamische Ausrichtung von Geländeankern auf dem Boden.

Mit Config.PlaneFindingMode kannst du festlegen, wie deine App Flugzeuge erkennt.

Geländeanker mit der neuen Async API erstellen

Rufen Sie Earth.resolveAnchorOnTerrainAsync() auf, um einen Geländeanker zu erstellen und zu platzieren.

Der Anker ist nicht sofort bereit und muss aufgelöst werden. Sobald das Problem behoben ist, ist es in der ResolveAnchorOnTerrainFuture verfügbar.

Java

final ResolveAnchorOnTerrainFuture future =
  earth.resolveAnchorOnTerrainAsync(
    latitude,
    longitude,
    /* altitudeAboveTerrain= */ 0.0f,
    qx,
    qy,
    qz,
    qw,
    (anchor, state) -> {
      if (state == TerrainAnchorState.SUCCESS) {
        // do something with the anchor here
      } else {
        // the anchor failed to resolve
      }
    });

Kotlin

var future =
  earth.resolveAnchorOnTerrainAsync(
    latitude,
    longitude,
    altitudeAboveTerrain,
    qx,
    qy,
    qz,
    qw,
    { anchor, state ->
      if (state == TerrainAnchorState.SUCCESS) {
        // do something with the anchor here
      } else {
        // the anchor failed to resolve
      }
    }
  )

„State of the Future“ prüfen

Der Zukunft ist ein FutureState zugeordnet.

Status Beschreibung
FutureState.PENDING Der Vorgang steht noch aus.
FutureState.DONE Der Vorgang ist abgeschlossen und das Ergebnis ist verfügbar.
FutureState.CANCELLED Der Vorgang wurde abgebrochen.

Ankerstatus „Gelände“ des Ergebnisses „Future“ prüfen

Die Anchor.TerrainAnchorState gehört zum asynchronen Vorgang und ist Teil des endgültigen Future-Ergebnisses.

Java

switch (terrainAnchorState) {
  case SUCCESS:
    // A resolving task for this Terrain anchor has finished successfully.
    break;
  case ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the Geospatial API.
    break;
  case ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/java/com/google/ar/core/Anchor.TerrainAnchorState#error_not_authorized
    // for troubleshooting steps.
    break;
  case ERROR_INTERNAL:
    // The Terrain anchor could not be resolved due to an internal error.
    break;
  default:
    // not reachable
    break;
}

Kotlin

when (state) {
  TerrainAnchorState.SUCCESS -> {
    // A resolving task for this Terrain anchor has finished successfully.
  }
  TerrainAnchorState.ERROR_UNSUPPORTED_LOCATION -> {
    // The requested anchor is in a location that isn't supported by the Geospatial API.
  }
  TerrainAnchorState.ERROR_NOT_AUTHORIZED -> {
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/java/com/google/ar/core/Anchor.TerrainAnchorState#error_not_authorized
    // for troubleshooting steps.
  }
  TerrainAnchorState.ERROR_INTERNAL -> {
    // The Terrain anchor could not be resolved due to an internal error.
  }
  else -> {
    // Default.
  }
}

Dachanker

Hero-Image für Dachanker

Dachdübel sind eine Art Anker und sind den Geländedübeln oben sehr ähnlich. Der Unterschied besteht darin, dass Sie die Höhe über dem Dach und nicht die Höhe über dem Gelände angeben.

Dachanker mit der neuen Async API erstellen

Der Anker ist nicht sofort verfügbar und muss aufgelöst werden.

Rufen Sie Earth.resolveAnchorOnRooftopAsync() auf, um einen Dachanker zu erstellen und zu platzieren. Ähnlich wie bei Geländeankern greifen Sie auch auf FutureState der Zukunft zu. Anschließend können Sie das Ergebnis für die Zukunft prüfen, um auf die Anchor.RooftopAnchorState zuzugreifen.

Java

final ResolveAnchorOnRooftopFuture future =
  earth.resolveAnchorOnRooftopAsync(
    latitude,
    longitude,
    /* altitudeAboveRooftop= */ 0.0f,
    qx,
    qy,
    qz,
    qw,
    (anchor, state) -> {
      if (state == RooftopAnchorState.SUCCESS) {
        // do something with the anchor here
      } else {
        // the anchor failed to resolve
      }
    });

Kotlin

var future =
  earth.resolveAnchorOnRooftopAsync(
    latitude,
    longitude,
    altitudeAboveRooftop,
    qx,
    qy,
    qz,
    qw,
    { anchor, state ->
      if (state == RooftopAnchorState.SUCCESS) {
        // do something with the anchor here
      } else {
        // the anchor failed to resolve
      }
    }
  )

„State of the Future“ prüfen

Der Zukunft ist ein FutureState zugeordnet, siehe Tabelle oben.

Dachankerstatus des zukünftigen Ergebnisses prüfen

Die Anchor.RooftopAnchorState gehört zum asynchronen Vorgang und ist Teil des endgültigen Future-Ergebnisses.

Java

switch (rooftopAnchorState) {
  case SUCCESS:
    // A resolving task for this Rooftop anchor has finished successfully.
    break;
  case ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the Geospatial API.
    break;
  case ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API.
    // https://developers.google.com/ar/reference/java/com/google/ar/core/Anchor.RooftopAnchorState#error_not_authorized
    // for troubleshooting steps.
    break;
  case ERROR_INTERNAL:
    // The Rooftop anchor could not be resolved due to an internal error.
    break;
  default:
    // not reachable
    break;
}

Kotlin

when (state) {
  RooftopAnchorState.SUCCESS -> {
    // A resolving task for this Rooftop anchor has finished successfully.
  }
  RooftopAnchorState.ERROR_UNSUPPORTED_LOCATION -> {
    // The requested anchor is in a location that isn't supported by the Geospatial API.
  }
  RooftopAnchorState.ERROR_NOT_AUTHORIZED -> {
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/java/com/google/ar/core/Anchor.RooftopAnchorState#error_not_authorized
    // for troubleshooting steps.
  }
  RooftopAnchorState.ERROR_INTERNAL -> {
    // The Rooftop anchor could not be resolved due to an internal error.
  }
  else -> {
    // Default.
  }
}

Nächste Schritte