از لنگرهای Geospatial برای قرار دادن محتوای دنیای واقعی در Unity استفاده کنید

لنگرهای جغرافیایی نوعی لنگر هستند که به شما امکان می دهند محتوای سه بعدی را در دنیای واقعی قرار دهید.

انواع لنگرهای جغرافیایی

سه نوع لنگر ژئوفضایی وجود دارد که هر کدام به طور متفاوتی ارتفاع را کنترل می کنند:

  1. لنگرهای WGS84 :
    لنگرهای WGS84 به شما امکان می دهند محتوای سه بعدی را در هر عرض جغرافیایی، طول جغرافیایی و ارتفاع مشخصی قرار دهید.

  2. لنگرهای زمین :
    لنگرهای زمین به شما امکان می دهند محتوا را فقط با استفاده از طول و عرض جغرافیایی با ارتفاع نسبت به زمین در آن موقعیت قرار دهید. ارتفاع نسبت به همکف یا طبقه که توسط VPS شناخته می شود تعیین می شود.

  3. لنگرهای پشت بام :
    لنگرهای پشت بام به شما امکان می دهند محتوا را فقط با استفاده از طول و عرض جغرافیایی با ارتفاع نسبت به پشت بام ساختمان در آن موقعیت قرار دهید. ارتفاع نسبت به بالای یک ساختمان که توسط Streetscape Geometry شناخته می شود تعیین می شود. زمانی که روی ساختمان قرار نگیرد، به طور پیش‌فرض ارتفاع زمین را نشان می‌دهد.

WGS84 زمین پشت بام
موقعیت افقی عرض جغرافیایی، طول جغرافیایی عرض جغرافیایی، طول جغرافیایی عرض جغرافیایی، طول جغرافیایی
موقعیت عمودی نسبت به ارتفاع WGS84 نسبت به سطح زمین تعیین شده توسط Google Maps نسبت به سطح پشت بام تعیین شده توسط Google Maps
نیاز به حل و فصل سرور دارد؟ خیر بله بله

پیش نیازها

قبل از ادامه، مطمئن شوید که Geospatial API را فعال کرده اید.

لنگرهای جغرافیایی را قرار دهید

هر نوع لنگر دارای APIهای اختصاصی برای ایجاد آنها است. برای اطلاعات بیشتر به انواع لنگرهای جغرافیایی مراجعه کنید.

یک لنگر از یک تست ضربه ایجاد کنید

شما همچنین می توانید یک لنگر Geospatial از یک نتیجه تست ضربه ایجاد کنید. از Pose از تست ضربه استفاده کنید و آن را به GeospatialPose تبدیل کنید. از آن برای قرار دادن هر یک از 3 نوع لنگر شرح داده شده استفاده کنید.

از یک ژست AR یک ژئوفضایی بگیرید

AREarthManager.Convert(Pose) یک راه اضافی برای تعیین طول و عرض جغرافیایی با تبدیل یک Pose AR به یک Pose Geospatial ارائه می دهد.

یک ژست واقعیت افزوده از یک موقعیت جغرافیایی

AREarthManager.Convert(GeospatialPose) موقعیت افقی، ارتفاع و چرخش ربع تعیین شده توسط زمین را با توجه به یک قاب مختصات شرق به بالا به جنوب به وضعیت AR با توجه به مختصات جهانی GL تبدیل می کند.

انتخاب کنید کدام روش مناسب مورد استفاده شما است

هر روش ایجاد یک لنگر دارای معاوضه هایی است که باید به خاطر داشته باشید:

  • هنگام استفاده از Streetscape Geometry ، از تست ضربه برای پیوست کردن محتوا به ساختمان استفاده کنید.
  • لنگرهای زمینی یا پشت بام را به لنگرهای WGS84 ترجیح دهید زیرا از مقادیر ارتفاع تعیین شده توسط Google Maps استفاده می کنند.

طول و عرض جغرافیایی یک مکان را تعیین کنید

