Мне нужно получить точное измерение высоты, используя только GPS.
Я пробовал Location.getAltitude()
, но это ужасно неточно. Любой совет?
Мне нужно получить точное измерение высоты, используя только GPS.
Я пробовал Location.getAltitude()
, но это ужасно неточно. Любой совет?
Есть две проблемы с использованием высоты смартфона/планшета GPS:
Другим способом будет синтаксический анализ строк 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.
Есть другие способы получить высоту, чем GPS. Вы можете использовать барометр, но пока еще не так много устройств с барометрическими датчиками (только новые). Я рекомендую использовать веб-службу для получения желаемых данных.
Вот вопрос, который должен вам помочь: Получить высоту по долготе и широте в Android
Другой подход заключается в измерении высоты от барометра.
Используя давление, вы можете рассчитать высоту пользователя. Я не уверен в точности уровня этого и является ли он более точным, чем другой подход ответа.
С помощью гипсометрической формулы вы можете рассчитать высоту:
Определение переменной:
P0: Sea-level pressure
P: Atmospheric pressure
T: Temperature
Вы можете получить давление в Android от датчиков окружающей среды
SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)
Для новичков я создал библиотеку, которая оборачивает LocationManager в наблюдаемые rxjava и добавляет несколько наблюдаемых помощников, чтобы получить высоту уровня моря из информации Nmea/GPGGA здесь.
Существуют библиотеки, такие как 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.
Я бы порекомендовал использовать 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!
}
}