Area Learning in Unity Unity中的区域学习

Unity How-to Guide: Area Learning

In this Area Learning How-to guide, you'll learn how to use a saved areadescription, create a new one, and extend existing ones. If you're not alreadyfamiliar with Area Learning, see the introduction.html

This guide makes extensive use of prefabs. If you want to learn more about them,see the Unity documentation.git

Unity教程指南:区域学习

在本区域学习操做指南中,您将学习如何使用已保存的商品,建立新商品,并扩展示有商品。 若是您还不熟悉区域学习,请参阅介绍。

本指南普遍使用预制件。 若是您想了解有关它们的更多信息,请参阅Unity文档。
github


Part 1: Using a saved area description

In this section, you'll learn how to use previously created area descriptionsin your application. Specifically, you'll be able to:api

  • Get a list of area descriptions.
  • Load a specific area description.
  • Set the Tango Delta Camera to use the area description.
  • Show the user an instruction related to relocalization.

If you don't have an area description on your device, or the most recent areadescription isn't of the area you're currently in, you'll need to create one.You can download the Tango Unity SDK, import theunitypackage file, and then build the example app "AreaLearning" located in theAssets > TangoSDK > Examples folder, or use any other application that cansave area descriptions. The ability to save area descriptions in your ownapplication is discussed later in this How-to guide.app

第1部分:使用保存的区域描述

在本节中,您将了解如何在应用程序中使用先前建立的区域描述。 具体来讲,您能够:

     获取区域描述列表。
     加载特定区域描述。
     设置Tango Delta相机以使用区域描述。
     向用户显示与重定位相关的指令。

若是您的设备上没有区域描述,或者最近的areadescription不是您当前所在的区域,您须要建立一个。您能够下载Tango Unity SDK,导入unitypackage文件, 而后构建位于Assets> TangoSDK> Examples文件夹中的示例应用程序“AreaLearning”,或使用任何其余能够保存区域描述的应用程序。 在您本身的应用程序中保存区域描述的能力将在本“操做指南”的后面部分中讨论。
框架


Preliminary steps

  1. If you haven't set up your computer to develop with Tango in Unity yet, see Getting Started With Unity.编辑器

  2. This guide builds on the Unity How-to guide for motion tracking. Go to that page and complete the steps found there, stopping just before the "Build and Run" section. When you have finished, return to this page and continue on with the steps below.ide

初步步骤

     若是您还没有在Unity中设置您的计算机与Tango一块儿开发,请参阅Unity入门。

     本指南基于用于运动跟踪的Unity How-to指南。 转到该页面并完成在那里找到的步骤,在“构建并运行”部分以前中止。 完成后,返回此页面,继续执行如下步骤。

函数

Tango Manager settings for saved area descriptions

  1. In the Hierarchy panel, click Tango Manager.
  2. In the Inspector panel, deselect Auto-connect to Service.oop

    When this option is selected, Tango Manager handles startup andinitialization automatically. This won't work for Area Learning because itrequires some custom settings. Keep this option turned off in Tango Manager;later in this How-to guide, you'll learn how to make your own "Area LearningStartup" to handle these settings.

            选择此选项时,Tango Manager会自动处理启动和初始化。 这将不适用于区域学习,由于它须要一些自定义设置。 在Tango Manager中关闭此选项;稍后在本“操做指南”中,您将学习如何制做本身的“区域学习启动”来处理这些设置。

  1. Select Enable Area Descriptions.

    This requests the Area Learning permission, which is required to load an areadescription or get the list of area descriptions on a device. After you selectEnable Area Descriptions, a secondary option appears called Mode, whichis set to Load Existing. Leave this as the active setting.

           这要求区域学习许可,这是装载一个地区或获取设备上的区域描述的列表所需的。 选择启用区域描述后,将显示一个辅助选项,称为“模式”,它设置为“加载现有”。 将此设置为活动设置。

Tango Delta Camera settings

By default, the Tango Delta Camera does not use area descriptions.

Tango Delta相机设置

