Geospatiale Anchors verwenden, um reale Inhalte auf Android NDK 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 raumbezogenen Ankern, die Höhen jeweils unterschiedlich verarbeiten:

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

  2. Geländeanker:
    . Mit Geländeanker können Sie Inhalte nur anhand des Breiten- und Längengrads platzieren, wobei eine Höhe relativ zum Gelände an dieser Position angegeben wird. Die Höhe wird relativ zum Boden bzw. zur Etage bestimmt, wie von VPS bekannt.

  3. Dachdübel:
    Mit dieser Option können Sie Inhalte nur anhand des Breiten- und Längengrads mit einer Höhe relativ zum Dach eines Gebäudes an dieser Position platzieren. Die Höhe wird relativ zur Oberseite eines Gebäudes bestimmt, wie sie durch Streetscape Geometry bekannt ist. Wenn das Objekt nicht auf einem Gebäude platziert wird, 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 zum von Google Maps ermittelten Geländeniveau Relativ zur Dachebene (von Google Maps ermittelt)
Muss vom Server behoben werden? Nein Ja Ja

Voraussetzungen

Aktivieren Sie die Geospatial API, bevor Sie fortfahren.

Raumbezogene Ankerpunkte festlegen

Für jeden Ankertyp gibt es spezielle APIs. Weitere Informationen finden Sie unter Arten von raumbezogenen Ankern.

Anker aus einem Treffertest erstellen

Sie können einen raumbezogenen Anker auch aus einem Treffertestergebnis erstellen. Verwende die Pose aus dem Treffertest und wandle sie in einen ArGeospatialPose um. Verwenden Sie es, um einen der drei beschriebenen Ankertypen zu platzieren.

Raumbezogene Pose aus AR-Positionen nehmen

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

Eine AR-Stellung aus einer Geo-Stellung machen

ArEarth_getPose() wandelt eine von der Erde angegebene horizontale Position, Höhe und Quaternion-Drehung in Bezug auf einen Ost-oben-Süd-Koordinatenframe in eine AR-Position in Bezug auf die GL-Weltkoordinate um.

Methode für Ihren Anwendungsfall auswählen

Bei jeder Methode zum Erstellen eines Ankers müssen bestimmte Vor- und Nachteile berücksichtigt werden:

  • Wenn Sie Streetscape-Geometrie verwenden, führen Sie einen Treffertest aus, um Inhalte an ein Gebäude anzuhängen.
  • Gelände- oder Dachanker sollten gegenüber WGS84-Ankern bevorzugt werden, da hierfür von Google Maps ermittelte Höhenwerte verwendet werden.

Breiten- und Längengrad eines Ortes bestimmen

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

  • Verwenden Sie Geospatial Creator, um die Welt mit 3D-Content zu betrachten und zu erweitern, ohne einen Ort besuchen zu müssen. Damit können Sie immersive 3D-Inhalte mithilfe von Google Maps im Unity-Editor visuell platzieren. Breitengrad, Längengrad, Rotation und Höhe des Contents werden automatisch berechnet.
  • Google Maps verwenden
  • Google Earth verwenden Wenn Sie diese Koordinaten mit Google Earth und nicht mit Google Maps abrufen, erhalten Sie einen Fehlerbereich von bis zu mehreren Metern.
  • Zum physischen Standort gehen

Google Maps verwenden

So ermitteln Sie den Breiten- und Längengrad eines Ortes in Google Maps:

  1. Rufen Sie auf Ihrem Computer Google Maps auf.

  2. Gehen Sie zu Ebenen > Mehr.

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

    Dadurch wird eine 2D-Perspektive erzwungen und mögliche Fehler verhindert, die aus einer angewinkelten 3D-Ansicht entstehen könnten.

  4. Klicken Sie auf der Karte mit der rechten Maustaste auf den Ort und wählen Sie den Längen- und Breitengrad aus, um ihn in die Zwischenablage zu kopieren.

Google Earth verwenden

Sie können den Breiten- und Längengrad eines Ortes in Google Earth berechnen, indem Sie in der Benutzeroberfläche auf einen Ort klicken und die Daten der Ortsmarkendetails lesen.

