Usar âncoras geoespaciais para posicionar conteúdo real no Android NDK

As âncoras geoespaciais são um tipo de âncora que permite colocar conteúdo 3D no mundo real.

Tipos de âncoras geoespaciais

Existem três tipos de âncoras geoespaciais, que processam a altitude de maneira diferente:

  1. Âncoras WGS84:
    As âncoras WGS84 permitem colocar conteúdo 3D em qualquer latitude, longitude e altitude.

  2. Âncoras de terreno:
    As âncoras de terreno permitem posicionar conteúdo usando somente latitude e longitude com uma altura relativa ao terreno naquela posição. A altitude é determinada em relação ao solo ou ao andar, como conhecido pelo VPS.

  3. Fixos de telhado:
    As âncoras no telhado permitem que você posicione conteúdo usando somente latitude e longitude com uma altura relativa ao telhado de um edifício naquela posição. A altitude é determinada em relação ao topo de um edifício, como conhecido da Streetscape Geometry. Por padrão, a altitude do terreno será definida quando não estiver em uma construção.

WGS84 Relevo Telhado
Posição horizontal Latitude, longitude Latitude, longitude Latitude, longitude
Posição vertical Relativa à altitude do WGS84 Relativa ao nível do terreno determinado pelo Google Maps Relativa ao nível do telhado determinado pelo Google Maps
Precisa ser resolvido pelo servidor? Não Sim Sim

Pré-requisitos

Ative a API Geospatial antes de continuar.

Posicionar âncoras geoespaciais

Cada tipo de âncora possui APIs dedicadas para criá-las; consulte Tipos de âncoras geoespaciais para mais informações.

Criar uma âncora a partir de um teste de hit

Você também pode criar uma âncora geoespacial com um resultado de teste de hit. Use a pose do teste de hit e converta-a em um ArGeospatialPose. Use-o para posicionar qualquer um dos três tipos de âncora descritos.

Fazer uma pose geoespacial com uma pose de RA

O ArEarth_getGeospatialPose() oferece outra maneira de determinar a latitude e a longitude convertendo uma pose de RA em uma geoespacial.

Fazer uma pose de RA de uma pose geoespacial

ArEarth_getPose() converte uma posição horizontal, altitude e rotação de quatérnio especificadas pela Terra em relação a um frame de coordenadas leste-sul em uma pose de AR em relação à coordenada mundial GL.

Escolha o método ideal para seu caso de uso

Cada método de criação de uma âncora apresenta compensações associadas que devem ser lembradas:

  • Ao usar o Streetscape Geometry, usar um teste de hit para anexar conteúdo a um edifício.
  • Prefira âncoras de terreno ou telhado em vez de âncoras WGS84 porque elas usam valores de altitude determinados pelo Google Maps.

Determinar a latitude e a longitude de um local

Há três maneiras de calcular a latitude e a longitude de um local:

  • Use o Geospatial Creator para ver e ampliar o mundo com conteúdo em 3D sem precisar ir fisicamente a um local. Isso permite posicionar visualmente o conteúdo imersivo em 3D usando o Google Maps no Unity Editor. A latitude, longitude, rotação e altitude do conteúdo serão calculadas automaticamente.
  • Usar o Google Maps
  • Usar o Google Earth. Observe que a obtenção dessas coordenadas usando o Google Earth, e não o Google Maps, lhe dará uma margem de erro de até vários metros.
  • Ir para o local físico

Usar o Google Maps

Para conferir a latitude e a longitude de um local usando o Google Maps, faça o seguinte:

  1. Acesse o Google Maps no seu computador desktop.

  2. Navegue até Camadas > Mais.

  3. Mude a opção Tipo de mapa para Satélite e desmarque a caixa de seleção Visualização de globo no canto inferior esquerdo da tela.

    Isso forçará uma perspectiva 2D e eliminará possíveis erros que podem vir de uma visualização 3D inclinada.

  4. No mapa, clique com o botão direito do mouse no local e selecione a longitude/latitude para copiá-lo para a área de transferência.

Usar o Google Earth

Para calcular a latitude e a longitude de um local no Google Earth, clique em um local na interface e leia os dados dos detalhes do marcador.

Para conferir a latitude e a longitude de um local usando o Google Earth:

  1. Acesse o Google Earth em um computador desktop.

  2. Navegue até o menu de navegação e selecione Estilo do mapa.

  3. Desative a opção Construções em 3D.

  4. Depois que a opção Construções em 3D for desativada, clique no ícone de fixação para adicionar um marcador de local no local selecionado.

  5. Especifique um projeto que contenha seu marcador de local e clique em Salvar.

  6. No campo Título do marcador de local, insira um nome para ele.

  7. Clique na seta para voltar no painel do projeto e selecione o menu Mais ações.

  8. Escolha Exportar como arquivo KML no menu.

O arquivo KLM informa a latitude, longitude e altitude de um marcador na tag <coordinates> separados por vírgulas, da seguinte forma:

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

Não use a latitude e a longitude das tags <LookAt>, que especificam a posição da câmera, não o local.

Ir para o local físico

Você pode calcular a altitude de um local indo até lá fisicamente e fazendo uma observação local.

Acessar o quatérnio de rotação

