Android: Как получить точную высоту?
Мне нужно получить точное измерение высоты, используя только GPS.
Я пробовал Location.getAltitude()
, но это ужасно неточно. Любой совет?
Ответы
Ответ 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!
}
}