13

地球座標に対してデバイスの背面が指している方向を表す方向ベクトルを取得するにはどうすればよいですか?

たとえば、机の上に置いた場合(画面を上に向けた場合)は[0,0、-1]と表示され、垂直に北向きに保持された場合は[1,0,0]と表示されます。

地球座標に関連している限り、方位、ピッチ、ロールから計算する方法を知っています。ここで明確にするために、私は角速度ではなく、地球に接する平面に対する実際の現在の角度を探しています。したがって、デバイスが垂直に保持され、北を向いている場合、角度「アルファ」は0または360、角度「ベータ」は90、「ガンマ」は0になります。これらの値を取得する方法がわかりません。また。

私は一日中APIを読んでいますが、これらのいずれかを取得する方法をまだ見つけることができません。

public void onSensorChanged(SensorEvent event) {
    // ?    
}

洞察をありがとう。

4

2 に答える 2

9

SensorManager.getRotationMatrix()私がこれを見つける前に書かれた、以下に概説されていることをします。磁気と真北の違いを修正したい場合でも必要になるため、追加の説明は残しておきます。

大まかなアルゴリズムは、回転行列を取得し[0,0,-1]、それをベクトルに乗算してから、これを座標系に合わせて調整することです。なんで?Androidドキュメントは、デバイスと世界の座標系を提供します

端末世界

[0,0,-1]Androidデバイスでは、画面から後方に垂直にポイントを調整することに注意してください。回転行列Rにこのベクトルを掛ける[0,0,-1]と、デバイスがテーブル上にあるときに、必要に応じてワールド座標が得られます。北向きに直立すると、が表示されます。これは、Androidシステムに対してとが入れ替わって[0,-1,0]いる座標系を選択したことを示しますが、これは単に規則の変更にすぎません。xy

注は、否定されR * [0,0,-1]^Tたの3番目の列にすぎません。Rこれから、擬似コードを取得します。

getRotationMatrix(R);
Let v = first three elements of third column of R.
swap v[0] and v[1]

これはあなたが望むものを手に入れるべきです。

何をしているのかに関する追加情報getRotationMatrix()は次のとおりです。


「下」の方向を確立するための加速度計データと、「北」の方向を決定するための磁力計データの両方が必要です。加速度計が重力のみを感知していると想定する必要があります(デバイスは静止しているか、一定の速度で移動しています)。次に、磁力計のベクトルを重力ベクトルに垂直な平面に投影する必要があります(磁場は一般に地表に接していないため)。これにより、2つの軸が得られます。3番目は直交しているため、外積で計算できます。これにより、デバイスシステムの地球座標ベクトルが得られます。逆、つまり地球座標のデバイス座標が必要なようです。このためには、方向余弦と反転の行列を作成するだけです。

上記の説明では、磁力計のベクトルが北を向いていることを前提としています。(高校の科学から!)実際には磁気南に向かっていると思いますが、手元にデバイスがないため、試すことができません。もちろん、磁北/南は、地球上のどこにいるかによって、真とは0度から180度異なります。GPS座標を取得して、実際のオフセットを計算できます。

これらを行うために必要な数学に精通していない場合は、さらに説明できますが、後で説明する必要があります。

于 2012-06-17T03:03:08.887 に答える
9

このページを読む:http://developer.android.com/reference/android/hardware/Sensor.html

API 8以降には、使用可能なすべてのセンサーと適切なフィルターの入力を組み合わせて生成される「仮想」センサーがあります。「TYPE_ORIENTATION」センサーは、デバイスの全体的な向きを示しますが、特定の向きでの障害状態のため、このインターフェースは非推奨になりました。新しいセンサーはTYPE_ROTATION_VECTOR(API 9以降)であり、デバイスの向きをクォータニオンとして提供します。これは実際に使用するのに最適なセンサーですが、その背後にある計算は少し重いです。

それができない場合は、SensorManager.getRotationMatrix()を呼び出して、最新の重力と磁力計のデータを渡します。これにより、ベクトルをデバイス座標からワールド座標に、またはその逆に変換するために使用できる回転行列が返されます(行列を転置して反転するだけです)。

getOrientation()関数を使用すると、進行方向、ピッチ、およびロールを取得できますが、これらの障害状態はTYPE_ORIENTATIONセンサーと同じです。

Examples:

  Device flat on a table, top facing north:
    1  0  0
    0  1  0
    0  0  1

  Tilted up 30 degrees (rotated about X axis)
    1   0      0
    0   0.86  -0.5
    0   0.5    0.86

  Device vertical (rotated about X axis), facing north:
    1  0  0
    0  0 -1
    0  1  0

  Device flat on a table, top facing west:
    0 -1  0
    1  0  0
    0  0  1

  Device rotated about its Y axis, onto its left side, top
  facing north:
    0  0 -1
    0  1  0
    1  0  0

役立つと思われるサンプルコードを次に示します。

public void onSensorChanged(SensorEvent event) {
    long now = event.timestamp;     // ns

    switch( event.sensor.getType() ) {
      case Sensor.TYPE_ACCELEROMETER:
        gData[0] = event.values[0];
        gData[1] = event.values[1];
        gData[2] = event.values[2];
        break;
      case Sensor.TYPE_MAGNETIC_FIELD:
        mData[0] = event.values[0];
        mData[1] = event.values[1];
        mData[2] = event.values[2];
        haveData = true;
        break;
    }

    if( haveData ) {
        double dt = (now - last_time) * .000000001;

        SensorManager.getRotationMatrix(R1, Imat, gData, mData);
        getOrientation(R1, orientation);
        pfdView.newOrientation(orientation[2], (float)dt);


        Log.d(TAG, "yaw: " + (int)(orientation[0]*DEG));
        Log.d(TAG, "pitch: " + (int)(orientation[1]*DEG));
        Log.d(TAG, "roll: " + (int)(orientation[2]*DEG));

        acft.compass = orientation[0];

        last_time = now;
    }
}
于 2012-06-17T04:16:14.113 に答える