So ermitteln Sie den Breiten- und Längengrad eines Ortes mit Google Earth:

  1. Rufen Sie Google Earth auf Ihrem Computer auf.

  2. Gehen Sie zum Dreistrich-Menü und wählen Sie Kartenstil aus.

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

  4. Wenn die Option 3D-Gebäude deaktiviert ist, klicken Sie auf das Stecknadelsymbol , um eine Ortsmarkierung am ausgewählten Standort hinzuzufügen.

  5. Geben Sie das Projekt für die Ortsmarkierung an und klicken Sie auf Speichern.

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

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

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

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

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

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

Zum physischen Standort gehen

Sie können die Höhe eines Ortes berechnen, indem Sie ihn dort hin- und herbewegen und eine lokale Beobachtung machen.

Rotationsquaternion abrufen

ArGeospatialPose_getEastUpSouthQuaternion() extrahiert die Ausrichtung aus einer raumbezogenen Position und gibt ein Quadernion aus, das die Rotationsmatrix darstellt, die einen Vektor vom Ziel in das Ost-oben-Süd-Koordinatensystem (EUS-Koordinatensystem) umwandelt. 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-Anker ist eine Art Anker, mit dem Sie 3D-Inhalte an jedem beliebigen Breiten- und Längengrad sowie in beliebiger Höhe platzieren können. Sie basiert auf einer Haltung und einer Orientierung, um sie in der realen Welt zu platzieren. Die Position besteht aus einem Breiten- und Längengrad sowie einer Höhe, die im WGS84-Koordinatensystem angegeben werden. Die Ausrichtung besteht aus einer Quaternionsrotation.

Die Höhe wird in Metern über dem WGS84-Ellipsoid angegeben, sodass die Bodenhöhe nicht bei null liegt. Ihre App ist für die Bereitstellung dieser Koordinaten für jeden erstellten Anker verantwortlich.

WGS84-Anker in der realen Welt platzieren

Höhe eines Ortes bestimmen

Es gibt mehrere Möglichkeiten, die Höhe eines Standorts beim Positionieren von Ankern zu bestimmen:

  • Wenn sich die Position des Ankers in der Nähe des Nutzers befindet, können Sie eine Höhe verwenden, die der Höhe des Nutzergeräts ähnelt.
  • Sobald Sie den Breiten- und Längengrad ermittelt haben, können Sie die Elevation API verwenden, um eine Höhe gemäß der EGM96 zu erhalten. Sie müssen die Maps API EGM96-Höhe in WGS84 konvertieren, damit sie mit der ArGeospatialPose-Höhe verglichen werden kann. Siehe GeoidEval mit einer Befehlszeile und einer HTML-Schnittstelle. Das Google Maps-API meldet Breiten- und Längengrade standardmäßig gemäß der WGS84-Spezifikation.
  • Die Breiten-, Längen- und Höhenangaben eines Ortes 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-, Längengrad- und Höhenangaben aus den <coordinates>-Tags, nicht aus den <LookAt>-Tags.
  • Wenn sich ein bereits vorhandener Anker in der Nähe befindet und Sie sich nicht an einem steilen Steigung befinden, können Sie die Höhe des ArGeospatialPose-Objekts der Kamera möglicherweise ohne eine andere Quelle wie die Maps API verwenden.

Anker erstellen

Sobald Sie die Breiten-, Längengrad-, Höhen- und Rotationsquaternion ermittelt haben, verwenden Sie ArEarth_acquireNewAnchor(), um Inhalte an den von Ihnen angegebenen geografischen Koordinaten zu verankern.

float eus_quaternion_4[4] = {qx, qy, qz, qw};
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArAnchor* earth_anchor = NULL;
    ArStatus status = ArEarth_acquireNewAnchor(ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude,
        eus_quaternion_4, &earth_anchor);

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

Geländeanker

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

Sie geben nicht die gewünschte Höhe ein, sondern geben die Höhe über dem Gelände an. Wenn dieser Wert null ist, befindet sich der Anker auf einer Höhe mit dem Gelände.

Suchmodus für Flugzeuge festlegen

Das Finden von Ebenen ist optional und für die Verwendung von Ankern nicht erforderlich. Beachten Sie, dass nur horizontale Ebenen verwendet werden. Horizontale Ebenen erleichtern die dynamische Ausrichtung von Geländeankern am Boden.

Wählen Sie mit ArPlaneFindingMode aus, wie Ihre App Flugzeuge erkennt.

Geländeanker mit der neuen Async API erstellen

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

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

