Cómo usar anclas geoespaciales para posicionar contenido real en el SDK de Android (Kotlin/Java)

Los anclas geoespaciales son un tipo de ancla que te permiten colocar contenido 3D en el mundo real.

Tipos de anclas geoespaciales

Existen tres tipos de anclas geoespaciales, y cada uno maneja la altitud de manera diferente:

  1. Anclas WGS84:
    Las anclas WGS84 te permiten colocar contenido 3D en cualquier latitud, longitud y altitud determinadas.

  2. Anclas de relieve:
    Las anclas de relieve te permiten colocar contenido utilizando únicamente la latitud y la longitud, y una altura relativa al terreno de esa posición. La altitud se determina en relación con el suelo o el piso, como los VPS.

  3. Anclas de techos:
    Las anclas de techos te permiten colocar contenido usando solo la latitud y la longitud, con una altura relativa al techo de un edificio en esa posición. La altitud se determina en relación con la parte superior de un edificio, como se conoce mediante la geometría del paisaje urbano. Esta opción se establece de forma predeterminada en la altitud del terreno cuando no se coloca en un edificio.

WGS84 Terreno Para techo
Posición horizontal Latitud, longitud Latitud, longitud Latitud, longitud
Posición vertical Relativo a la altitud WGS84 Relativo al nivel del terreno determinado por Google Maps Relativo al nivel del techo determinado por Google Maps
¿Necesita que el servidor se resuelva? No

Requisitos previos

Asegúrate de habilitar la API de Geospatial antes de continuar.

Cómo colocar anclas geoespaciales

Cada tipo de ancla tiene APIs dedicadas para crearlas. Consulta Tipos de anclas geoespaciales para obtener más información.

Crea un ancla a partir de una prueba de posicionamiento

También puedes crear un ancla geoespacial a partir de un resultado de la prueba de posicionamiento. Usa la Pose de la prueba de posicionamiento y conviértela en GeospatialPose. Úsala para colocar cualquiera de los 3 tipos de anclaje descritos.

Obtén una postura geoespacial con una posición de RA

Earth.getGeospatialPose() proporciona una forma adicional de determinar la latitud y longitud mediante la conversión de una posición de RA en una posición geoespacial.

Obtén una postura de RA con una posición geoespacial

Earth.getPose() convierte una posición horizontal, la altitud y la rotación del cuaternión especificados por la Tierra con respecto a un marco de coordenadas de este a sur en una posición de RA con respecto a la coordenada mundial de GL.

Elige el método que se adapte a tu caso de uso

Cada método para crear un ancla tiene compensaciones asociadas que se deben tener en cuenta:

  • Cuando uses la geometría del paisaje urbano, realiza una prueba de posicionamiento para adjuntar contenido a un edificio.
  • Prefiere las anclas de terreno o de techo en lugar de las anclas WGS84, ya que utilizan valores de altitud determinados por Google Maps.

Determinar la latitud y longitud de una ubicación

Existen tres maneras de calcular la latitud y longitud de una ubicación:

  • Usa el Creador de Geospatial para ver y ampliar el mundo con contenido 3D sin tener que ir físicamente a una ubicación. Esto te permite colocar visualmente contenido inmersivo en 3D con Google Maps en Unity Editor. La latitud, la longitud, la rotación y la altitud del contenido se calcularán automáticamente.
  • Usar Google Maps
  • Usa Google Earth. Ten en cuenta que, si obtienes estas coordenadas con Google Earth, a diferencia de Google Maps, obtendrás un margen de error de hasta varios metros.
  • Ir a la ubicación física

Usar Google Maps

Para obtener la latitud y la longitud de una ubicación con Google Maps, sigue estos pasos:

  1. Ve a Google Maps en tu computadora de escritorio.

  2. Navega a Capas > Más.

  3. Cambia el Tipo de mapa a Satélite y desmarca la casilla de verificación Globe View en la esquina inferior izquierda de la pantalla.

    De esta manera, se forzará una perspectiva en 2D y se eliminarán los posibles errores que podrían surgir cuando se mira un ángulo en 3D.

  4. En el mapa, haz clic con el botón derecho en la ubicación y selecciona la longitud o latitud para copiarla en el portapapeles.

Cómo usar Google Earth

Puedes calcular la latitud y longitud de una ubicación desde Google Earth haciendo clic en una ubicación en la interfaz de usuario y leyendo los datos de los detalles de los marcadores.

Para obtener la latitud y longitud de una ubicación con Google Earth, sigue estos pasos:

  1. Ve a Google Earth en tu computadora de escritorio.

  2. Navega al menú de hamburguesa y selecciona Estilo del mapa.

  3. Desactiva la opción Edificios 3D.

  4. Después de desactivar el interruptor de Edificios 3D, haz clic en el ícono de fijar para agregar un marcador en la ubicación seleccionada.

  5. Especifica un proyecto para que contenga tu marcador y haz clic en Guardar.

  6. En el campo Título del marcador, ingresa un nombre para este.

  7. Haz clic en la flecha hacia atrás en el panel del proyecto y selecciona el menú Más acciones.

  8. Elige Exportar como archivo KML en el menú.

El archivo KLM informa la latitud, la longitud y la altitud de un marcador en la etiqueta <coordinates> separados por comas, de la siguiente manera:

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

