這兩年虛擬現實VR和增強現實AR簡直火的不要不要的,衆多巨頭都在發力,Google也推出了自己的AR技術解決方案,因爲目前介紹Tango的中文資料還比較少,所以本人結合官網文檔和自己的理解寫了本文,如有錯漏請不吝賜教。
一、簡介
1. Tango是什麼,可以用來幹什麼?
Tango是Google的一個AR增強現實項目,配合其獨特的移動設備和SDK可以方便的在應用中使用AR技術。
2. Tango室內定位爲什麼有很高的精確度?
衆所周知,傳統的定位技術(GPS\WIFI等)在室內定位上精度很低,那麼Tango是怎麼實現室內定位的呢?
Tango採用的是“參照定位”,即相對於“初始位置”的一種定位方式,不涉及到衛星定位。它根據硬件設備的傳感器,比如重力傳感器、IMU陀螺儀等,獲取移動設備相對於初始位置的“位移”和“旋轉角度”,自己構建了一個“參照座標系”,因此有較高的準確度。
當然,還有其他一些軟件技術手段,比如通過區域學習修正偏差等。
3. 幾個重要的概念
Tango中如下3個概念,其實也算是3個功能模塊。開發者通過設置TangoConfig對象的相應字段來選擇開啓哪些功能。
a. 移動追蹤(motion tracking)
移動追蹤指的是,Tango會記錄追蹤移動設備的在3D空間中的位置,位置數據包括地點和超像旋轉角度等、實時報告給應用。
b. 區域學習(Area Leaning)
移動追蹤只會反饋移動設備當前的座標信息、對於設備“看”到的東西沒有任何記憶,區域學習使移動設備能夠看到和記住物理空間的關鍵視覺特徵,比如邊緣,角落等。
區域學習會把看到的保存起來,下次再次“看”到的時候會進行匹配,利用這些數據修正誤差(漂移修正),使得軌跡追蹤、定位更加準確。
c. 深度感知(Depth Perception)
深度感知給予設備“明白”物體之間的距離,這是通過獨特的硬件設備技術實現的,比如“結構光”、“光速飛行時間TOF”和Stereo立體測量
4. Tango的簡單使用方式
在Android中,Tango是一個後臺Sevice,負責AR工作。我們使用Tango的方式就是啓動這個Service,與其進行交互。
Tango主要有如下兩個對象:
private Tango mTango; //Tnago對象
private TangoConfig mConfig; //配置
按照需求對TangoConfig類進行配置,下面代碼配置了移動追蹤和自動恢復
private TangoConfig setupTangoConfig(Tango tango) {
TangoConfig config = tango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
//開啓移動追蹤功能
config.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING, true);
// 自動恢復
config.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY, true);
return config;
}
初始化Tango,調用它的connect()方法。
@Override
protected void onResume() {
super.onResume();
mTango = new Tango(HelloMotionTrackingActivity.this, new Runnable() {
@Override
public void run() {
synchronized (HelloMotionTrackingActivity.this) {
mConfig = setupTangoConfig(mTango);
mTango.connect(mConfig);
startupTango(); //處理數據
}
}
});
}
通過回調處理數據,上一步中處理數據的方法是startupTango(),其源碼如下
private void startupTango() {
//設置座標參照系
final ArrayList<TangoCoordinateFramePair> framePairs =
new ArrayList<TangoCoordinateFramePair>();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE));
// 通過回調獲取和處理座標數據
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
@Override
public void onPoseAvailable(final TangoPoseData pose) {
//在這裏寫處理移動追蹤和區域學習數據的代碼
}
@Override
public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
// We are not using onXyzIjAvailable for this app.
}
@Override
public void onPointCloudAvailable(TangoPointCloudData pointCloud) {
// 如果開啓深度感知,則在這裏處理點陣信息
}
@Override
public void onTangoEvent(final TangoEvent event) {
//在這裏處理各種事件,比如魚眼攝像頭出問題,pose數據失效事件等
}
@Override
public void onFrameAvailable(int cameraId) {
// We are not using onFrameAvailable for this application.
}
});
}
應用不在前臺的時候,斷開和Tango的連接(官網推薦的用法)
@Override
protected void onPause() {
super.onPause();
synchronized (this) {
mTango.disconnect();
}
}
二、開發者必備
1. 學習資料
- 官網:https://developers.google.com/tango/
- 開發者社區:https://plus.google.com/communities/114537896428695886568
- 官網的demo:https://github.com/googlesamples/tango-examples-java
- sdk源碼:官方demo中有個jar包,名字是tango_java_lib.jar
- 官網API:https://developers.google.com/tango/apis/overview
2. 開發方式
開發方式 | 軟件需求 | 設備 |
---|---|---|
Java Android | Android Studio、 TangoReleaseLibs(Tango SDK) | Tango Device |
Unity Android | Unity 5.2.1以上(配置好Android開發環境)、Tango Unity SDK | Tango Device |
注:Android API版本 只支持 API Level 17 及以上,Tango Device是必須的,沒有其獨特的感應設備,Tango沒辦法正常工作。
三、移動追蹤(motion tracking)
1. Tango的座標數據——pose
pose是Tango中的座標表示,其具體的Java對象是TangoPoseData,其包含了兩個信息:三維座標、物體的朝向,其結構如下:
struct PoseData {
double orientation[4]; //朝向信息,四元數表示
double translation[3]; //三維座標信息
}
三維座標系可以用下圖表示,當我們正常站立手持移動設備面向自己的臉部時,X軸的正方向是向右的。
朝向信息,也可以說成旋轉信息,如下圖理解,三個方向上的旋轉,用四元數表示(這個我不太懂,三個旋轉用四元數表示好像是爲了方便計算,具體請百度)。
2. pose的生命週期
pose數據是有可能失效的,比如魚眼攝像頭髮生了錯誤導致出錯等。下圖 是pose數據的狀態轉換圖。
3. 應用獲取和處理pose數據
private void startupTango() {
// 設置座標參照系
final ArrayList<TangoCoordinateFramePair> framePairs =
new ArrayList<TangoCoordinateFramePair>();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE));
// 在回調中獲取座標信息
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
@Override
public void onPoseAvailable(final TangoPoseData pose) {
logPose(pose);
}
});
}
/**
* 打印座標信息
*/
private void logPose(TangoPoseData pose) {
StringBuilder stringBuilder = new StringBuilder();
float translation[] = pose.getTranslationAsFloats();
stringBuilder.append("Position: " +
translation[0] + ", " + translation[1] + ", " + translation[2]);
float orientation[] = pose.getRotationAsFloats();
stringBuilder.append(". Orientation: " +
orientation[0] + ", " + orientation[1] + ", " +
orientation[2] + ", " + orientation[3]);
Log.i(TAG, stringBuilder.toString());
}
四、區域學習(Area Leaning)
1. ADF文件
區域學習將設備“看到的信息”保存成ADF(Area Description File)文件,採用UUID進行唯一標識。ADF文件算是一種持久化的數據,可以重複利用。
ADF文件實際上是一種鍵值對的文件形式,它其中保存了區域學習記錄的信息,但是這些空間信息不需要也不允許開發者進行修改,其他官網公開的屬性有如下幾個:
鍵值 | 解釋 |
---|---|
KEY_UUID | UUID唯一標識 |
KEY_NAME | 文件的name |
KEY_TRANSFORMATION | ADF到全局座標的一個轉換 (x, y, z, qx, qy, qz, qw) |
KEY_DATE_MS_SINCE_EPOCH | ADF文件保存的時間 |
此外,我們也可以加入一些自己定義的鍵值對信息。
2. 區域重定位(區域匹配)
如果載入使用以前的ADF文件,要實現正常的功能,必須進行一個重定位過程,用戶要手持設備走到現實中與載入的ADF匹配的地域,tango會將環境信息和ADF文件信息做匹配,匹配成功了即意味着“重定位”成功。
區域匹配是有可能失敗的,Tango的區域匹配成功率與環境的“多樣性”有關,如果環境很空曠,或者各個房間都是一模一樣的,那麼區域學習和匹配陳功率較低。如果環境中有各式各樣的物品,那麼成功率較高。
3. 加載和使用ADF文件示例
開啓區域學習
TangoConfig mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_LEARNINGMODE, true);
加載特定UUID標識的ADF文件
mConfig.putString(TangoConfig.KEY_STRING_AREADESCRIPTION, uuid);
獲取最近所有的ADF文件
ArrayList<String> fullUUIDList = new ArrayList<String>();
fullUUIDList = mTango.listAreaDescriptions();
保存當前的ADF文件,這個可能很耗時,不要在UI線程做(官方提供了SaveAdfTask來做這件事)。
Tango.saveAreaDescription()
在回調中處理區域學習的位置數據,因爲文章開頭有講述,其他步驟省略了。
@Override
public void onPoseAvailable(TangoPoseData pose) {
if (pose.baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& pose.targetFrame == TangoPoseData.COORDINATE_FRAME_DEVICE) {
// 這個條件意味着移動設備到了一個新的位置
}
else if (pose.baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& pose.targetFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE) {
// 這個條件告訴我們,設備回到了ADF文件區域的開始位置,也意味着重定位過程成功。
//開發者可以視其爲重定位成功的信號
}
五、深度感知(Depth Perception)
深度感知目前爲平衡對設備和處理器的要求,理想的掃描距離爲0.5米到4米之間,近距離物品掃描和手勢檢測並不完美。對於採用紅外光技術的深度感知設備,在如下兩種情況有可能工作不正常:
- 環境中紅外光在光源中佔據較高比例,比如陽光和白熾燈照射的區域
- 不反射紅外光的物品難以被正常掃描
深度感知的工作原理就是掃描攝像頭照射的區域,對照射到的物品計算其空間位置,給出一大堆三維點陣的信息(point cloud)
深度感知仍舊在回調裏面編寫獲取數據的方法,回調中不能做耗時操作,如果上次回調沒有完成,因爲你無法獲取最新的數據。
@Override
public void onPointCloudAvailable(final TangoPointCloudData pointCloudData) {
//在這裏處理點陣數據
}
六、 總結
1. Tango功能總結
功能 | 數據表示 | 對應的數據類 | 用途 |
---|---|---|---|
移動追蹤 | 三維座標信息和物體的朝向信息 | TangoPoseData | 檢測移動設備的位置和朝向 |
區域學習 | ADF文件 | TangoAreaDescriptionMetaData | 提高移動追蹤的準確度、記憶空間信息(做室內導航) |
深度學習 | 點陣信息(一大堆三維座標集合) | TangoPointCloudData | 掃描建模 |
2. 如何利用它開發AR應用
如果你理解了AR的本質,那麼你會發現Tango已經提供了實現AR的一切條件,設備自身的位置朝向信息,以及周圍的環境信息。應用能得到這些數據,那麼做AR就沒有問題。
如果你想開發3D AR應用,那麼應該採用 Unity +Tango的開發方式,因爲Tango本身並不提供3D渲染的功能。
如果覺得本文對你有幫助,請關注、留言、點贊,相互分享才能持續進步!