Prüfen Sie den Status des Geländeankers mit ArResolveAnchorOnTerrainFuture_getResultTerrainAnchorState(). Rufen Sie den aufgelösten Anker mit ArResolveAnchorOnTerrainFuture_acquireResultAnchor() ab.

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnTerrainCallback callback = NULL;
ArResolveAnchorOnTerrainFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnTerrainAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_terrain, eus_quaternion_4,
        context, callback, &future);
  }
}

Die Zukunft überprüfen

Das Future hat ein verknüpftes ArFutureState.

Status Beschreibung
AR_FUTURE_STATE_PENDING Der Vorgang steht noch aus.
AR_FUTURE_STATE_DONE Der Vorgang ist abgeschlossen und das Ergebnis ist verfügbar.
AR_FUTURE_STATE_CANCELLED Der Vorgang wurde abgebrochen.

Status des Geländeankers des Future-Ergebnisses prüfen

Der ArTerrainAnchorState gehört zum asynchronen Vorgang und ist Teil des endgültigen Future-Ergebnisses.

switch (terrain_anchor_state) {
  case AR_TERRAIN_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_TERRAIN_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_TERRAIN_ANCHOR_STATE_ERROR_INTERNAL:
    // The Terrain anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

Dachanker

Hero-Image – Dach Anker

Dachanker sind eine Art Anker und ähneln den obigen Geländeanker sehr. Der Unterschied besteht darin, dass Sie die Höhe über dem Dach und nicht die über dem Gelände angeben.

Rooftop-Anker mit der neuen Async API erstellen

Der Anker ist nicht sofort fertig und muss aufgelöst werden.

Um einen Dachanker zu erstellen und zu platzieren, rufen Sie ArEarth_resolveAnchorOnRooftopAsync() auf. Ähnlich wie bei Geländeankerpunkten rufen Sie auch das ArFutureState des Futures auf. Anschließend können Sie das Ergebnis „Future“ anklicken, um auf ArRooftopAnchorState zuzugreifen.

Verwenden Sie ArEarth_resolveAnchorOnRooftopAsync(), um eine ArResolveAnchorOnRooftopFuture zu erstellen.

Prüfen Sie den Status des Ankers auf dem Dach mit ArResolveAnchorOnRooftopFuture_getResultRooftopAnchorState().

Rufen Sie den aufgelösten Anker mit ArResolveAnchorOnRooftopFuture_acquireResultAnchor() ab.

float eus_quaternion_4[4] = {qx, qy, qz, qw};
void* context = NULL;
ArResolveAnchorOnRooftopCallback callback = NULL;
ArResolveAnchorOnRooftopFuture* future = NULL;
if (ar_earth != NULL) {
  ArTrackingState earth_tracking_state = AR_TRACKING_STATE_STOPPED;
  ArTrackable_getTrackingState(ar_session, (ArTrackable*)ar_earth,
                               &earth_tracking_state);
  if (earth_tracking_state == AR_TRACKING_STATE_TRACKING) {
    ArStatus status = ArEarth_resolveAnchorOnRooftopAsync(
        ar_session, ar_earth,
        /* location values */
        latitude, longitude, altitude_above_rooftop, eus_quaternion_4,
        context, callback, &future);
  }
}

Die Zukunft überprüfen

Dem Future-Objekt wird ein ArFutureState zugeordnet, siehe Tabelle oben.

Dachankerstatus des Ergebnisses „Future“ prüfen

Der ArRooftopAnchorState gehört zum asynchronen Vorgang und ist Teil des endgültigen Future-Ergebnisses.

switch (rooftop_anchor_state) {
  case AR_ROOFTOP_ANCHOR_STATE_SUCCESS:
    // A resolving task for this anchor has been successfully resolved.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_UNSUPPORTED_LOCATION:
    // The requested anchor is in a location that isn't supported by the
    // Geospatial API.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED:
    // An error occurred while authorizing your app with the ARCore API. See
    // https://developers.google.com/ar/reference/c/group/ar-anchor#:~:text=from%20this%20error.-,AR_ROOFTOP_ANCHOR_STATE_ERROR_NOT_AUTHORIZED,-The%20authorization%20provided
    // for troubleshooting steps.
    break;
  case AR_ROOFTOP_ANCHOR_STATE_ERROR_INTERNAL:
    // The Rooftop anchor could not be resolved due to an internal error.
    break;
  default:
    break;
}

Nächste Schritte