ArGeospatialPose_getEastUpSouthQuaternion() extrai a orientação de uma pose geoespacial e gera um quatérnio que representa a matriz de rotação que transforma um vetor do alvo para o sistema de coordenadas leste-para-sul (EUS). X+ pontos para leste, Y+ pontos para cima e Z+ pontos para sul. Os valores são gravados na ordem {x, y, z, w}.

Âncoras WGS84

Uma âncora WGS84 é um tipo de âncora que permite posicionar conteúdo 3D em qualquer latitude, longitude e altitude. Ele depende de uma postura e de uma orientação para ser colocado no mundo real. A posição consiste em latitude, longitude e altitude, que são especificadas no sistema de coordenadas WGS84. A orientação consiste em uma rotação de quatérnio.

A altitude é informada em metros acima do elipsoide de referência WGS84, de modo que o nível do solo não seja zero. Seu aplicativo é responsável por fornecer essas coordenadas para cada âncora criada.

Coloque uma âncora WGS84 no mundo real

Determinar a altitude de um local

Existem algumas maneiras de determinar a altitude de um local para colocar âncoras:

  • Se o local da âncora estiver fisicamente perto do usuário, você poderá usar uma altitude semelhante à do dispositivo do usuário.
  • Quando você tiver a latitude e a longitude, use a API Elevation para conferir uma elevação com base na especificação EGM96. Você precisa converter a elevação EGM96 da API Maps em WGS84 para comparação com a altitude de ArGeospatialPose. Veja o GeoidEval, que tem uma interface de linha de comando e uma HTML. A API do Google Maps informa a latitude e longitude de acordo com a especificação WGS84 pronta para uso.
  • Você pode obter a latitude, longitude e altitude de um local no Google Earth. Isso lhe dará uma margem de erro de até vários metros. Use a latitude, a longitude e a altitude das tags <coordinates>, não das tags <LookAt>, no arquivo KML.
  • Se um ponto âncora estiver próximo e você não estiver em uma subida íngreme, poderá usar a altitude do ArGeospatialPose da câmera sem outra fonte, como a API Maps.

Criar a âncora

Depois de ter a latitude, a longitude, a altitude e o quatérnio da rotação, use ArEarth_acquireNewAnchor(). para fixar o conteúdo nas coordenadas geográficas especificadas.

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

Âncoras para terrenos

Uma âncora de terreno é um tipo de âncora que permite posicionar objetos de RA usando somente latitude e longitude, aproveitando informações do VPS para encontrar a altitude precisa acima do solo.

Em vez de inserir a altitude desejada, você fornece a altitude acima do terreno. Quando esse valor é zero, a âncora fica nivelada com o terreno.

Definir o modo de descoberta de avião

A localização de planos é opcional e não é obrigatória para o uso de âncoras. Somente planos horizontais são usados. Planos horizontais ajudam no alinhamento dinâmico das âncoras de terreno no solo.

Use ArPlaneFindingMode para selecionar como o app detecta planos.

Criar uma âncora de terreno usando a nova API assíncrona

Para criar e posicionar uma âncora de terreno, chame ArEarth_resolveAnchorOnTerrainAsync().

O anúncio âncora não estará pronto imediatamente e precisa ser resolvido. Após a resolução, ela vai estar disponível no ArResolveAnchorOnTerrainFuture.

Verifique o estado da âncora do terreno usando ArResolveAnchorOnTerrainFuture_getResultTerrainAnchorState(). Consiga a âncora resolvida usando ArResolveAnchorOnTerrainFuture_acquireResultAnchor().

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

Confira o estado do futuro

O Future terá um ArFutureState associado.

Estado Descrição
AR_FUTURE_STATE_PENDING A operação ainda está pendente.
AR_FUTURE_STATE_DONE A operação foi concluída e o resultado está disponível.
AR_FUTURE_STATE_CANCELLED A operação foi cancelada.

Verificar o estado da âncora do terreno do resultado Futuro

O ArTerrainAnchorState pertence à operação assíncrona e faz parte do resultado final do Future.

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

Âncoras para telhados

Imagem principal das âncoras no telhado

As âncoras de telhado são um tipo de âncora e são muito semelhantes às Âncoras de terreno acima. A diferença é que você fornecerá a altitude acima do telhado em vez de fornecer a altitude acima do terreno.

Criar uma âncora Rooftop usando a nova API Async

O anúncio âncora não estará pronto imediatamente e precisa ser resolvido.

Para criar e posicionar uma âncora no telhado, chame ArEarth_resolveAnchorOnRooftopAsync(). Assim como nas âncoras de terreno, você também acessa o ArFutureState do futuro. Em seguida, marque o resultado futuro para acessar o ArRooftopAnchorState.

Use ArEarth_resolveAnchorOnRooftopAsync() para criar uma ArResolveAnchorOnRooftopFuture.

Confira o estado da âncora no telhado usando ArResolveAnchorOnRooftopFuture_getResultRooftopAnchorState().

Consiga a âncora resolvida usando ArResolveAnchorOnRooftopFuture_acquireResultAnchor().

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

Confira o estado do futuro

A classe Future terá um ArFutureState associado. Consulte a tabela acima.

Verificar o estado da âncora no telhado do resultado Future

O ArRooftopAnchorState pertence à operação assíncrona e faz parte do resultado final do Future.

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

A seguir