Подтвердить что ты не робот

Android: Как получить точную высоту?

Мне нужно получить точное измерение высоты, используя только GPS.

Я пробовал Location.getAltitude(), но это ужасно неточно. Любой совет?

4b9b3361

Ответ 1

Есть две проблемы с использованием высоты смартфона/планшета GPS:

  • Высота - это высота над опорным эллипсоидом WGS84. Это не высота над уровнем земли или уровнем моря. Подробнее об этом: http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=10915. Эта ошибка может быть исправлена; вот описание, как это сделать вручную: http://www.unavco.org/edu_outreach/tutorial/geoidcorr.html. Веб-статья ссылается на калькулятор, чтобы получить высоту Geoid для коррекции; Я не знаю, есть ли для этого вычисления веб-сервис.
  • Высота GPS очень неточна для относительно дешевых GPS-приемников. Вот статья о том: http://gpsinformation.net/main/altitude.htm. Одним из способов справиться с такой неточностью является фильтрация данных о высоте. Я использовал структуру данных кругового массива, чтобы запомнить последние несколько (я использовал 4) показания высоты и вычислить среднее значение. Этого достаточно, чтобы получить относительно точное чтение вертикальной скорости для моего приложения.

Ответ 2

Другим способом будет синтаксический анализ строк NMEA. Предложение $GPGGA содержит исправленные данные о высоте над уровнем моря.

Итак, просто создайте прослушиватель для NMEA-строк для вашего LocationManager и проанализируйте сообщения:

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.

Ответ 3

Есть другие способы получить высоту, чем GPS. Вы можете использовать барометр, но пока еще не так много устройств с барометрическими датчиками (только новые). Я рекомендую использовать веб-службу для получения желаемых данных.

Вот вопрос, который должен вам помочь: Получить высоту по долготе и широте в Android

Ответ 4

Другой подход заключается в измерении высоты от барометра.

Используя давление, вы можете рассчитать высоту пользователя. Я не уверен в точности уровня этого и является ли он более точным, чем другой подход ответа.

С помощью гипсометрической формулы вы можете рассчитать высоту:

hypsometric formula

Определение переменной:

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

Вы можете получить давление в Android от датчиков окружающей среды

SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)

Ответ 5

Для новичков я создал библиотеку, которая оборачивает LocationManager в наблюдаемые rxjava и добавляет несколько наблюдаемых помощников, чтобы получить высоту уровня моря из информации Nmea/GPGGA здесь.

Ответ 6

Существуют библиотеки, такие как CS-Map с открытым исходным кодом, которые предоставляют API, который выполняет поиск в больших таблицах. Вы указываете координаты, и он сообщит вам смещение высоты, которое необходимо применить к эллипсоидальной высоте в этом месте, чтобы получить ортометрическую высоту "реального мира".

Примечание. Используя CS-Map ранее, подключить его не так просто, как 5-минутная работа. Заранее предупреждаю, что это сложнее, чем вызов одного API с набором координат долготы и получение вернуться на высоту. Я больше не работаю в компании, где мы выполняли такую работу, поэтому, к сожалению, не могу найти код, чтобы точно сказать, какой API вызывать.

Сейчас, выполняя поиск в Google (2019), кажется, что CS-Map была объединена с MetaCRS в OSGeo, проекте " Open Source Geospatial Foundation ". Тот же поиск привел меня на эту старую вики CS-Map, а также на страницу PROJ GitHub, где PROJ, похоже, похож на CS-Map.

Ответ 7

Я бы порекомендовал использовать NmeaListener, как предложил sladstaetter в своем ответе. Однако, согласно документации 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!
    }
}