這兩年虛擬現(xiàn)實VR和增強現(xiàn)實AR簡直火的不要不要的,眾多巨頭都在發(fā)力掩完,Google也推出了自己的AR技術(shù)解決方案,因為目前介紹Tango的中文資料還比較少,所以本人結(jié)合官網(wǎng)文檔和自己的理解寫了本文框产,如有錯漏請不吝賜教。
一错洁、簡介
1. Tango是什么茅信,可以用來干什么?
Tango是Google的一個AR增強現(xiàn)實項目墓臭,配合其獨特的移動設(shè)備和SDK可以方便的在應(yīng)用中使用AR技術(shù)。
2. Tango室內(nèi)定位為什么有很高的精確度妖谴?
眾所周知窿锉,傳統(tǒng)的定位技術(shù)(GPS\\WIFI等)在室內(nèi)定位上精度很低酌摇,那么Tango是怎么實現(xiàn)室內(nèi)定位的呢?
Tango采用的是“參照定位”嗡载,即相對于“初始位置”的一種定位方式窑多,不涉及到衛(wèi)星定位。它根據(jù)硬件設(shè)備的傳感器洼滚,比如重力傳感器埂息、IMU陀螺儀等,獲取移動設(shè)備相對于初始位置的“位移”和“旋轉(zhuǎn)角度”遥巴,自己構(gòu)建了一個“參照坐標(biāo)系”千康,因此有較高的準(zhǔn)確度。
當(dāng)然铲掐,還有其他一些軟件技術(shù)手段拾弃,比如通過區(qū)域?qū)W習(xí)修正偏差等。
3. 幾個重要的概念
Tango中如下3個概念摆霉,其實也算是3個功能模塊豪椿。開發(fā)者通過設(shè)置TangoConfig對象的相應(yīng)字段來選擇開啟哪些功能。
a. 移動追蹤(motion tracking)
移動追蹤指的是携栋,Tango會記錄追蹤移動設(shè)備的在3D空間中的位置搭盾,位置數(shù)據(jù)包括地點和超像旋轉(zhuǎn)角度等、實時報告給應(yīng)用婉支。
b. 區(qū)域?qū)W習(xí)(Area Leaning)
移動追蹤只會反饋移動設(shè)備當(dāng)前的坐標(biāo)信息鸯隅、對于設(shè)備“看”到的東西沒有任何記憶,區(qū)域?qū)W習(xí)使移動設(shè)備能夠看到和記住物理空間的關(guān)鍵視覺特征磅摹,比如邊緣滋迈,角落等。
區(qū)域?qū)W習(xí)會把看到的保存起來户誓,下次再次“看”到的時候會進(jìn)行匹配饼灿,利用這些數(shù)據(jù)修正誤差(漂移修正),使得軌跡追蹤帝美、定位更加準(zhǔn)確碍彭。
c. 深度感知(Depth Perception)
深度感知給予設(shè)備“明白”物體之間的距離,這是通過獨特的硬件設(shè)備技術(shù)實現(xiàn)的悼潭,比如“結(jié)構(gòu)光”庇忌、“光速飛行時間TOF”和Stereo立體測量
4. Tango的簡單使用方式
在Android中,Tango是一個后臺Sevice舰褪,負(fù)責(zé)AR工作皆疹。我們使用Tango的方式就是啟動這個Service,與其進(jìn)行交互占拍。
Tango主要有如下兩個對象:
private Tango mTango; //Tnago對象
private TangoConfig mConfig; //配置
按照需求對TangoConfig類進(jìn)行配置略就,下面代碼配置了移動追蹤和自動恢復(fù)
private TangoConfig setupTangoConfig(Tango tango) {
TangoConfig config = tango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
//開啟移動追蹤功能
config.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING, true);
// 自動恢復(fù)
config.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY, true);
return config;
}
初始化Tango捎迫,調(diào)用它的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(); //處理數(shù)據(jù)
}
}
});
}
通過回調(diào)處理數(shù)據(jù)表牢,上一步中處理數(shù)據(jù)的方法是startupTango()窄绒,其源碼如下
private void startupTango() {
//設(shè)置坐標(biāo)參照系
final ArrayList<TangoCoordinateFramePair> framePairs =
new ArrayList<TangoCoordinateFramePair>();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE));
// 通過回調(diào)獲取和處理坐標(biāo)數(shù)據(jù)
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
@Override
public void onPoseAvailable(final TangoPoseData pose) {
//在這里寫處理移動追蹤和區(qū)域?qū)W習(xí)數(shù)據(jù)的代碼
}
@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數(shù)據(jù)失效事件等
}
@Override
public void onFrameAvailable(int cameraId) {
// We are not using onFrameAvailable for this application.
}
});
}
應(yīng)用不在前臺的時候,斷開和Tango的連接(官網(wǎng)推薦的用法)
@Override
protected void onPause() {
super.onPause();
synchronized (this) {
mTango.disconnect();
}
}
二敲茄、開發(fā)者必備
1. 學(xué)習(xí)資料
- 官網(wǎng):https://developers.google.com/tango/
- 開發(fā)者社區(qū):https://plus.google.com/communities/114537896428695886568
- 官網(wǎng)的demo:https://github.com/googlesamples/tango-examples-java
- sdk源碼:官方demo中有個jar包位谋,名字是tango_java_lib.jar
- 官網(wǎng)API:https://developers.google.com/tango/apis/overview
2. 開發(fā)方式
開發(fā)方式 | 軟件需求 | 設(shè)備 |
---|---|---|
Java Android | Android Studio、 TangoReleaseLibs(Tango SDK) | Tango Device |
Unity Android | Unity 5.2.1以上(配置好Android開發(fā)環(huán)境)折汞、Tango Unity SDK | Tango Device |
注:Android API版本 只支持 API Level 17 及以上倔幼,Tango Device是必須的,沒有其獨特的感應(yīng)設(shè)備爽待,Tango沒辦法正常工作损同。
三、移動追蹤(motion tracking)
1. Tango的坐標(biāo)數(shù)據(jù)——pose
pose是Tango中的坐標(biāo)表示鸟款,其具體的Java對象是TangoPoseData膏燃,其包含了兩個信息:三維坐標(biāo)、物體的朝向何什,其結(jié)構(gòu)如下:
struct PoseData {
double orientation[4]; //朝向信息组哩,四元數(shù)表示
double translation[3]; //三維坐標(biāo)信息
}
三維坐標(biāo)系可以用下圖表示,當(dāng)我們正常站立手持移動設(shè)備面向自己的臉部時处渣,X軸的正方向是向右的伶贰。
朝向信息,也可以說成旋轉(zhuǎn)信息罐栈,如下圖理解黍衙,三個方向上的旋轉(zhuǎn),用四元數(shù)表示(這個我不太懂荠诬,三個旋轉(zhuǎn)用四元數(shù)表示好像是為了方便計算琅翻,具體請百度)。
2. pose的生命周期
pose數(shù)據(jù)是有可能失效的柑贞,比如魚眼攝像頭發(fā)生了錯誤導(dǎo)致出錯等方椎。下圖 是pose數(shù)據(jù)的狀態(tài)轉(zhuǎn)換圖。
3. 應(yīng)用獲取和處理pose數(shù)據(jù)
private void startupTango() {
// 設(shè)置坐標(biāo)參照系
final ArrayList<TangoCoordinateFramePair> framePairs =
new ArrayList<TangoCoordinateFramePair>();
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE));
// 在回調(diào)中獲取坐標(biāo)信息
mTango.connectListener(framePairs, new OnTangoUpdateListener() {
@Override
public void onPoseAvailable(final TangoPoseData pose) {
logPose(pose);
}
});
}
/**
* 打印坐標(biāo)信息
*/
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());
}
四钧嘶、區(qū)域?qū)W習(xí)(Area Leaning)
1. ADF文件
區(qū)域?qū)W習(xí)將設(shè)備“看到的信息”保存成ADF(Area Description File)文件棠众,采用UUID進(jìn)行唯一標(biāo)識。ADF文件算是一種持久化的數(shù)據(jù)有决,可以重復(fù)利用摄欲。
ADF文件實際上是一種鍵值對的文件形式轿亮,它其中保存了區(qū)域?qū)W習(xí)記錄的信息,但是這些空間信息不需要也不允許開發(fā)者進(jìn)行修改胸墙,其他官網(wǎng)公開的屬性有如下幾個:
鍵值 | 解釋 |
---|---|
KEY_UUID | UUID唯一標(biāo)識 |
KEY_NAME | 文件的name |
KEY_TRANSFORMATION | ADF到全局坐標(biāo)的一個轉(zhuǎn)換 (x, y, z, qx, qy, qz, qw) |
KEY_DATE_MS_SINCE_EPOCH | ADF文件保存的時間 |
此外,我們也可以加入一些自己定義的鍵值對信息按咒。
2. 區(qū)域重定位(區(qū)域匹配)
如果載入使用以前的ADF文件迟隅,要實現(xiàn)正常的功能,必須進(jìn)行一個重定位過程励七,用戶要手持設(shè)備走到現(xiàn)實中與載入的ADF匹配的地域智袭,tango會將環(huán)境信息和ADF文件信息做匹配,匹配成功了即意味著“重定位”成功掠抬。
區(qū)域匹配是有可能失敗的吼野,Tango的區(qū)域匹配成功率與環(huán)境的“多樣性”有關(guān),如果環(huán)境很空曠两波,或者各個房間都是一模一樣的瞳步,那么區(qū)域?qū)W習(xí)和匹配陳功率較低。如果環(huán)境中有各式各樣的物品腰奋,那么成功率較高奏窑。
3. 加載和使用ADF文件示例
開啟區(qū)域?qū)W習(xí)
TangoConfig mConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
mConfig.putBoolean(TangoConfig.KEY_BOOLEAN_LEARNINGMODE, true);
加載特定UUID標(biāo)識的ADF文件
mConfig.putString(TangoConfig.KEY_STRING_AREADESCRIPTION, uuid);
獲取最近所有的ADF文件
ArrayList<String> fullUUIDList = new ArrayList<String>();
fullUUIDList = mTango.listAreaDescriptions();
保存當(dāng)前的ADF文件轿腺,這個可能很耗時,不要在UI線程做(官方提供了SaveAdfTask來做這件事)。
Tango.saveAreaDescription()
在回調(diào)中處理區(qū)域?qū)W習(xí)的位置數(shù)據(jù)扁凛,因為文章開頭有講述,其他步驟省略了蔚润。
@Override
public void onPoseAvailable(TangoPoseData pose) {
if (pose.baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& pose.targetFrame == TangoPoseData.COORDINATE_FRAME_DEVICE) {
// 這個條件意味著移動設(shè)備到了一個新的位置
}
else if (pose.baseFrame == TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION
&& pose.targetFrame == TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE) {
// 這個條件告訴我們训貌,設(shè)備回到了ADF文件區(qū)域的開始位置,也意味著重定位過程成功康二。
//開發(fā)者可以視其為重定位成功的信號
}
五碳胳、深度感知(Depth Perception)
深度感知目前為平衡對設(shè)備和處理器的要求,理想的掃描距離為0.5米到4米之間赠摇,近距離物品掃描和手勢檢測并不完美固逗。對于采用紅外光技術(shù)的深度感知設(shè)備,在如下兩種情況有可能工作不正常:
- 環(huán)境中紅外光在光源中占據(jù)較高比例藕帜,比如陽光和白熾燈照射的區(qū)域
- 不反射紅外光的物品難以被正常掃描
深度感知的工作原理就是掃描攝像頭照射的區(qū)域烫罩,對照射到的物品計算其空間位置,給出一大堆三維點陣的信息(point cloud)
深度感知仍舊在回調(diào)里面編寫獲取數(shù)據(jù)的方法洽故,回調(diào)中不能做耗時操作贝攒,如果上次回調(diào)沒有完成,因為你無法獲取最新的數(shù)據(jù)时甚。
@Override
public void onPointCloudAvailable(final TangoPointCloudData pointCloudData) {
//在這里處理點陣數(shù)據(jù)
}
六隘弊、 總結(jié)
1. Tango功能總結(jié)
功能 | 數(shù)據(jù)表示 | 對應(yīng)的數(shù)據(jù)類 | 用途 |
---|---|---|---|
移動追蹤 | 三維坐標(biāo)信息和物體的朝向信息 | TangoPoseData | 檢測移動設(shè)備的位置和朝向 |
區(qū)域?qū)W習(xí) | ADF文件 | TangoAreaDescriptionMetaData | 提高移動追蹤的準(zhǔn)確度哈踱、記憶空間信息(做室內(nèi)導(dǎo)航) |
深度學(xué)習(xí) | 點陣信息(一大堆三維坐標(biāo)集合) | TangoPointCloudData | 掃描建模 |
2. 如何利用它開發(fā)AR應(yīng)用
如果你理解了AR的本質(zhì),那么你會發(fā)現(xiàn)Tango已經(jīng)提供了實現(xiàn)AR的一切條件梨熙,設(shè)備自身的位置朝向信息开镣,以及周圍的環(huán)境信息。應(yīng)用能得到這些數(shù)據(jù)咽扇,那么做AR就沒有問題邪财。
如果你想開發(fā)3D AR應(yīng)用,那么應(yīng)該采用 Unity +Tango的開發(fā)方式质欲,因為Tango本身并不提供3D渲染的功能树埠。
如果覺得本文對你有幫助,請關(guān)注嘶伟、留言怎憋、點贊,相互分享才能持續(xù)進(jìn)步九昧!