سه روش برای محاسبه طول و عرض جغرافیایی یک مکان وجود دارد:

  • از Geospatial Creator برای مشاهده و تقویت جهان با محتوای سه بعدی بدون نیاز به رفتن فیزیکی به مکانی استفاده کنید. این به شما امکان می دهد محتوای سه بعدی همه جانبه را به صورت بصری با استفاده از نقشه های گوگل در ویرایشگر Unity قرار دهید. طول و عرض جغرافیایی، چرخش و ارتفاع محتوا به طور خودکار برای شما محاسبه می شود.
  • از نقشه های گوگل استفاده کنید
  • از Google Earth استفاده کنید. توجه داشته باشید که به دست آوردن این مختصات با استفاده از گوگل ارث، بر خلاف نقشه گوگل، تا چندین متر حاشیه خطا برای شما ایجاد می کند.
  • به مکان فیزیکی بروید

از نقشه های گوگل استفاده کنید

برای دریافت طول و عرض جغرافیایی یک مکان با استفاده از Google Maps:

  1. در رایانه رومیزی خود به Google Maps بروید.

  2. به لایه ها > بیشتر بروید.

  3. نوع Map را به Satellite تغییر دهید و تیک Globe View را در گوشه سمت چپ پایین صفحه پاک کنید.

    این کار باعث می شود که یک چشم انداز دوبعدی ایجاد شود و خطاهای احتمالی که می تواند از نمای سه بعدی زاویه دار ایجاد شود را حذف می کند.

  4. روی نقشه، روی مکان کلیک راست کرده و طول جغرافیایی/طول جغرافیایی را انتخاب کنید تا آن را در کلیپ بورد خود کپی کنید.

از Google Earth استفاده کنید

می‌توانید با کلیک کردن روی یک مکان در رابط کاربری و خواندن داده‌ها از جزئیات مکان‌نما، طول و عرض جغرافیایی یک مکان را از Google Earth محاسبه کنید.

برای دریافت طول و عرض جغرافیایی یک مکان با استفاده از Google Earth:

  1. در رایانه رومیزی خود به Google Earth بروید.

  2. به منوی همبرگر بروید و Map Style را انتخاب کنید.

  3. سوئیچ ساختمان های سه بعدی را خاموش کنید.

  4. هنگامی که سوئیچ ساختمان های سه بعدی خاموش شد، روی نماد پین کلیک کنید برای اضافه کردن یک مکان در مکان انتخاب شده.

  5. پروژه ای را مشخص کنید که نشان مکان شما را داشته باشد و روی ذخیره کلیک کنید.

  6. در قسمت عنوان برای نشان مکان، یک نام برای نشان مکان وارد کنید.

  7. روی فلش عقب کلیک کنید در پنجره پروژه و انتخاب کنید منوی اقدامات بیشتر .

  8. از منو Export as file KML را انتخاب کنید.

فایل KLM طول، طول و ارتفاع را برای یک مکان در تگ <coordinates> که با کاما از هم جدا شده است، به شرح زیر گزارش می دهد:

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

از طول و عرض جغرافیایی تگ های <LookAt> که موقعیت دوربین را مشخص می کنند، نه مکان را استفاده نکنید .

به مکان فیزیکی بروید

شما می توانید ارتفاع یک مکان را با رفتن به آنجا به صورت فیزیکی و انجام یک مشاهده محلی محاسبه کنید.

کواترنیون چرخش را بدست آورید

GeospatialPose.EunRotation جهت گیری را از یک Pose Geospatial استخراج می کند و یک کواترنیون به دست می دهد که نشان دهنده ماتریس چرخش است که یک بردار را از هدف به سیستم مختصات شرق به بالا-شمال (EUN) تبدیل می کند. X+ به سمت شرق، Y+ به سمت بالا به دور از گرانش، و Z+ به شمال اشاره می کند.

لنگر WGS84

