コンパスを含むAndroidスマートフォンの向きの概要


107

私はしばらくの間、Androidの方位センサーに頭を悩ませてきました。理解できたと思いました。その後、私はそうではないことに気づきました。今、私は(希望)私はそれについて再び良い気持ちを持っていると思いますが、私はまだ100%ではありません。私はそれについて私のパッチの理解を試みて説明します、そしてうまくいけば、私が部分で間違っているか、どんな空白を埋めても、人々は私を訂正することができるでしょう。

経度0度(本初子午線)と緯度0度(赤道)に立っていると思います。この場所は、実際にはアフリカの沖合の海にありますが、我慢してください。スマートフォンの底面が私の足を指すように、スマートフォンを顔の前で持ちます。私は北を向いているので(グリニッジの方を向いています)、電話の右側は東をアフリカに向けています。この方向で(下の図を参照して)、X軸は東を指し、Z軸は南を指し、Y軸は空を指します。

これで、電話のセンサーを使用して、この状況でデバイスの向き(場所ではなく)を計算できます。この部分はいつも私を混乱させました、おそらくそれがうまくいくことを受け入れる前に何かがどのように働いたか理解したかったからでしょう。電話は2つの異なる技術の組み合わせを使用してその方向を解決しているようです。

その前に、上記の方向に立っている、緯度と経度0度の架空の土地に戻って立っているところを想像してみてください。また、目隠しをされていて、靴が遊び場のラウンドアバウトに固定されているとします。誰かがあなたを後ろに突き刺した場合、あなたは前に(北に向かって)倒れ、あなたの落下を壊すために両手を外に出します。同様に、誰かがあなたに左肩を突きつけた場合、あなたは右手に倒れます。内耳には「重力センサー」(youtubeクリップ)があり、前方/後方に落下したり、左/右に落下したり、倒れたり(または上に倒れたり)したかどうかを検出できます。したがって、人間は電話と同じX軸とZ軸を中心とした位置合わせと回転を検出できます。

今、誰かが今あなたを東に向くようにラウンドアバウトで90度回転させたと想像してください。Y軸を中心に回転しています。生物学的には検出できないため、この軸は異なります。ある程度の角度がついていることはわかっていますが、惑星の北磁極との関係で方向はわかりません。代わりに、外部ツール...磁気コンパスを使用する必要があります。これにより、どの方向を向いているかを確認できます。同じことが私たちの電話にも当てはまります。

今、携帯電話にも3軸の加速度計があります。私が持っているNOをそれらが実際にどのように機能するかを考えますが、私がそれを視覚化する方法は、重力が空から落ちる一定で均一な「雨」であると想像し、上図の軸が流れる雨の量を検出できるチューブであると想像することです。電話が直立していると、すべての雨がY字型の「チューブ」を通って流れます。携帯電話を徐々に回転させて画面を上に向けると、Yを流れる雨の量はゼロに減少し、Zを通る量は最大の雨が流れるまで着実に増加します。同様に、電話を横向きに傾けると、Xチューブは最終的に最大量の雨を収集します。したがって、3つのチューブを流れる雨の量を測定することにより、電話の向きに応じて、向きを計算できます。

携帯電話には、通常のコンパスのように動作する電子コンパスもあります。その「仮想針」は磁北を指します。アンドロイドマージたびように、これらの二つのセンサからの情報SensorEventのがTYPE_ORIENTATION生成されvalues[3]、配列が持つ
値[0]:方位- (磁北のコンパス方位東)
値[1]:ピッチ、x軸周りの回転が(電話です前方または後方に傾く)
値[2]:ロール、y軸を中心とした回転(電話が左側または右側に傾いている)

したがって、Androidが3番目の加速度計の読み取りではなく方位角(方位角方位)を与える理由(つまり、私にはわかりません)は、方位角方位計の方がより有用であると考えています。彼らがこのタイプのセンサーを非推奨にした理由はわかりません。現在SensorEvent、タイプののシステムにリスナーを登録する必要があるようですTYPE_MAGNETIC_FIELD。イベントのvalue[]配列はSensorManger.getRotationMatrix(..)SensorManager.getOrientation(..)メソッドに渡される回転行列(以下を参照)を取得するためにメソッドに渡される必要があります。Androidチームが廃止された理由を誰かが知っていSensor.TYPE_ORIENTATIONますか?効率的なことですか?これは、同様の質問へのコメントの1つに示されていますが、別のタイプのリスナーをdevelopment / samples / Compass / src / com / example / android / compass / CompassActivity.javaの例。

回転行列についてお話ししたいと思います。(これが私が最もよくわからないところです)したがって、上記のAndroidドキュメントの3つの図は、A、B、Cと呼びます。

A = SensorManger.getRotationMatrix(..)メソッドの図で、世界の座標系を表します

B = SensorEvent APIで使用される座標系。

C = SensorManager.getOrientation(..)メソッド図

つまり、私の理解では、Aは「世界の座標系」を表していると私は考えています。これは、惑星上の位置が(緯度、経度)カップルとオプションの(高度)として与えられる方法を指していると思います。Xは「東座標、Yは「北座標」です。Zは空を指し、高度を表します。

図Bに示す電話の座標系は固定されています。Y軸は常に上を指します。回転行列は常に電話によって計算され、2つの間のマッピングを可能にします。それで、回転行列がBの座標系をCに変換すると私は考えるのは正しいですか したがって、SensorManager.getOrientation(..)メソッドを呼び出すvalues[]ときは、図Cに対応する値を持つ配列を使用します。電話が空を指している場合、回転行列は単位行列(1と数学的に同等の行列)です。これは、デバイスが整列しているため、マッピングが不要であることを意味します世界の座標系で。

