android 傳感器坐標
傳感器分類
總體來說,傳感器分為運動傳感器和位置傳感器兩種。(此處忽略了一些溫度、光照等環境傳感器)。
運動傳感器用來監測設備的運動,比如傾斜、震動和搖擺。運動傳感器包括:加速度計、陀螺儀、重力感應器、線性加速度計、旋轉向量傳感器。
位置傳感器用來監測設備的位置,即相對于世界坐標系的位置。包括地磁場傳感器、接近傳感器和方向傳感器。
(方向傳感器是基于軟件的,根據加速度計和地磁場傳感器導出)。
可以看出,手機的上述傳感器讀數,需要涉及到兩個坐標系,一個是相對于手機自身,一個是相對于世界位置。
上面很多傳感器是測量手機自身姿態的,那么它們讀出的數是相對于手機坐標系的;
另一些傳感器和方法,目的是測量手機在世界坐標系中的位置,那么它們的讀數就是相對于世界坐標系的。
手機的自然坐標系
當一個設備被放在其默認的方向上時,X軸是水平指向右的,Y軸是垂直向上的,Z軸是指向屏幕正面之外的,即屏幕背面是Z的負值。
當設備運動或者旋轉的時候,這些坐標軸是不會改變的,即它們是跟隨手機的。
即是說,手機坐標系是跟隨設備的自然方向的(但是請記住自然方向不一定是豎直,比如平板它的自然方向就很有可能是橫向)。
使用這個坐標系的傳感器:
即是說它們的度數顯示了在手機的這三個軸上的數字大小。
屏幕旋轉
常常要考慮屏幕的旋轉,即屏幕畫面相對于自然方向的旋轉。
于是就需要使用 getRotation()方法來獲取屏幕的旋轉值。
這個方法是Display類中的,跟傳感器不相關。
這個方法的返回值只對應0,90,180,270四種旋轉情況,它說明屏幕顯示區域的旋轉情況。
世界坐標系
有一些傳感器和方法使用相對于世界的坐標系,因為它們返回的數據反映設備相對于地球及真實環境的位置信息。
請見getOrientation() 方法,getRotationMatrix() 方法,Orientation Sensor, 和 Rotation Vector Sensor。下面各自介紹。
getRotationMatrix()
getRotationMatrix()方法說明中,定義的世界坐標系如下:
X軸平行于地面,指向東方。
Y軸平行于地面,指向北極方向。
Z軸垂直于地面,指向天空。
getOrientation()
getOrientation() 方法中所用的坐標系與上面的不同:
X軸平行于地面,指向西方;
Y軸平行于地面,指向地磁場北極。
Z軸垂直于地面,指向地心。
getOrientation方法的返回值表示:
values[0]: azimuth, rotation around the Z axis.
values[1]: pitch, rotation around the X axis.
values[2]: roll, rotation around the Y axis.
并且這三個角度值都是以弧度做單位,逆時針方向為正。
方向傳感器的返回值說明
方向傳感器是利用加速度計和地磁場傳感器得到自己的數據。
方向傳感器比較特殊,因為它的數值是相對于絕對方向的。它得到的是手機設備的絕對姿態值。
一個方向傳感器得到的三維數據如下:
(參見http://developer.android.com/guide/topics/sensors/sensors_position.html#sensors-pos-orient)
方向傳感器返回的都是角度值,以度數為單位。
注意下面說的x、y、z軸均是手機自身的坐標軸。
第一個角度:Azimuth (degrees of rotation around the z axis).
表示手機自身的y軸與地磁場北極方向的角度,即手機頂部朝向與正北方向的角度。
(This is the angle between magnetic north and the device's y axis. )
當手機繞著自身的z軸旋轉時,該角度值將發生改變。
例如該角度值為0時,表示手機頂部指向正北;該角度為90度時,代表手機頂部指向正東;該角度為180度時,代表手機頂部指向正南;該角度為270度時,代表手機頂部指向正西。
第二個角度:Pitch (degrees of rotation around the x axis).
表示手機頂部或尾部翹起的角度。
當手機繞著自身的x軸旋轉,該角度會發生變化,值的范圍是-180到180度。
當z軸正向朝著y軸正向旋轉時,該角度是正值;當z軸正向朝著y軸負向旋轉時,該角度是負值。
假設將手機屏幕朝上水平放在桌子上,如果桌子是完全水平的,該角度應該是0。
假如從手機頂部抬起,直到將手機沿x軸旋轉180度(屏幕向下水平放在桌面上),這個過程中,該角度值會從0變化到-180。
如果從手機底部開始抬起,直到將手機沿x軸旋轉180度(屏幕向下水平放在桌面上),該角度的值會從0變化到180。
第三個角度:Roll (degrees of rotation around the y axis).
表示手機左側或右側翹起的角度。
當手機繞著自身x軸旋轉時,該角度值將會發生變化,取值范圍是-90到90度。
當z軸正向朝著x軸正向旋轉時,該角度是負值;
當z軸正向朝著x軸負向旋轉時,該角度是正值。
(這里跟官方文檔的說法有點不太一致,即第三個角度的正負號正好相反,我不知道是文檔寫錯了,還是它用了別的什么坐標系)。
因為通過真機測試,結果如下:
將手機屏幕朝上水平放在桌子上,如果桌子是完全水平的,該角度應該是0。
假如將手機左側逐漸抬起,直到將手機沿Y軸旋轉90度(手機與桌面垂直),在這個旋轉過程中,該角度會從0變化到-90。
如果從手機的右側開始抬起,直到將手機沿Y軸旋轉90度(手機與桌面垂直),該角度的值會從0變化到90度。
其他說明:
由于需要計算,所以方向傳感器的準確度和精度都會受到影響。
官方文檔上說,只有當第三個roll的角度值為0的時候得到的值比較可靠。
specifically, this sensor is only reliable when the roll component is 0。
所以從Android 2.2 (API level 8)開始,不建議使用方向傳感器。
建議使用 getRotationMatrix()和getOrientation() 結合來計算方向值。
也可以利用remapCoordinateSystem()方法來進行一些方向值向其他坐標系的轉換。