No uses la latitud ni la longitud de las etiquetas <LookAt>, que especifican la posición de la cámara y no la ubicación.

Ir a la ubicación física

Para calcular la altitud de una ubicación, puedes acudir a ese lugar físico y realizar una observación local.

Obtén el cuaternión de rotación

GeospatialPose.getEastUpSouthQuaternion() extrae la orientación de una posición geoespacial y da como resultado un cuaternión que representa la matriz de rotación que transforma un vector del objetivo al sistema de coordenadas de este a sur (EUS). X+ apunta hacia el este, Y+ apunta hacia arriba y Z+ apunta al sur. Los valores se escriben en el orden {x, y, z, w}.

Anclas WGS84

Un ancla WGS84 es un tipo de ancla que te permite colocar contenido 3D en cualquier latitud, longitud y altitud. Se basa en la posición y la orientación para ubicarse en el mundo real. La posición consta de una latitud, una longitud y una altitud que se especifican en el sistema de coordenadas WGS84. La orientación consiste en una rotación de cuaternión.

La altitud se informa en metros por encima del elipsoide WGS84 de referencia, de modo que el nivel del suelo no es cero. Tu app es responsable de proporcionar estas coordenadas para cada ancla creada.

Coloca un ancla WGS84 en el mundo real

Cómo determinar la altitud de una ubicación

Existen varias formas de determinar la altitud de una ubicación para colocar anclas:

  • Si la ubicación del ancla está físicamente cerca del usuario, puedes usar una altitud similar a la del dispositivo del usuario.
  • Una vez que tengas la latitud y la longitud, usa la API de Elevation para obtener una elevación según la especificación EGM96. Debes convertir la elevación EGM96 de la API de Google Maps a WGS84 para compararla con la altitud de GeospatialPose. Consulta GeoidEval que tiene una línea de comandos y una interfaz HTML. La API de Google Maps informa la latitud y la longitud de acuerdo con la especificación WGS84 lista para usar.
  • Puedes obtener la latitud, la longitud y la altitud de una ubicación en Google Earth. Aparecerá un margen de error de hasta varios metros. En el archivo KML, usa la latitud, la longitud y la altitud de las etiquetas <coordinates>, no de las etiquetas <LookAt>.
  • Si un ancla existente está cerca y si no estás en una inclinación empinada, es posible que puedas usar la altitud del GeospatialPose de la cámara sin usar otra fuente, como la API de Google Maps.

Crea el ancla

Una vez que tengas el cuaternión de latitud, longitud, altitud y rotación, usa Earth.createAnchor() para anclar el contenido a las coordenadas geográficas que especifiques.

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.
}

Anclas de relieve

Un ancla de terreno es un tipo de ancla que te permite colocar objetos de RA usando solo latitud y longitud, y aprovecha la información de los VPS para encontrar la altitud precisa sobre el suelo.

En lugar de ingresar la altitud deseada, puedes hacerlo por encima del terreno. Cuando el valor sea cero, el ancla estará nivelada con el terreno.

Cómo configurar el modo de búsqueda de planos

La búsqueda de planos es opcional y no es obligatorio para usar las anclas. Ten en cuenta que solo se usan planos horizontales. Los planos horizontales ayudarán a la alineación dinámica de los anclajes de terreno en el suelo.

Usa Config.PlaneFindingMode para seleccionar cómo tu app detecta los planos.

Crea un ancla de terreno con la nueva API de Async

Para crear y colocar un ancla de terreno, llama a Earth.resolveAnchorOnTerrainAsync().

El ancla no estará lista de inmediato y debe resolverse. Una vez que se resuelva, estará disponible en ResolveAnchorOnTerrainFuture.

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
      }
    }
  )

Conoce el estado del futuro

La interfaz Future tendrá un objeto FutureState asociado.

Estado Descripción
FutureState.PENDING La operación aún está pendiente.
FutureState.DONE La operación está completa y el resultado está disponible.
FutureState.CANCELLED Se canceló la operación.

Verifica el estado del ancla del terreno del resultado Future

El elemento Anchor.TerrainAnchorState pertenece a la operación asíncrona y forma parte del resultado Future final.

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.
  }
}

Anclajes para techos

Hero image de las anclas de techo

Los anclajes de techo son un tipo de ancla y son muy similares a los anclajes de relieve mencionados anteriormente. La diferencia consiste en que se debe proporcionar la altitud sobre el techo en lugar de la altitud sobre el terreno.

Crea un ancla de techo con la nueva API de Async

El ancla no estará lista de inmediato y debe resolverse.

Para crear y colocar un ancla de techo, llama a Earth.resolveAnchorOnRooftopAsync(). Al igual que con las anclas de terreno, también accederás al FutureState de Future. Luego, puedes verificar el resultado futuro para acceder a Anchor.RooftopAnchorState.

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
      }
    }
  )

Conoce el estado del futuro

La interfaz Future tendrá un objeto FutureState asociado. Consulta la tabla anterior.

Verifica el estado del ancla de techo del resultado Future

El elemento Anchor.RooftopAnchorState pertenece a la operación asíncrona y forma parte del resultado Future final.

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.
  }
}

Próximos pasos