OK。もうやめた方がいいと思います。前に言ったように、私が人を台無しにしたり、人を助けたりした場所(またはさらに混乱した人!)


25
私はこの質問が本当に好きです。答えられないけど好きです。
Octavian A. Damiean、2011年

4
ティム、あなたは答えを得たことがありますか?私も同じように頭をかいてきました。これは、これまでに見た中で最もドキュメントが不十分なAPIの1つです。
Pierre-Luc Paour

本当に怖くないです。私は先に進む必要がありました。いつかこの問題に戻ります。
Tim

1
ここで、ほぼ同じ質問がありますか?そして、レスポンス、ソリューションも。メイド私のコードの公共のGithubで。

私が疑問に思っているのと同じことですが、Androidデバイスにコンパスを実装し、インターネットからの助けを借りれば問題なく機能しますが、混乱しているのは...デバイスが地面に置かれているとしましょう私とその北を向いている今、私は私の携帯電話を取り上げ、それを私の頭の上に垂直に置きます。最初に、針はその方向を変更する必要があり、その理由。私は自分の方向を変えていなかったのでそれはすべきではないと思っていますが、それは私のアプリと私がダウンロードした他のすべてのアプリで変わっています。なぜ誰かが説明できますか?
Syed Raza Mehdi

回答:


26

あなたはチェックしたいかもしれません ワンスクリーンターンに値する別の記事。回転行列が必要な理由を説明しています。

簡単に言えば、デバイスが回転しても、電話のセンサーは常に同じ座標系を使用します。

単一方向にロックされていないアプリケーションでは、デバイスを回転させると画面座標系が変化します。したがって、デバイスがデフォルトの表示モードから回転すると、センサー座標系は画面座標系と同じではなくなります。この場合の回転行列は、AをCに変換するために使用されます(Bは常に固定されたままです)。

これを使用する方法を示すコードスニペットを次に示します。

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);

// Register this class as a listener for the accelerometer sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                    SensorManager.SENSOR_DELAY_NORMAL);

//...
// The following code inside a class implementing a SensorEventListener
// ...

float[] inR = new float[16];
float[] I = new float[16];
float[] gravity = new float[3];
float[] geomag = new float[3];
float[] orientVals = new float[3];

double azimuth = 0;
double pitch = 0;
double roll = 0;

public void onSensorChanged(SensorEvent sensorEvent) {
    // If the sensor data is unreliable return
    if (sensorEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
        return;

    // Gets the value of the sensor that has been changed
    switch (sensorEvent.sensor.getType()) {  
        case Sensor.TYPE_ACCELEROMETER:
            gravity = sensorEvent.values.clone();
            break;
        case Sensor.TYPE_MAGNETIC_FIELD:
            geomag = sensorEvent.values.clone();
            break;
    }

    // If gravity and geomag have values then find rotation matrix
    if (gravity != null && geomag != null) {

        // checks that the rotation matrix is found
        boolean success = SensorManager.getRotationMatrix(inR, I,
                                                          gravity, geomag);
        if (success) {
            SensorManager.getOrientation(inR, orientVals);
            azimuth = Math.toDegrees(orientVals[0]);
            pitch = Math.toDegrees(orientVals[1]);
            roll = Math.toDegrees(orientVals[2]);
        }
    }
}

4
方位角、ピッチ、ロールは非推奨のOrientationSensorからの出力と同じではないことを述べてください。orientation[0] = orientation[0] >= 0 ? orientation[0]: orientation[0] + 360;方位角if (orientation[1] <= -90) { orientation[1] += (-2*(90+orientation[1])); } else if(orientation[1] >= 90){ orientation[1] += (2*(90 - orientation[1])); }を正規化し、ピッチを正規化します
ラファエルT

@RafaelTとロールを正規化しますか?それとも意味がありませんか?
Matthias

@RafaelT:方位角の正規化が影響を及ぼしているようです。値は[-180,180]から[0、360]に変わります。ただし、取得するピッチ値はすでに[-90,90]にあるため、提案する正規化は効果がありません。
Matthias

(gravity!= null && geomag!= null)をチェックした後、タブレットをどのように動かしてもgeomagの値が常に0になるとはどういう意味ですか?ジオマグセンサーのないタブレットかもしれませんか?
高度

3

ロールは重力の関数であり、90度のロールはすべての重力をxレジスタに入れます。

ピッチは同じです。90度のピッチアップでは、重力のすべてのコンポーネントがyレジスタに配置されます。

ヨー/ヘッディング/方位角は重力に影響を与えません。重力に対して常に直角であるため、重力にどの方向を向いているかは測定できません。

これが、評価にコンパスが必要な理由です。多分それは理にかなっていますか?



0

私はこの問題を抱えていたので、さまざまな方向で何が起こるかを考えました。デバイスが横向きに取り付けられている場合、たとえば自動車のマウントでは、コンパスからの「度」が0-275(時計回り)から269(西と北の間)を超えているように見え、-90から0まで逆にカウントされます。 0から269に転送します。270は-90になります

まだ横長ですが、デバイスが仰向けに置かれていると、私のセンサーは0〜360になります。ポートレートモードでは、背中を横にしてポートレートで立ち上がる0〜360の範囲で実行されます。

誰かを助けることを願っています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.