2012-04-19 180 views
27

我正在做一個地圖應用程序,其中包括位置的箭頭,顯示您所面臨的方式,像這樣:如何讓Android手機的方向符合人的方向?

Map with a blue arrow

我直接從SensorManager.getOrientation()獲得方位,使用第一個返回值:方位。當手機被拿着以便屏幕指向地平線上方和縱向時,箭頭正常工作。但是:

  • 當手機被握住以便屏幕指向地平線以下時,箭頭指向離用戶面對的方向180度。
  • 當手機被拿着讓屏幕的正面與地平線齊平時,箭頭不知道它指向哪個方向。方位角根本不返回有意義的結果。
  • 當手機向左或向右傾斜(或保持橫向模式)時,箭頭向左或向右傾斜。

的精心構建及以下科學的圖像顯示了我的意思(其中藍色是用戶的面,紅色的箭頭方向,屏幕大約是面向用戶的臉部,和谷歌地圖不正是我想要的):

Graph of what happens vs what I want

(需要注意的是,與谷歌地圖,但沒有成功做名單上的最後兩個動作,如果自動旋轉是關閉的。但是我甚至在那個階段,但其中一個)

看起來好像它是隻需使用如下所示的Y軸指示方向:http://developer.android.com/reference/android/hardware/SensorEvent.html,當我希望它使用Z軸指向方向的大部分時間和Y時,手機是平的。但是,考慮到getOrientation()返回的值,我不得不編寫複雜的案例來解決一些問題,並且面向電話的用例不可解決。我確定有一個更簡單的方法。

這裏是我的代碼(如果lastAcceleration和lastMagneticField無論是從內部傳感器傳來):

float[] rotationMatrix = new float[9]; 
if(SensorManager.getRotationMatrix(rotationMatrix, null, lastAcceleration, lastMagneticField)){ 
    float[] orientMatrix = new float[3]; 
    SensorManager.getOrientation(rotationMatrix, orientMatrix); 

    orientation = orientMat[0]*180/(float)Math.PI; 
} 

我在做什麼錯?有沒有更簡單的方法來做到這一點?

編輯:只是爲了澄清,我假設用戶將設備拿在他們面前,屏幕指向他們。除此之外,我顯然無法分辨是否只有其中一個旋轉。另外,我正在使用用戶在移動時的動作,但這是在他們靜止時的動作。

+16

+1爲科學圖像 – 2012-04-19 04:33:16

+0

是你的問題解決?你是如何得到lastAcceleration,lastMagneticField的? – 2015-06-24 04:50:41

+0

沒有。從未解決。也許它是永遠不可解決的,而且谷歌地圖似乎並不像我那時那麼聰明。我早已把它從我需要做的任務清單中拋棄了,因爲我不再爲同一家公司工作,更不用說同一個項目了。無論如何,Android現在的工作方式可能完全不同。 – AlbeyAmakiir 2015-06-24 06:10:39

回答

0

這看起來相當棘手。我正在開發一款適用於Android的PNS,並且面臨着某種類似的問題,因此我仍然需要這種光源:How to get the rotation between accelerometer's axis and motion vector?

問題是,它在我看來絕對不可能找到用戶正面對的方向不是設備),如果他沒有移動。那是人類身體上沒有傳感器,那麼如果設備停留在絕對相同的位置但用戶旋轉了90°,該怎麼辦?我看不出有什麼辦法可以找到它。

我可以建議的(而且實際上符合我的問題)是,你可以(我不知道你實際上在你的代碼中做了什麼)使用用戶的運動來確定他的標題。讓我解釋。假設你有第一個位置A.用戶轉到B.然後,您可以構建AB矢量,並在用戶停在B處時獲取用戶的標題。然後,您必須將代碼限制到抵達目的地時所面對的方向。

我知道這不如Google地圖的效果好,但是您知道Google爲此使用了什麼嗎?我的意思是他們只使用加速度傳感器和磁場傳感器?

+0

我假設用戶將設備放在它們前面,屏幕指向它們。除此之外,我顯然不能再做了。另外,我正在採取用戶的動作。就是這樣,當他們停止時,加速度計和磁場應該接管。 – AlbeyAmakiir 2012-04-22 22:29:20

6

你叫過remapCoordinateSystem嗎?否則,當手機垂直放置時,您只能獲得正確的價值。對於這種情況當手機被拿着讓屏幕的正面與地平線齊平時,您無法獲得用戶的正面。因爲要獲得面對面,必須將傳感器讀數的z值投影到世界座標系中的xy平面中,並且在設備水平保持時爲零。

更確切地說,如果你想要面對手機,那麼手機必須與水平方向傾斜至少約25度,你必須調用remapCoordinateSystem。下面的代碼會給你你想要的最後2張圖片。
代碼

float[] rotationMatrix = new float[9]; 

if(SensorManager.getRotationMatrix(rotationMatrix, null, lastAcceleration, lastMagneticField)){ 
    float[] orientMatrix = new float[3]; 
    float remapMatrix = new float[9]; 
    SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapMatrix); 
    SensorManager.getOrientation(remapMatrix, orientMatrix); 

    orientation = orientMat[0]*180/(float)Math.PI; 
} 

的getOrientation給你假設手機正確的價值觀是鋪設平坦。因此,如果手機垂直握住,則必須重新映射座標以獲得平坦的位置。在幾何上,您將手機-z軸投影到世界xy平面,然後計算此投影矢量與世界y軸之間的角度。

+0

我不確定我關注。或者,也許你沒有。當屏幕水平時,獲取方向並不是不可能的,因爲這既是Google所做的,也是我現在所擁有的。當手機垂直時,我希望得到正面。和不。我還沒有調用'remapCoordinateSystem'。該文檔不完全清楚如何使用它。 – AlbeyAmakiir 2012-05-20 23:27:20

+0

如果手機處於握持狀態,您可以獲取指南針的方向,但不能識別手機的朝向,因此屏幕的朝向與地平線保持一致。那就是手機正朝着地面,所以談論北,南等等沒有意義......你可以得到「指南針方向」,但這個方向取決於手機的方向。也就是說,如果手機在您面前以縱向模式平放,並且指南針顯示0度,那麼當您旋轉至橫向時,指南針將根據您旋轉的方向顯示90或270個手指。 – 2012-05-23 03:28:19

0

看來,適當的方式來獲得當用戶垂直拿着手機軸承是用這樣的:如果你要處理兩種方式(垂直和平板)

// after calling getRotationMatrix pass the rotationMatix below: 
SensorManager.remapCoordinateSystem(inR, AXIS_X, AXIS_Z, outR); 

你會可能需要檢測,然後只在垂直時執行此重新映射。

查看API文檔here

0

你應該考慮問題並確定用戶是否接近垂直拿起電話。

我選擇了從桌子上的平面向上或向下45度俯仰後,座標系應該重新映射。

if (Math.round(Math.toDegrees(-orientation[1])) < 45 && Math.round(Math.toDegrees(-orientation[1])) > -45) { 
//do something while the phone is horizontal 
}else{ 
//R below is the original rotation matrix 
float remapOut[] = new float[9]; 
SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapOut); 
//get the orientation with remapOut 
float remapOrientation[] = new float[3]; 
SensorManager.getOrientation(remapOut, remapOrientation); 

它工作得很好。 讓我知道,如果任何人都可以建議這方面的改進。謝謝。