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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...