28

私の Android デバイスから、線形加速度値の配列 (デバイスの座標系) と絶対方位値の配列 (地球の座標系) を読み取ることができます。私が必要とするのは、後者の座標で線形加速度値を取得することです。システム。

どうすればそれらを変換できますか?

コメントでアリの返信後に編集:

わかりました。正しく理解できれば、線形加速度を測定するとき、携帯電話の位置はまったく問題になりません。測定値は地球の座標系で与えられるからです。右?

しかし、電話をさまざまな位置に置き、さまざまな軸で加速するテストを行ったところです。3 組の写真があります。最初の写真はデバイスの設置方法を示し (ペイントの「マスター スキル」で申し訳ありません)、2 番目の写真は線形 acc によって提供されたデータからの読み取り値を示しています。センサー:

  1. デバイスを左側に配置

最初の位置 最初の読み

  1. 背中に横たわっているデバイス

二位 2回目の読み取り

  1. デバイススタンディング

ここに画像の説明を入力 ここに画像の説明を入力

そして今 - 3 番目のケースでは、デバイスの位置は問題にならないのに、なぜ Z 軸 (Y 軸ではなく) に沿って加速度が発生するのでしょうか?

4

4 に答える 4

44

やっと解決できました!したがって、地球の座標系で加速度ベクトルを取得するには、次のことが必要です。

  1. 回転行列を取得します(後でクラスfloat[16]で使用できるようにするため)から(およびセンサー値をパラメーターとして使用)、android.opengl.MatrixSensorManager.getRotationMatrix()SENSOR.TYPE_GRAVITYSENSOR.TYPE_MAGNETIC_FIELD
  2. 回転行列で使用android.opengl.Matrix.invertM()して反転します (転置ではありません!)。
  3. センサーを使用Sensor.TYPE_LINEAR_ACCELERATIONして線形加速度ベクトルを取得します (デバイスの座標系で)。
  4. android.opengl.Matrix.multiplyMV()回転行列に線形加速度ベクトルを掛けるために使用します。

そして、あなたはそれを持っています!他の人のために貴重な時間を節約できることを願っています。

Edward Falk と Ali のヒントに感謝します!!

于 2012-07-23T14:19:59.593 に答える
18

@alex の回答に基づいて、コード スニペットを次に示します。

private float[] gravityValues = null;
private float[] magneticValues = null;

 @Override
    public void onSensorChanged(SensorEvent event) {
        if ((gravityValues != null) && (magneticValues != null) 
            && (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)) {

            float[] deviceRelativeAcceleration = new float[4];
            deviceRelativeAcceleration[0] = event.values[0];
            deviceRelativeAcceleration[1] = event.values[1];
            deviceRelativeAcceleration[2] = event.values[2];
            deviceRelativeAcceleration[3] = 0;

            // Change the device relative acceleration values to earth relative values
            // X axis -> East
            // Y axis -> North Pole
            // Z axis -> Sky

            float[] R = new float[16], I = new float[16], earthAcc = new float[16];

            SensorManager.getRotationMatrix(R, I, gravityValues, magneticValues);

            float[] inv = new float[16];

            android.opengl.Matrix.invertM(inv, 0, R, 0);
            android.opengl.Matrix.multiplyMV(earthAcc, 0, inv, 0, deviceRelativeAcceleration, 0);
           Log.d("Acceleration", "Values: (" + earthAcc[0] + ", " + earthAcc[1] + ", " + earthAcc[2] + ")");                

        } else if (event.sensor.getType() == Sensor.TYPE_GRAVITY) {
            gravityValues = event.values;
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            magneticValues = event.values;
        } 
   }
于 2016-04-07T13:26:59.023 に答える
4

ドキュメントによると、電話の座標系で線形加速度を取得します。

任意のベクトルを携帯電話の座標系から地球の座標系に変換するには、回転行列を乗算します。getRotationMatrix()から回転行列を取得できます。

(おそらく、この乗算を行う関数が既に存在するかもしれませんが、私は Android プログラミングを行っておらず、その API に精通していません。)

回転行列に関する優れたチュートリアルは、Direction Cosine Matrix IMU: Theory manuscript です。幸運を!

于 2012-07-20T11:53:34.723 に答える
1

OK、まず第一に、Androidで実際の慣性航法を行おうとしているのなら、あなたはあなたのためにあなたの仕事を切り取っています。スマートフォンで使用されている安価な小さなセンサーは、十分に正確ではありません。ただし、建物の内部など、短距離での中間ナビゲーションに関していくつかの興味深い作業が行われています。あなたが掘り下げることができる主題に関する論文がおそらくあるでしょう。グーグルの「モーションインターフェース開発者会議」とあなたは何か役に立つものを見つけるかもしれません-それはInvensenseが数ヶ月前に開催した会議です。

第二に、いいえ、線形加速度は世界座標ではなく、デバイス座標にあります。自分で変換する必要があります。つまり、デバイスの3D方向を知る必要があります。

あなたがしたいのは、仮想センサーTYPE_GRAVITYとTYPE_LINEAR_ACCELERATIONをサポートするバージョンのAndroidを使用することです。適度に正確で正確な測定値を取得するには、ジャイロを備えたデバイスが必要です。

内部的には、システムはジャイロ、加速度計、磁力計を組み合わせて、デバイスの向きの真の値を導き出します。これにより、加速度計デバイスが重力コンポーネントと加速度コンポーネントに効果的に分割されます。

したがって、実行したいのは、TYPE_GRAVITY、TYPE_LINEAR_ACCELERATION、およびTYPE_MAGNETOMETERのセンサーリスナーを設定することです。SensorManagerへの入力として重力と磁力計のデータを使用します。getRotationMatrix()は、ワールド座標をデバイス座標に、またはその逆に変換する回転行列を取得します。この場合、「versa」の部分が必要になります。つまり、線形加速度入力を、方向行列の転置を掛けてワールド座標に変換します。

于 2012-07-21T17:09:42.353 に答える