默认状况下,Tango Delta相机不使用区域描述。

  1. In the Hierarchy panel, click Tango Delta Camera.
  2. In the Inspector panel, select Use Area Description Pose in the Tango Delta Pose Controller (Script) component.

    This lets you use the localized coordinates from the area description. 这容许您使用区域描述中的本地化坐标。

Create a startup gameObject   建立一个启动gameObject

  1. On the GameObject menu, click Create Empty.

  2. In the Inspector panel, change the name to "Startup."

Add a script to the startup gameObject   向启动gameObject添加脚本

  1. In the Inspector panel, click Add Component.

  2. In the Component menu, click New Script. (You may have to scroll down to see it.)

  3. In the New Script dialog, change the name to "AreaLearningStartup".

  4. Click Create and Add.

Add the code for the AreaLearningStartup script   添加AreaLearningStartup脚本的代码

  1. In the Area Learning Startup (Script) component, click the gear icon to view the context menu, and then select Edit Script.

  2. 在区域学习启动(脚本)组件中,单击齿轮图标以查看上下文菜单,而后选择编辑脚本。
  3. In the script editor, replace the existing script with the code below. To copy the code to the Clipboard, move the pointer over the code, and then in the upper right corner of the code section, click the Click to copy button.

  4. 在脚本编辑器中,将现有脚本替换为如下代码。 要将代码复制到剪贴板,请将指针移到代码上,而后在代码部分的右上角单击单击以复制按钮。

    using System.Collections; using UnityEngine; using Tango; public class AreaLearningStartup : MonoBehaviour, ITangoLifecycle {     private TangoApplication m_tangoApplication;     public void Start()     {         m_tangoApplication = FindObjectOfType<TangoApplication>();         if (m_tangoApplication != null)         {             m_tangoApplication.Register(this);             m_tangoApplication.RequestPermissions();         }     }     public void OnTangoPermissions(bool permissionsGranted)     {         if (permissionsGranted)         {             AreaDescription[] list = AreaDescription.GetList();             AreaDescription mostRecent = null;             AreaDescription.Metadata mostRecentMetadata = null;             if (list.Length > 0)             {                 // Find and load the most recent Area Description                 mostRecent = list[0];                 mostRecentMetadata = mostRecent.GetMetadata();                 foreach (AreaDescription areaDescription in list)                 {                     AreaDescription.Metadata metadata = areaDescription.GetMetadata();                     if (metadata.m_dateTime > mostRecentMetadata.m_dateTime)                     {                         mostRecent = areaDescription;                         mostRecentMetadata = metadata;                     }                 }                 m_tangoApplication.Startup(mostRecent);             }             else             {                 // No Area Descriptions available.                 Debug.Log("No area descriptions available.");             }         }     }     public void OnTangoServiceConnected()     {     }     public void OnTangoServiceDisconnected()     {     } } 

Code details

As described earlier, you must manually control the startup process of theTangoApplication component on the Tango Manager gameObject.

In the AreaLearningStartup class, you declare a TangoApplication object:

代码详细信息

如前所述,您必须在Tango Manager gameObject上手动控制TangoApplication组件的启动过程。

在AreaLearningStartup类中,您声明一个TangoApplication对象:


private TangoApplication m_tangoApplication; 

In the Start() method, you initialize m_tangoApplication to refer to theTangoApplication in the scene:

在Start()方法中,您初始化m_tangoApplication以引用场景中的TangoApplication:


public void Start() {     m_tangoApplication = FindObjectOfType<TangoApplication>(); 

To load an area description file, you must specify it when connecting to Tango.A common way to do this is by showing a list of all area descriptions on thedevice for the user to choose from. However, you can only query the list of areadescriptions after you are granted the Area Learning permission. Therefore, youmust manually control the startup process by explicitly calling theRequestPermissions() and Startup() methods on the TangoApplicationcomponent on the Tango Manager gameObject.

Register to receive callbacks, and request permissions:

要加载区域描述文件,必须在链接到Tango时指定。常见的方法是显示设备上全部区域描述的列表供用户选择。 可是,在授予区域学习权限后,您只能查询areadescriptions列表。 所以,您必须经过在Tango Manager gameObject上的TangoApplicationcomponent上显式调用RequestRequestPermissions()和Startup()方法来手动控制启动过程。

注册以接收回调,并请求权限:


if (m_tangoApplication != null) {     m_tangoApplication.Register(this);     m_tangoApplication.RequestPermissions(); } 

After permissions are granted, OnTangoPermissions() is called and you can getthe list of area descriptions and then connect to a specified area description.For simplicity, this example uses the most recent area description:

授予权限后,调用OnTangoPermissions(),您能够获取区域描述列表,而后链接到指定的区域描述。为了简单起见,本示例使用最新的区域描述:

if (permissionsGranted) {     AreaDescription[] list = AreaDescription.GetList();     AreaDescription mostRecent = null;     AreaDescription.Metadata mostRecentMetadata = null;     if (list.Length > 0)     {         // Find and load the most recent Area Description         mostRecent = list[0];         mostRecentMetadata = mostRecent.GetMetadata();         foreach (AreaDescription areaDescription in list)         {             AreaDescription.Metadata metadata = areaDescription.GetMetadata();             if (metadata.m_dateTime > mostRecentMetadata.m_dateTime)             {                 mostRecent = areaDescription;                 mostRecentMetadata = metadata;             }         } 

You connect to Tango and pass the most recent area description:

您链接到探戈并经过最新的区域描述:

m_tangoApplication.Startup(mostRecent); 

For your application, you will need to implement more functionality in theOnTangoPermissions function. In this example, we always pick the most recentarea description and only write a log if there are no visible area descriptions.For your application, you should implement your own logic for choosing an areadescription and handling the case where there is no area description available.

When you have finished examining the script, save it, and then return to theUnity Editor.

对于您的应用程序,您须要在OnTangoPermissions函数中实现更多的功能。 在这个例子中,咱们老是选择最近的区域描述,而且只有在没有可见区域描述时才写一个日志。对于你的应用程序,你应该实现本身的逻辑来选择一个区域描述,并处理没有区域描述的状况。

当您完成检查脚本,保存它,而后返回到统一编辑器。


Create an instruction screen

Before localization happens, the application gets no motion updates. To improvethe user experience, you can instruct the user to walk around until they havelocalized.

建立指令屏幕

在本地化以前,应用程序没有运动更新。 为了改善用户体验,您能够指示用户走动,直到他们定位。

  1. In the Hierarchy panel, select Create > UI > Canvas.

  2. In the Hierarchy panel, right-click Canvas and then select UI > Image.

  3. In the Project panel, navigate to the Assets > TangoSDK > Examples > Common > Textures folder. It should contain a texture called relocalize_screen. You can also download this texture from our Unity examples.

  4. In the Hierarchy panel, click Image.

  5. In the Image (Script) component of the Image gameObject, there is a field named Source Image. Drag the relocalize_screen texture to the Source Image field.

  6. To ensure the texture displays correctly, click Set Native Size.

Listen for localization and show the instruction  听取本地化并显示指令

  1. In the Project panel, navigate to the Assets > TangoSDK > Examples > AreaLearning > Scripts folder. It should contain a script called RelocalizingOverlay.

  2. In the Hierarchy panel, click Tango Manager.

  3. Drag the RelocalizingOverlay script to a blank space in the Tango Manager's Inspector panel.

  4. 将RelocalizingOverlay脚本拖动到Tango管理器的“检查器”面板中的空白处。

  5. In the Relocalizing Overlay (Script) component you just created, there is a field named Relocalization Overlay. Drag the Image gameObject from the Hierarchy panel to the Relocalization Overlay field.

  6. 在刚刚建立的Relocalizing Overlay(Script)组件中,有一个名为Relocalization Overlay的字段。 将图像gameObject从“层次”面板拖动到“重定位覆盖”字段。

Build and run your project  构建并运行您的项目

  1. On the File menu, click Build and Run.

  2. In the Build Settings dialog, click Build and Run.

  3. In the Build Android dialog, enter a name for your app in the Save As field, and then click Save.

Your application loads the most recent area description and shows a screeninstructing you to walk around until relocalization occurs. After that happens,the instruction screen disappears and you can walk around and view the plane,cube, and sphere where you placed them in the scene. The app uses the areadescription's coordinate frame while handling camera movement.

您的应用程序加载最近的区域描述,并显示一个屏幕,您能够走动,直到从新定位。 以后,指令屏幕消失,您能够四处走动,查看您将场景放置在其中的平面,立方体和球体。 该应用程序使用areadescription的坐标框架,同时处理相机移动。

Part 2: Create and extend area descriptions  第2部分:建立和扩展区域描述

In this section, you'll learn how to use Area Learning mode to create new areadescriptions or extend existing ones. It builds on the steps you've followedthus far in this How-to guide.

在本节中,您将学习如何使用区域学习模式建立新的areadescriptions或扩展示有的。 它创建在您在此“操做指南”中遵循的步骤。

Tango Manager settings for new area descriptions  新区域描述的Tango经理设置

  1. In the Hierarchy panel, click Tango Manager.  

  2. 在“层次结构”面板中,单击“探戈管理器”。

  3. In the Inspector panel, beneath Enable Area Descriptions, click the field to the right of Mode, and then click Learning.

    Keep in mind that in learning mode, your app selects key features in eachincoming image and memorizes them to give you the benefits of driftcorrection and localization. This requires much more computational powerthan loading an area description file. You should restrict Learning modeto a separate setup mode in your application and use Load Existing modeduring your main experience.

    In Learning mode, you can use the same startup script as Load Existing modewith one key difference in the behavior of m_tangoApplication.Startup().In Learning mode, calling m_tangoApplication.Startup(null) is valid, andtriggers the creation of a new area description.

  4. 在“检查器”面板中的“启用区域描述”下,单击“模式”右侧的字段,而后单击“学习”。

    请记住,在学习模式下,您的应用程序选择每一个新的图像中的关键功能,并记住它们,为您带来漂移校订和本地化的好处。 这须要比加载区域描述文件多得多的计算能力。 您应该将学习模式限制为应用程序中的单独设置模式,并使用加载现有模式您的主要体验。

    在学习模式下,您可使用与加载现有模式相同的启动脚本在m_tangoApplication.Startup()的行为中的一个主要区别在学习模式下,调用m_tangoApplication.Startup(null)是有效的,而且触发建立一个新的区域描述

  5. In the AreaLearningStartup script (attached to the Startup gameObject), replace the line:

  6. 在AreaLearningStartup脚本(附加到Startup gameObject)中,替换如下行:

    Debug.Log("No area descriptions available."); 

    with:

    m_tangoApplication.Startup(null); 

    Your application will load the most recent area description if present, orcreate a new area description if none exist on the device.

  7. 您的应用程序将加载最近的区域描述(若是存在),或者若是设备上没有描述,则建立新的区域描述。
Note: When you load an existing area description in learning mode, this iscalled "extending" an area description because you're accumulating new areadescription features on top of the existing area description.
注意:当您在学习模式下加载现有区域描述时,这将被称为“扩展”区域描述,由于您正在现有区域描述的上方累积新的区域描述。

Save an area description  保存区域描述

Note: The rest of this How-to guide is not meant to be copy/pasted directly.

In Learning mode, you can save the area description that was learned bycalling AreaDescription.SaveCurrent() in a place that makes sense for yourown application. Saving an area description can take a few minutes, so be sureto save in a background thread.

While the save is running, TangoEvent notification callbacks are sent thatdescribe the save progress. You can listen for these callbacks by implementingthe ITangoEventinterface and listening to AreaDescriptionSaveProgress events. In the snippetbelow, we update a GUIText m_savingText with the save progress as apercentage. You'll need to create your own implementation to match your UI.

注意:本操做指南的其他部分不是直接复制/粘贴。

在学习模式下,您能够保存经过调用AreaDescription.SaveCurrent()在一个对yourown应用程序有意义的地方学习的区域描述。 保存区域描述可能须要几分钟,所以请务必保存在后台线程中。

当保存正在运行时,发送描述保存进度的TangoEvent通知回调。 您能够经过实现ITangoEventinterface并侦听AreaDescriptionSaveProgress事件来侦听这些回调。 在下面的代码段中,咱们将保存进度更新为GUIText m_savingText为apercentage。 您须要建立本身的实现来匹配您的UI。

public void OnTangoEventAvailableEventHandler(Tango.TangoEvent tangoEvent) {     if (tangoEvent.type == TangoEnums.TangoEventType.TANGO_EVENT_AREA_LEARNING         && tangoEvent.event_key == "AreaDescriptionSaveProgress")     {         m_savingText.text = "Saving. " + (float.Parse(tangoEvent.event_value) * 100) + "%";     } } 

You can also see saving progress implemented in our Area Learningsample.

Note: A new file with a new UUID is created when saving both new areadescriptions and extended area descriptions.
您还能够查看在咱们的区域了解示例中实现的保存进度。
注意:当保存新的地图项和扩展区域描述时,将建立具备新UUID的新文件。

Relocalizing   从新定位

When you relocalize, small errors that have been accumulated arecorrected,including errors in the past. You can use this to correct not only the device'slocation, but also objects that were placed relative to the device, even backin time.

The augmented reality sampledoes this. The sample lets you drop virtual markers into the real world. Everytime amarkeris dropped, the sample also stores the timestamp when you placed the marker andthe transformation from the device to the placed marker. When you relocalize,the sample goes through the list of objects, asks for the (now corrected) devicepose for each timestamp, and updates the object's location using the new devicepose and stored transformation.

The code snippet below from ouraugmented reality sampleshows one implementation. Note that it relies on the ARMarker class's membervariables to keep the timestamp and pose.

当您从新定位时,已经累积的小错误被纠正,包括过去的错误。 您可使用它来更正设备的位置,还能够更正相对于设备放置的对象,甚至是回溯时间。

加强现实对此进行了抽样。 该示例容许您将虚拟标记放入现实世界中。 每次amarkeris放弃,样本还存储时间戳,当您放置标记和从设备到放置的标记的转换。 当从新定位时,样本将经过对象列表,请求每一个时间戳的(如今更正的)设备,并使用新的设备和存储的转换更新对象的位置。

下面的代码片断显示了一个实现。 注意,它依赖于ARMarker类的成员变量来保持时间戳和姿态。

public void OnTangoPoseAvailable(Tango.TangoPoseData poseData) {     if (poseData.framePair.baseFrame ==         TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_AREA_DESCRIPTION &&         poseData.framePair.targetFrame ==         TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_START_OF_SERVICE &&         poseData.status_code == TangoEnums.TangoPoseStatusType.TANGO_POSE_VALID)     {         // Adjust mark's position each time a loop closure is detected.         foreach (GameObject obj in m_markerList)         {             ARMarker tempMarker = obj.GetComponent<ARMarker>();             if (tempMarker.m_timestamp != -1.0f)             {                 TangoCoordinateFramePair pair;                 TangoPoseData relocalizedPose = new TangoPoseData();                 pair.baseFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_AREA_DESCRIPTION;                 pair.targetFrame = TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_DEVICE;                 PoseProvider.GetPoseAtTime(relocalizedPose, tempMarker.m_timestamp, pair);                 Vector3 pDevice = new Vector3((float)relocalizedPose.translation[0],                                               (float)relocalizedPose.translation[1],                                               (float)relocalizedPose.translation[2]);                 Quaternion qDevice = new Quaternion((float)relocalizedPose.orientation[0],                                                     (float)relocalizedPose.orientation[1],                                                     (float)relocalizedPose.orientation[2],                                                     (float)relocalizedPose.orientation[3]);                 Matrix4x4 uwTDevice = m_uwTss * Matrix4x4.TRS(pDevice, qDevice, Vector3.one) * m_dTuc;                 Matrix4x4 uwTMarker = uwTDevice * tempMarker.m_deviceTMarker;                 obj.transform.position = uwTMarker.GetColumn(3);                 obj.transform.rotation = Quaternion.LookRotation(uwTMarker.GetColumn(2), uwTMarker.GetColumn(1));             }         }     } }