لنگر WGS84 نوعی لنگر است که به شما امکان می دهد محتوای سه بعدی را در هر عرض جغرافیایی، طول و ارتفاع معین قرار دهید. برای قرار گرفتن در دنیای واقعی به پوز و جهت گیری متکی است. این موقعیت شامل یک عرض جغرافیایی، طول جغرافیایی و ارتفاع است که در سیستم مختصات WGS84 مشخص شده است. جهت گیری از یک چرخش کواترنیونی تشکیل شده است.

ارتفاع بر حسب متر بالاتر از بیضی مرجع WGS84 گزارش شده است به طوری که سطح زمین در صفر نیست . برنامه شما مسئول ارائه این مختصات برای هر لنگر ایجاد شده است.

یک لنگر WGS84 را در دنیای واقعی قرار دهید

ارتفاع یک مکان را تعیین کنید

چند راه برای تعیین ارتفاع مکان برای قرار دادن لنگر وجود دارد:

  • اگر مکان لنگر از نظر فیزیکی نزدیک کاربر است، می‌توانید از ارتفاعی مشابه ارتفاع دستگاه کاربر استفاده کنید.
  • هنگامی که طول و عرض جغرافیایی را دارید، از Elevation API برای بدست آوردن ارتفاع بر اساس مشخصات EGM96 استفاده کنید. شما باید ارتفاع Maps API EGM96 را برای مقایسه با ارتفاع GeospatialPose به WGS84 تبدیل کنید. GeoidEval را ببینید که دارای خط فرمان و رابط HTML است. Maps API طول و عرض جغرافیایی را مطابق با مشخصات WGS84 از جعبه گزارش می دهد.
  • می‌توانید طول، طول و ارتفاع یک مکان را از Google Earth دریافت کنید. این به شما یک حاشیه خطا تا چند متر می دهد. از طول، طول و ارتفاع از تگ های <coordinates> استفاده کنید، نه تگ های <LookAt> را در فایل KML.
  • اگر یک لنگر موجود نزدیک است و اگر در شیب تند نیستید، ممکن است بتوانید از ارتفاع GeospatialPose دوربین بدون استفاده از منبع دیگری مانند Maps API استفاده کنید.

لنگر را ایجاد کنید

هنگامی که ربع طول جغرافیایی، طول جغرافیایی، ارتفاع و چرخش را دارید، از ARAnchorManagerExtensions.AddAnchor() برای لنگر انداختن محتوا به مختصات جغرافیایی که مشخص می کنید استفاده کنید.

if (earthTrackingState == TrackingState.Tracking)
{
  var anchor =
      AnchorManager.AddAnchor(
          latitude,
          longitude,
          altitude,
          quaternion);
  var anchoredAsset = Instantiate(GeospatialAssetPrefab, anchor.transform);
}

لنگرهای زمین

لنگر زمینی نوعی لنگر است که به شما امکان می دهد اشیاء AR را فقط با استفاده از طول و عرض جغرافیایی قرار دهید و از اطلاعات VPS برای یافتن ارتفاع دقیق از سطح زمین استفاده کنید.

به جای اینکه ارتفاع مورد نظر را وارد کنید، ارتفاع بالای زمین را ارائه می دهید. هنگامی که این صفر باشد، لنگر هم سطح با زمین خواهد بود.

حالت هواپیمایابی را تنظیم کنید

پیدا کردن هواپیما اختیاری است و برای استفاده از لنگرها لازم نیست. توجه داشته باشید که فقط از صفحات افقی استفاده می شود. هواپیماهای افقی به هم ترازی پویا لنگرهای زمین در زمین کمک خواهند کرد.

توجه داشته باشید که لنگرهای زمین تحت تأثیر Horizontal و Horizontal | Vertical

از منوی کشویی Detection Mode برای تنظیم حالت تشخیص استفاده کنید:

با استفاده از Async API جدید یک لنگر Terrain ایجاد کنید

برای ایجاد و قرار دادن لنگر Terrain، ARAnchorManagerExtensions.resolveAnchorOnTerrainAsync() را فراخوانی کنید.

لنگر بلافاصله آماده نخواهد شد و باید حل شود. پس از حل شدن، در ResolveAnchorOnTerrainPromise در دسترس خواهد بود.

