Андроид:Как получить точную высоту?
Вопрос
Мне нужно получить точное измерение высоты только с помощью GPS.
Я пытался Location.getAltitude()
, но это ужасно неточно.Любой совет?
Решение
Есть две проблемы с использованием высоты GPS смартфона / планшета:
- Высота представляет собой высоту над эталонным эллипсоидом WGS84. Это не высота над уровнем земли или уровнем моря. Вот подробно об этом: http://www.gpspassion.com/forumsen/topic.asp?topic_id=10915. Анкет Эта ошибка может быть исправлена; Вот описание, как это сделать вручную: http://www.unavco.org/edu_outreach/tutorial/geoidcorr.html. Анкет Веб -статья ссылается на калькулятор, чтобы получить высоту геоида для коррекции; Я не знаю, есть ли также веб -сервис для этого вычисления.
- Высота GPS ужасно неточна для относительно дешевых GPS -приемников. Вот статья об этом: http://gpsinformation.net/main/altitude.htm. Анкет Одним из методов справиться с такого рода неточности является фильтрация данных высоты. Я использовал структуру данных круговой массивы, чтобы запомнить последние несколько (я использовал 4) показания высоты и вычислил среднее значение. Этого было достаточно, чтобы получить относительно точное чтение вертикальной скорости для моего применения.
Другие советы
Другим способом будет анализ строк NMEA. А $ Gpgga предложение Уже содержит исправленные данные высоты над уровнем моря.
Итак, просто создайте слушателя в NMEA-стринге для вашего местоположения Managemanager и проанализируйте сообщения:
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.
Есть и другие способы получить высоту, чем GPS. Вы можете использовать барометр, но, поскольку еще не так много устройств с барометрическими датчиками (только новые). Я рекомендую использовать веб -сервис для получения желаемых данных.
Вот вопрос, который должен вам помочь: Получить высоту по долготе и широте в Android
Другой подход заключается в измерении высоты от барометра.
Используя давление, вы можете рассчитать высоту пользователя. Я не уверен в том, что он является более точным, и является ли он более точным, чем подход другого ответа.
С помощью Гипсометрическая формула Вы можете рассчитать высоту:
Переменная определение:
P0: Sea-level pressure
P: Atmospheric pressure
T: Temperature
Вы можете получить давление в Android от Датчики окружающей среды
SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)
Для новичков я составил библиотеку, которая обертывает местоположение в Rxjava Observables и добавил несколько наблюдаемых помощников, чтобы получить Altitutde на уровне моря из NMEA/GPGGA MRE здесь
Существуют библиотеки, такие как CS-Map с открытым исходным кодом, которые предоставляют API, выполняющий поиск в больших таблицах.Вы указываете координаты, и они сообщают вам смещение высоты, которое необходимо применить к эллипсоидной высоте в этом месте, чтобы получить «реальную» ортометрическую высоту.
Примечание:Если вы раньше использовали CS-Map, подключить его не так-то просто и займет 5 минут.Заранее предупреждаю, что это сложнее, чем вызывать один API с набором широтных координат и возвращать высоту. Я больше не работаю в компании, где мы выполняли такую работу, поэтому, к сожалению, не могу найти код, чтобы точно сказать, какой API вызывать.
Выполняя поиск в Google прямо сейчас (2019 г.), кажется, что CS-Map был объединен с MetaCRS в OSGeo, "Геопространственный фонд с открытым исходным кодом" проект.Тот же самый поиск привел меня к эта старая вики CS-Map а также страница PROJ на GitHub, где PROJ похож на проект CS-Map.
Я бы порекомендовал использовать 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!
}
}