帶你認(rèn)識Google 屌炸天的AR增強現(xiàn)實技術(shù)——Tango

這兩年虛擬現(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í)資料

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軸的正方向是向右的伶贰。

image

朝向信息,也可以說成旋轉(zhuǎn)信息罐栈,如下圖理解黍衙,三個方向上的旋轉(zhuǎn),用四元數(shù)表示(這個我不太懂荠诬,三個旋轉(zhuǎn)用四元數(shù)表示好像是為了方便計算琅翻,具體請百度)。

image

2. pose的生命周期

pose數(shù)據(jù)是有可能失效的柑贞,比如魚眼攝像頭發(fā)生了錯誤導(dǎo)致出錯等方椎。下圖 是pose數(shù)據(jù)的狀態(tài)轉(zhuǎn)換圖。

image

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)步九昧!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绊袋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子耽装,更是在濱河造成了極大的恐慌愤炸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掉奄,死亡現(xiàn)場離奇詭異规个,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)姓建,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門诞仓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人速兔,你說我怎么就攤上這事墅拭。” “怎么了涣狗?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵谍婉,是天一觀的道長。 經(jīng)常有香客問我镀钓,道長穗熬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任丁溅,我火速辦了婚禮唤蔗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己妓柜,他們只是感情好箱季,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棍掐,像睡著了一般藏雏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上作煌,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天诉稍,我揣著相機(jī)與錄音,去河邊找鬼最疆。 笑死,一個胖子當(dāng)著我的面吹牛蚤告,可吹牛的內(nèi)容都是我干的努酸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼杜恰,長吁一口氣:“原來是場噩夢啊……” “哼获诈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起心褐,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤舔涎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后逗爹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亡嫌,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年掘而,在試婚紗的時候發(fā)現(xiàn)自己被綠了挟冠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡袍睡,死狀恐怖知染,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情斑胜,我是刑警寧澤控淡,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站止潘,受9級特大地震影響掺炭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜覆山,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一竹伸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦勋篓、人聲如沸吧享。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钢颂。三九已至,卻和暖如春拜银,著一層夾襖步出監(jiān)牢的瞬間殊鞭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工尼桶, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留操灿,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓泵督,卻偏偏與公主長得像趾盐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子小腊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容