public GameObject TerrainAnchorPrefab;

public void Update()
{
    ResolveAnchorOnTerrainPromise terrainPromise =
        AnchorManager.ResolveAnchorOnTerrainAsync(
            latitude, longitude, altitudeAboveTerrain, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckTerrainPromise(terrainPromise));
}

private IEnumerator CheckTerrainPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.TerrainAnchorState == TerrainAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(TerrainAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

وضعیت قول را بررسی کنید

Promise یک PromiseState مرتبط خواهد داشت.

ایالت توضیحات
Pending عملیات همچنان در انتظار است.
Done عملیات کامل شده و نتیجه در دسترس است.
Cancelled عملیات لغو شده است.

وضعیت لنگر زمین نتیجه Promise را بررسی کنید

TerrainAnchorState متعلق به عملیات ناهمزمان است و بخشی از نتیجه نهایی Promise است.

switch (result.TerrainAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case TerrainAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case TerrainAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case TerrainAnchorState.ErrorInternal:
        // The Terrain anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

لنگرهای پشت بام

پشت بام لنگر قهرمان

لنگرهای پشت بام نوعی لنگر هستند و بسیار شبیه به لنگرهای Terrain در بالا هستند. تفاوت این است که شما به جای ارتفاع بالای زمین، ارتفاع بالای پشت بام را ارائه می دهید.

یک لنگر پشت بام با استفاده از Async API جدید ایجاد کنید

لنگر بلافاصله آماده نخواهد شد و باید حل شود.

برای ایجاد و قرار دادن یک لنگر پشت بام، ARAnchorManagerExtensions.resolveAnchorOnRooftopAsync() را فراخوانی کنید. مشابه لنگرهای Terrain، به PromiseState of the Promise نیز دسترسی خواهید داشت. سپس می توانید نتیجه Promise را برای دسترسی به RooftopAnchorState بررسی کنید.

public GameObject RooftopAnchorPrefab;

public void Update()
{
    ResolveAnchorOnRooftopPromise rooftopPromise =
        AnchorManager.ResolveAnchorOnRooftopAsync(
            latitude, longitude, altitudeAboveRooftop, eunRotation);

    // The anchor will need to be resolved.
    StartCoroutine(CheckRooftopPromise(rooftopPromise));
}

private IEnumerator CheckRooftopPromise(ResolveAnchorOnTerrainPromise promise)
{
    yield return promise;

    var result = promise.Result;
    if (result.RooftopAnchorState == RooftopAnchorState.Success &&
        result.Anchor != null)
    {
        // resolving anchor succeeded
        GameObject anchorGO = Instantiate(RooftopAnchorPrefab,
            result.Anchor.gameObject.transform);
        anchorGO.transform.parent = result.Anchor.gameObject.transform;
    }
    else
    {
       // resolving anchor failed
    }

    yield break;
}

وضعیت قول را بررسی کنید

Promise یک PromiseState مرتبط خواهد داشت، جدول بالا را ببینید.

وضعیت لنگر پشت بام نتیجه Promise را بررسی کنید

RooftopAnchorState متعلق به عملیات ناهمزمان است و بخشی از نتیجه نهایی Promise است.

switch (result.RooftopAnchorState)
{
    case TerrainAnchorState.Success:
        // Anchor has successfully resolved
        break;
    case RooftopAnchorState.ErrorUnsupportedLocation:
        // The requested anchor is in a location that isn't supported by the Geospatial API.
        break;
    case RooftopAnchorState.ErrorNotAuthorized:
        // An error occurred while authorizing your app with the ARCore API. See
        // https://developers.google.com/ar/reference/unity-arf/namespace/Google/XR/ARCoreExtensions#terrainanchorstate_errornotauthorized
        // for troubleshooting steps.
        break;
    case RooftopAnchorState.ErrorInternal:
        // The Rooftop anchor could not be resolved due to an internal error.
        break;
    default:
        break;
}

بعدش چی