web-dev-qa-db-ja.com

Android:正確な高度を取得する方法は?

GPSのみを使用して高度の正確な測定値を取得する必要があります。

Location.getAltitude()を試しましたが、それはひどく不正確です。何かアドバイス?

52
ask

スマートフォン/タブレットGPSの高度の使用には2つの問題があります。

  1. 高度は、WGS84基準楕円体より上の高度です。地上または海抜からの高度ではありません。詳細は次のとおりです。 http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=10915 。このエラーは修正できます。これを手動で行う方法について説明します: http://www.unavco.org/edu_outreach/tutorial/geoidcorr.html 。ウェブ記事は電卓にリンクして、補正のためにジオイドの高さを取得します。この計算に利用できるWebサービスもあるかどうかはわかりません。
  2. GPSの高度は、比較的安価なGPS受信機にとっては非常に不正確です。これに関する記事は次のとおりです。 http://gpsinformation.net/main/altitude.htm 。この種の不正確さに対処する1つの方法は、高度データをフィルタリングすることです。円形配列データ構造を使用して、最後の(4つ使用した)高度測定値を記憶し、平均を計算しました。これで、アプリケーションの垂直速度を比較的正確に読み取ることができました。
57
Stefan

別の方法は、NMEA文字列を解析することです。 $ GPGGA文 には、すでに海抜高度の修正された高度データが含まれています。

そのため、LocationManagerのNMEA文字列のリスナーを作成し、メッセージを解析します。

private GpsStatus.NmeaListener mNmeaListener = new GpsStatus.NmeaListener() {
    @Override
    public void onNmeaReceived(long timestamp, String nmea) {
        parseNmeaString(nmea);
    }
};

public void registerLocationManager(Context context) {
        mLocationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
        mLocationManager.addNmeaListener(mNmeaListener);
}

private void parseNmeaString(String line) {
        if (line.startsWith("$")) {
            String[] tokens = line.split(",");
            String type = tokens[0];

            // Parse altitude above sea level, Detailed description of NMEA string here http://aprs.gids.nl/nmea/#gga
            if (type.startsWith("$GPGGA")) {
                if (!tokens[9].isEmpty()) {
                    mLastMslAltitude = Double.parseDouble(tokens[9]);
                }
            }
        }
    }

ロケーションリスナーを介して受信した最後のロケーションオブジェクトの高度を置き換えるか、NMEAを介して新しいロケーション全体を解析できます。

4
sladstaetter

別のアプローチは、気圧計から高度を測定することです。

圧力を使用して、ユーザーの高度を計算できます。私はこれの精度レベルと、それが他の答えのアプローチよりも正確であるかどうかはわかりません。

hypsometric formula を使用すると、高度を計算できます。

hypsometric formula

変数定義:

P0: Sea-level pressure 
P: Atmospheric pressure 
T: Temperature 

圧力はAndroidから 環境センサー

SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)
1
Jonas Praem

GPS以外の方法で高度を取得する方法があります。気圧計を使用できますが、気圧センサーを備えたデバイスはまだ多くないため(新しいデバイスのみ)。 Webサービスを使用して目的のデータを取得することをお勧めします。

ここにあなたを助けるべき質問があります: Androidの経度と緯度で高度を取得する

1
7heViking

大きなテーブルでこれらの検索を行うAPIを提供するオープンソースのCS-Mapなどのライブラリがあります。座標を指定すると、その位置の楕円体の高さに適用する必要がある高さのオフセットがわかり、「現実の」オルソメトリックの高さが取得されます。

注:以前にCS-Mapを使用したことがあるので、プラグインするのは簡単な5分間の作業ではありません。事前に、緯度経度座標のセットで単一のAPIを呼び出して取得するよりも複雑であることを警告します高さに戻る。 私はこの種の仕事をしている会社で働いていないので、残念ながら、どのAPIを呼び出すかを正確に言うためにコードを検索することはできません。

Google検索で今すぐ(2019)、CS-MapがOSGeoのMetaCRSに統合されたようです。これは、「 Open Source Geospatial Foundation 」プロジェクトです。同じ検索で この古いCS-Map wikiPROJ GitHubページ に至りました。PROJはCS-Mapと同様のプロジェクトのようです。

0
Stéphane

初心者の場合、LocationManagerをrxjavaオブザーバブルにラップし、Nmea/GPGGAから海面高度を取得するためのオブザーバブルヘルパーを追加するライブラリを作成しましたmre info here

0
Samuel Eminet

Sladstaetterが his answer で提案したように、NmeaListenerを使用することをお勧めします。ただし、 NMEAドキュメント によると、取得できる文は「$ GPGGA」だけではありません。 「GGA」文($-GGA)を探す必要があります。

そのためには、正規表現が最適です:

@Override
public void onNmeaReceived(final long timestamp, final String nmea) {
    final Pattern pattern = Pattern.compile("\\$..GGA,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([+-]?\\d+(.\\d+)?),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$");
    final Matcher matcher = pattern.matcher(nmea);
    if (matcher.find()) {
        final float altitude = Float.parseFloat(matcher.group(1));
        // ...enjoy the altitude!
    }
}
0
Berťák