Android:如何获取准确的高度?

发布于 2025-01-08 00:58:27 字数 92 浏览 2 评论 0原文

我需要仅使用 GPS 来准确测量高度。

我尝试了 Location.getAltitude(),但这非常不准确。 有什么建议吗?

I need to get an accurate measurement of altitude using GPS only.

I tried Location.getAltitude(), but that is terribly inaccurate.
Any advice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

南城旧梦 2025-01-15 00:58:27

使用智能手机/平板电脑 GPS 的高度有两个问题:

  1. 高度是 WGS84 参考椭球上方的高度。它不是高于地面或海平面的高度。以下是更多详细信息: http://www.gpspassion.com/forumsen/ topic.asp?TOPIC_ID=10915。这个错误是可以纠正的;以下是如何手动执行此操作的说明: http://www.unavco.org/ edu_outreach/tutorial/geoidcorr.html。网络文章链接到一个计算器以获取大地水准面高度以进行校正;我不知道是否还有可用于此计算的网络服务。
  2. 对于相对便宜的 GPS 接收器来说,GPS 高度非常不准确。这是一篇相关文章:http://gpsinformation.net/main/altitude.htm。解决这种不准确性的一种方法是过滤高度数据。我使用圆形数组数据结构来记住最后几个(我使用了 4 个)高度读数并计算平均值。这足以为我的应用获得相对准确的垂直速度读数。

There are two issues with using altitude of a smartphone / tablet GPS:

  1. The altitude is the altitude above the WGS84 reference ellipsoid. It is not the altitude above ground level or sea level. Here is more detail on that: http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=10915. This error can be corrected; here is a description how to do that by hand: http://www.unavco.org/edu_outreach/tutorial/geoidcorr.html. The web article links to a calculator to get the Geoid height for correction; I do not know if there is also a web service available for this computation.
  2. The GPS altitude is terribly inaccurate for relatively cheap GPS receivers. Here is an article on that: http://gpsinformation.net/main/altitude.htm. One method to cope with this kind of inaccuracy is to filter the altitude data. I used a circular array data structure to remember the last few (I used 4) altitude readings and compute the average. This sufficed to get a relatively accurate reading of vertical speed for my application.
心不设防 2025-01-15 00:58:27

另一种方法是解析 NMEA 字符串。 $GPGGA 语句 已包含修正后的海拔高度数据。

因此,只需为 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 解析整个新位置。

Another way would be parsing NMEA strings. The $GPGGA sentence already contains the corrected altitude data above sea level.

So, simply create a listener to NMEA-strings for your LocationManager and parse the messages:

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]);
                }
            }
        }
    }

You can either replace the altitude of the last Location object received through a location listener, or parse the whole new location through NMEA.

奈何桥上唱咆哮 2025-01-15 00:58:27

另一种方法是通过气压计测量高度。

通过使用压力,您可以计算用户的海拔高度。我不确定它的精度水平以及它是否比其他答案的方法更准确。

通过使用测压公式,您可以计算海拔高度:

hypsometric公式

变量定义:

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

您可以从环境传感器获取android中的压力

SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)

Another approach is to measure the altitude from the barometer.

By using the pressure you can calculate the user's altitude. I'm uncertain of the precision level of this and whether it is more accurate than the other answer's approach.

By using the hypsometric formula you can calculate the altitude:

hypsometric formula

Variable definition:

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

You can get the pressure in android from the environment sensors

SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE,pressure)
烧了回忆取暖 2025-01-15 00:58:27

如果设备有气压计,那么使用它可以提高相对精度。我并不是想使用气压计来计算相对于海平面的高度,这可以在几个公式中找到,因为这高度依赖于天气条件。

当您知道设备具有良好的定位且具有高精度值时,您想要做的是获取 GPS 高度。此时,您获取气压并将该压力设置为参考。

