我只需要使用GPS就可以准确测量海拔高度。
我试过Location.getAltitude()
,但这非常不准确。
有什么建议吗?
答案 0 :(得分:52)
使用智能手机/平板电脑GPS的高度存在两个问题:
答案 1 :(得分:4)
另一种方法是解析NMEA字符串。 $GPGGA sentence已包含海拔以上的校正高度数据。
因此,只需为您的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]);
}
}
}
}
您可以替换通过位置侦听器接收的最后一个Location对象的高度,也可以通过NMEA解析整个新位置。
答案 2 :(得分:1)
除了GPS之外,还有其他方法可以获得高度。您可以使用气压计,但因为没有那么多具有气压传感器的设备(只有新的气压计)。我建议使用Web服务来获取所需的数据。
以下是一个可以帮助您完成问题的问题:Get altitude by longitude and latitude in Android
答案 3 :(得分:1)
如果设备具有气压计,则使用该气压计可以提高相对精度。我并不是要使用气压计来计算相对于海平面的高度,正如可以在几个公式中找到的那样,因为高度高度依赖于天气条件。
您要做的是在知道设备具有良好的定位以及高精度值的情况下获取GPS高度。此时,您将获取大气压力并将该压力作为参考。
当压力增加约12 hPa时,您会知道您的海拔降低了约100 m(https://en.wikipedia.org/wiki/Atmospheric_pressure“ 在海拔高度较低的低海拔处,压力降低了约1.2 kPa(12 hPa)每100米。“)。
不要将该值作为一个精确值,但是GPS所确定的高度变化会由于树木覆盖视线和其他因素而变化很大,而在这些条件下气压计将保持非常精确。
下图是持续时间约1小时20分钟的自行车骑行时间。通过GPS确定,起点和终点在海拔477 m处相同。测得的压力为1015.223 hPA。
最低点是377 m,测得的压力是1025.119 hPa。因此,在这种情况下,100 m相差10 hPa。
最高点为550 m,实测压力为1007.765 hPa。
终点是相同的高度,并且压力与开始条件完全相同(压力可能会因天气条件而变化,但没有变化)。温度下降了大约1°C,因此温度一直保持恒定。
包含许多变化的黑线是通过GPS测量的高度,镜像但干净的线是大气压。它的变化很小,仅是因为压力没有像GPS质量那样剧烈变化。这是一条非常平滑,非常精确的曲线。这不是由于滞后。这是用Bosch BME280传感器测量的,该传感器能够检测门的关闭,地板检测的变化,电梯方向,无人机的噪声,其0.2 Pa等于1.7 cm,高度变化400 m时的误差为1 m 。这些传感器集成在某些智能手机中。例如,Pixel 3包含Bosch BMP380。
如果镜像压力图(如黑色虚线所示),您将看到它与GPS高度非常匹配。它比GPS精确得多,但是唯一的问题是您不能将其作为绝对值。
GPS和压力的采样都是在1秒的间隔内进行的,因此d3库中没有进行曲线平滑处理,从而造成了一些错误的印象。
因此,在GPS定位良好的情况下,大约每10-30分钟重新调整一次压力将为您提供一个良好的基础,以便您可以通过两者之间的压力进行海拔高度测量。
答案 4 :(得分:0)
对于新来者,我制作了一个库,将LocationManager包装到rxjava可观察对象中,并添加了一些可观察的帮助程序,以从Nmea / GPGGA mre info here
获取海平面高度答案 5 :(得分:0)
另一种方法是从气压计测量高度。
通过使用压力,您可以计算用户的高度。我不确定此方法的精确度以及它是否比其他答案的方法更准确。
通过使用hypsometric formula,您可以计算高度:
变量定义:
P0: Sea-level pressure
P: Atmospheric pressure
T: Temperature
获得android系统的压力
SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)
答案 6 :(得分:0)
有些库(例如开源CS-Map)提供了可以在大型表中进行这些查找的API。您指定坐标,它会告诉您需要将该高度应用于该位置处的椭球高度的高度偏移量。
注意:以前使用过CS-Map,插入它并不是5分钟的直接工作。提前警告您,它比调用一组带有lat-long的API更复杂。坐标并返回高度。 我不再在我们从事此类工作的公司工作,因此很遗憾,无法查找代码以确切说明要调用的API。
现在(2019年)在Google上进行搜索,看来CS-Map已被合并到OSGeo中的“ Open Source Geospatial Foundation”项目中的MetaCRS中。相同的搜索使我进入了this old CS-Map wiki和the PROJ GitHub page,其中PROJ似乎与CS-Map类似。
答案 7 :(得分:0)
我建议使用 NmeaListener 作为标准 在his answer中建议。但是,根据NMEA documentation,“ $ 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!
}
}