OpenGL: Rotation vector sensor of Android and Device motion of iOS

来源:http://www.cnblogs.com/psklf/archive/2017/05/22/6890885.html
-Advertisement-
Play Games

為了實現一個全景圖片展示的功能,需要藉助手機的姿態感測器,實現一個這樣的功能:當手機旋轉時,視角也跟著旋轉(讀者若理解不能,可以參考下現在流行的 VR 應用,使用陀螺儀模式時的效果,亦可稱作“單目 VR 效果”)。這個功能的實現原理為:利用手機感測器得到手機的當前的姿態的信息(可以是用各種方式來描述 ...


為了實現一個全景圖片展示的功能,需要藉助手機的姿態感測器,實現一個這樣的功能:當手機旋轉時,視角也跟著旋轉(讀者若理解不能,可以參考下現在流行的 VR 應用,使用陀螺儀模式時的效果,亦可稱作“單目 VR 效果”)。這個功能的實現原理為:利用手機感測器得到手機的當前的姿態的信息(可以是用各種方式來描述的),然後調整投影的參數,實現最終的圖像跟著手機旋轉的效果。

手機姿態獲取

Android

Android 平臺有各種各樣的感測器(Sensor),不止一個 sensor 可以實現前文提到的目的。在 Android SDK API Guides 中可以找到所有可用的 sensors。

1 gyroscope

這個就是陀螺儀了,是硬體感測器(hardware sensor),可以提供設備繞 xyz 三個軸旋轉的角速度。註意這裡的坐標系就是設備自身的,短邊 x 軸,長邊 y 軸,z 軸穿越手機屏幕。為實現旋轉效果需要的數據是旋轉的角度(用以計算旋轉矩陣),所以如果要用 gyroscope 則許需要對數據進行積分,最好加上濾波使效果平穩。

2 orientation

這是一個軟體感測器(software sensor),返回的數據不是感測器硬體直接採集得到的,而是根據硬體的數據進行合適的計算得到的。

閱讀文檔即可得知,此用於獲取設備在 Yaw,Pitch and Roll 三個方向的旋轉的角度,根據這三個角度也就可以確定其姿態了。但是官方文檔不推薦這樣使用,而是推薦 rotation vector sensor 並配合 [getRotationMatrix()](https://developer.android.google.cn/reference/android/hardware/SensorManager.html#getRotationMatrix(float[],%20float[],%20float[],%20float[]) 來計算出這三個參數,至於原因,官方文檔只說現在留著這個感測器類型是歷史原因,讓大家不要用了,沒解釋其他的。具體原因後面解釋。

3 rotation vector

這個 sensor 和上面的 orientation 一樣,都是軟體感測器。這個表示的仍然是設備的姿態,但是與上面的不同,這個用一個四元數來表示設備的旋轉,旋轉的參考坐標系是真實的物理世界。

在應用該感測器提供的數據時,值得註意的是,有可能感測器返回的數據不一定是四個數據,也有可能是三個參數,比較安全的做法是這樣做:

        @Override
        public void onSensorChanged(SensorEvent event) {
            float[] quat = new float[4];
            SensorManager.getQuaternionFromVector(quat, event.values);
            // use the quaternion
            // ...
        }

可參考:TYPE_ROTATION_VECTOR

比較

那麼這兩個感測器似乎都能用,到底用哪個呢?顯而易見,第一個用起來不太方便。那麼後兩者區別在哪?

實際上,官方就不推薦使用 orientation,已經將其標記為 deprecated,並且提供了另一個方法叫做 getOrientation(),用法較複雜一點,從加速度計和地磁感測器獲取數據,根據此計算得旋轉矩陣,然後在根據旋轉矩陣計算三個方向的旋轉角度。個人感覺就是放棄了幫助開發者去計算這個數據,而是告訴大家應該怎麼樣算,自己去算吧。為什麼要廢棄呢,根據這裡的解釋,舊版感測器的問題主要是萬向節鎖,當某一個軸轉動 90 度,就很難準確描述另外兩個軸的轉動了,對萬向節鎖的理解可以看我之前的文章:萬向節鎖(Gimbal Lock)的理解。相比較,rotation vector 用四元數來描述旋轉,避免了這個問題,所以我採用這個感測器來採集設備姿態的信息。

iOS

iOS 平臺稍微簡單一些,沒有那麼多具體的感測器。deviceMotion 就很好用,獲取 deviceMotion.attitude 這是一個CMAttitude對象,可以直接獲取用四元數表示的設備的姿態信息。

其實 CoreMotion 這個 Framework 也是可以提供裸陀螺儀數據等等,但是 CMDeviceMotion 下麵的 attitude 這個屬性返回的數據是更加準確的,如果需要精確的數據,推薦使用這個方法。

實現旋轉

這裡我先簡單闡述一下一個旋轉的意義:當我們看著一張圖片的時候,如果要實現旋轉這張圖的效果,有兩個辦法:

  1. 將圖片轉一下(調整物體的模型的參數)
  2. 我的腦袋轉一下(調整攝像機的參數,也就是改變觀察矩陣(即 look at matrix)的參數)

實際上這兩種方法都可以實現,實際應用的時候隨便選一個更合適自己的就可以了。我這裡要說明的是如果採用後一個辦法,不能簡單地將兩個矩陣相乘就算數了,我們要從實際情況去考慮這個問題,考慮 OpenGL 的觀察矩陣的計算:

// GLU
gluLookAt(x0, y0, z0, xref, yref, zref, Vx, Vy, Vz)

// glm
GLM_FUNC_DECL tmat4x4<T, P> glm::lookAt (   tvec3< T, P > const &   eye,
tvec3< T, P > const &   center,
tvec3< T, P > const &   up 
)

兩種是一樣的,分別指定觀察坐標系的原點(eye),參考點(即視點,相機瞄準的點,center),和向上向量(up)。當旋轉相機時,需要將 center 和 up 同時應用這個相應的旋轉。我之前犯過的一個錯誤是:我僅僅把旋轉應用到了 center 上面,而沒有應用到 up vector,up vector 一直設置的是(0, 1, 0)。直觀點說就是:視點轉了,但是頭頂朝向沒有變化,這個是不符合邏輯的,我們需要讓視線N:P_0 - P_ref和 up vector 保持垂直。

問題解決

在實際實踐中,Android 的坑還真是特別的多,我發現使用 rotation vector 計算出旋轉矩陣,會根據手機當前和真實世界的關係產生一定偏移,也就是說手機朝向北方和朝向南方得到的數據是不一樣的,而我希望的是得到一個與手機初始的朝向無關(也就是手機繞真實世界的南北極組成的軸旋轉的角度),而與手機與地平線的夾角有關的這麼一個數據。總的來說就是 rotation vector 做了一些我不想要的校正。同時我找到另一個 sensor:GAME_ROTATION_VECTOR,其介紹如下:

Identical to TYPE_ROTATION_VECTOR except that it doesn't use the geomagnetic field. Therefore the Y axis doesn't point north, but instead to some other reference, that reference is allowed to drift by the same order of magnitude as the gyroscope drift around the Z axis.
In the ideal case, a phone rotated and returning to the same real-world orientation will report the same game rotation vector (without using the earth's geomagnetic field). However, the orientation may drift somewhat over time. See TYPE_ROTATION_VECTOR for a detailed description of the values. This sensor will not have the estimated heading accuracy value.

使用這個我基本上實現我想要的效果,所以以後要用這個 Rotation vector 的時候,要考慮清楚到底要用哪一個。另外還有一個 Geomagnetic Rotation Vector 實際使用效果較差,精度較低,但是省電。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • vue安裝 將來我們不同的項目可能會用到不同的node版本,那麼就需要在各個node版本之間切換,所以建議使用nvm進行node版本控制。 安裝nvm: 前往https://github.com/coreybutler/nvm-windows下載,雙擊打開 點擊下一步: 第一個路徑XX/node/n ...
  • for-of迴圈: 新語法如下: 它的優點是: 這是目前遍曆數組最簡潔和直接的語法; 它避免了for-in的所有缺陷; 與forEach()不一樣,它支持break,continue和return。 for-of迴圈不僅僅是為遍曆數組而設計的。基本上所有類數組對象都適用 它也能用在字元串上,它將字元 ...
  • 一,效果圖。 二,代碼。 ...
  • 先回顧生命周期 Activity一共有3中狀態 運行中 Activity位於前臺,並具有用戶焦點 暫停 另一個Activity位於屏幕前臺並具有用戶焦點,但此Activity仍可見。也就是說,另一個Activity顯示在此Activity上方,並且該Activity部分透明或未覆蓋整個屏幕。暫停的A ...
  • 學習IOS幾天了,跟著教程做了兩個小應用了,現在先來總結一下。今天就是創建視圖和綁帶到代碼了。其實就是常見的MVC模式實現。 使用的Xcode版本是8.2。 在Xcode創建項目之後,預設就會創建一個Main.stroyborad,程式的入口也就是這裡,可以在 General 的 Deploymen ...
  • ios完整學習路線 圖片來源於網上下載 本人不是大牛,寫博客的目的只為記錄自己的學習過程。 也不算是入門從頭學習吧,之前已經做過將近兩年mac區域網開發相關的工作(檢測iphone主板所用的設備,內部使用,不用上線store,依然覺得自己還是小白),沒真正做過ios app這塊。也從來沒有記錄過學到 ...
  • 文章參考自:http://www.runoob.com/w3cnote/android-tutorial-togglebutton-switch.html 本節給大家介紹的Android基本UI控制項是:開關按鈕ToggleButton和開關Switch,這兩個其實都是開關組件,只是後者需要在Andr ...
  • 基於微信小程式的 模板消息 下發條件:用戶本人在微信體系內與頁面有交互行為後觸發 1. 使用說明 1.1 獲取模板id 登錄https://mp.weixin.qq.com獲取模板,如果沒有合適的模板,可以申請添加新模板,審核通過後可使用 1. 頁面的 `` 組件,屬性 report submit ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...