当气压增加约 12 hPa 时,您会知道您的海拔高度降低了约 100 m ( https:// en.wikipedia.org/wiki/Atmospheric_Pressure在海拔较低的地方,每升高 100 度,气压就会降低约 1.2 kPa (12 hPa)米。”)。

不要将该值视为精确值,但由于树木遮挡视线和其他因素,GPS 确定的高度变化很大,而气压计在这些条件下将保持非常精确。

下图是骑行时间约为 1 小时 20 分钟的情况。起点和终点相同,均在海拔 477 m 左右,由 GPS 确定。测得的压力为 1015.223 hPA。

最低点为377 m,实测气压为1025.119 hPa。因此,在这种情况下,100 m 会产生 10 hPa 的差异。

最高点550 m,实测气压1007.765 hPa。

终点与起始条件具有相同的高度和完全相同的压力(压力可能会因天气条件而变化,但事实并非如此)。温度下降了 1°C 左右,所以一切都相当稳定。

包含许多变化的黑线是通过 GPS 测量的高度,镜像但干净的线是气压。它的变化非常小,只是因为压力的变化不像 GPS 质量那样剧烈。这是一条非常平滑、非常精确的曲线。这不是由于滞后。这是用博世BME280传感器测量的,该传感器能够检测门的关闭、楼层检测、电梯方向、无人机,噪音为0.2 Pa(相当于1.7厘米),400m高度变化时误差为1m 。一些智能手机中集成了此类传感器。例如,Pixel 3 包含 Bosch BMP380。

如果镜像压力图(如黑色虚线所示),您会发现它与 GPS 高度非常匹配。它比 GPS 精确得多,但唯一的问题是你不能将其视为绝对值。

GPS 和压力的样本都是以 1 秒的间隔采集的,因此 d3 库没有进行曲线平滑,从而导致一些错误的印象。

,当您的 GPS 定位良好时,也许每 10-30 分钟重新调整一次压力将为您提供一个良好的基础,以便通过其间的压力进行高度测量。

If the device has a barometer, then using it can improve the relative accuracy. I don't mean to use the barometer to compute the height in relation to the sea level, as can be found in several formulas, as this is highly dependent of the weather conditions.

What you want to do is to get the GPS-altitude when you know that the device has a good fix, with high accuracy values. At that point you fetch the barometric pressure and set that pressure as a reference.

When the pressure increases around 12 hPa, you will know that your altitude decreased by around 100 m ( https://en.wikipedia.org/wiki/Atmospheric_pressure "At low altitudes above sea level, the pressure decreases by about 1.2 kPa (12 hPa) for every 100 metres." ).

Don't take that value as an exact, but variations in the altitude determined by GPS vary a lot due to trees covering the line of sight and other factors, while the barometer will remain very precise under those conditions.

The following graph is a bike ride of around one hour and 20 minutes in duration. Starting point and end point are the same at around 477 m above sea level, determined via GPS. The measured pressure is 1015.223 hPA.

The lowest point is 377 m, with a measured pressure of 1025.119 hPa. So in that case, 100 m make a difference of 10 hPa.

The highest point is 550 m, with a measured pressure of 1007.765 hPa.

Ending point is the same height, and the exact same pressure as the starting conditions (the pressure could have varied due to the weather conditions, but it didn't). The temperature dropped around 1°C, so it was all pretty constant.

The black line containing the many variations is the altitude measured via GPS, the mirrored, but clean line, is the barometric pressure. It has very little variation in it simply because the pressure doesn't vary as wild as the GPS-quality. It is a very smooth, very precise curve. This is not due to lag. This is measured with a Bosch BME280 sensor, which is capable of detecting the closing of a door, change of floor detection, elevator direction, drones, with a noise of 0.2 Pa which equals 1.7 cm and an error of 1m at 400m of height change. These kind of sensors are integrated in some Smartphones. For example, the Pixel 3 contains a Bosch BMP380.

If you mirror the pressure graph, as is shown with the dotted black line, you will see that it very closely matches the GPS altitude. It is much more precise than GPS, but the only problem is that you can't take it as an absolute value.

The samples of GPS and pressure were both taken in 1 second intervals, so there is no curve smoothing from the d3 library causing some false impressions.

enter image description here

So maybe readjusting the pressure around every 10-30 minutes while you have a GPS good fix will give you a good base to perform your altitude measurements by pressure in between.

迷你仙 2025-01-15 00:58:27

除了 GPS 之外,还有其他方法可以获得高度。您可以使用气压计,但目前还没有那么多带有气压传感器的设备(只有新设备)。我建议使用网络服务来获取所需的数据。

这是一个应该可以帮助您解决的问题: 在 Android 中通过经度和纬度获取高度

There are other ways to get the altitude than by GPS. You can use the barometer but as there isn't that many devices with a barometric sensors yet (only the new ones). I will recommend to use a web service to acquire the desired data.

Here is a question which should help you through: Get altitude by longitude and latitude in Android

鲜肉鲜肉永远不皱 2025-01-15 00:58:27

对于新手,我制作了一个库,将 LocationManager 包装到 rxjava observables 中,并添加一些可观察的帮助程序,以从 Nmea/GPGGA mre 信息获取海平面高度

For newcomers I made a library that wrap LocationManager into rxjava observables and add some observable helpers to get sea level altitutde from Nmea/GPGGA mre info here

何止钟意 2025-01-15 00:58:27

有一些库(例如开源 CS-Map)提供了在大型表中执行这些查找的 API。您指定坐标,它会告诉您需要应用于该位置的椭球体高度以获得“真实世界”的正交高度的高度偏移。

注意:之前使用过 CS-Map,将其插入并不是完全简单的 5 分钟工作。提前警告您,它比使用一组经纬度坐标调用单个 API 并获取更复杂退了一个高度。 我不再在我们从事此类工作的公司工作,因此遗憾的是无法查找代码来准确说明要调用哪个 API。

现在(2019 年)在 google 上搜索它,看来 CS-Map 已合并到 OSGeo 中的 MetaCRS,即“开源地理空间基金会”项目。同样的搜索让我找到了这个旧的 CS-Map wiki 以及 PROJ GitHub 页面,其中 PROJ 似乎是与 CS-Map 类似的项目。

There are libraries, such as the open-source CS-Map which provide an API that do these lookups in large tables. You specify the coordinates, and it will tell you the height offset that needs to be applied to the ellipsoidal height at that location to get the "real-world" orthometric height.

Note: Having used CS-Map before, it isn't exactly straight-forward 5-minute job to plug it in. Warning you in advance that it is more complicated than calling a single API with a set of lat-long coordinates and getting back a height. I no longer work at the company where we were doing this kind of work, so unfortunately cannot look up the code to say exactly which API to call.

Doing a google search for it right now (2019), it seems CS-Map has been merged into MetaCRS in OSGeo, the "Open Source Geospatial Foundation" project. That same search led me to this old CS-Map wiki as well as the PROJ GitHub page, where PROJ seems to be similar project to CS-Map.

寄意 2025-01-15 00:58:27

我建议使用 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!
    }
}

I would recommend using NmeaListener, as sladstaetter
suggested in his answer. However, according to NMEA documentation, "$GPGGA" is not the only sentence you can get. You should look for any "GGA" sentence ($--GGA).

Regular expressions are great for that, e.g.:

@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!
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文