如何从 GPS LocationManager 获取 HDOP 或 VDOP 值?

Posted

技术标签:

【中文标题】如何从 GPS LocationManager 获取 HDOP 或 VDOP 值?【英文标题】:How do I get the HDOP or VDOP values from the GPS LocationManager? 【发布时间】:2011-10-23 00:39:10 【问题描述】:

如何从 GPS LocationManager 获取HDOP or VDOP values?

【问题讨论】:

【参考方案1】:

GPS_Location:

double lo=gps_loc.getLongitude();
double la=gps_loc.getLatitude();

水平精度:

int horiAcc=(int)(gps_loc.getAccuracy());

HDOP:

int hd= (int) (horiAcc/5);

【讨论】:

能否解释一下最后一个公式。为什么要制作 div 5? div 5 看起来像是某种近似值,osmtracker 使用了值 4:github.com/nguillaumin/osmtracker-android/blob/master/src/me/… 5 是 5 米,这是您使用的 GPS 设备的估计精度。您可以从芯片制造商规范中获得它(如果您知道手机中的芯片)。 4 或 5 米对手机来说是好的 - 如果您知道设备精度,您可以计算 HDOP,或者您可以直接从 NMEA 读取 HDOP,请参阅下面的答案。【参考方案2】:

要获取 HDOP、VDOP、PDOP、DGPSID 和 AGEOFDGPSDATA 使用GpsStatus.NmeaListener 并实现onNmeaReceived()

protected String latestHdop;
protected String latestPdop;
protected String latestVdop;
protected String geoIdHeight;
protected String ageOfDgpsData;
protected String dgpsId;


@Override
public void onNmeaReceived(long timestamp, String nmeaSentence) 
    loggingService.OnNmeaSentence(timestamp, nmeaSentence);

    if(Utilities.IsNullOrEmpty(nmeaSentence))
        return;
    

    String[] nmeaParts = nmeaSentence.split(",");

    if (nmeaParts[0].equalsIgnoreCase("$GPGSA")) 

        if (nmeaParts.length > 15 && !Utilities.IsNullOrEmpty(nmeaParts[15])) 
            this.latestPdop = nmeaParts[15];
        

        if (nmeaParts.length > 16 &&!Utilities.IsNullOrEmpty(nmeaParts[16])) 
            this.latestHdop = nmeaParts[16];
        

        if (nmeaParts.length > 17 &&!Utilities.IsNullOrEmpty(nmeaParts[17]) && !nmeaParts[17].startsWith("*")) 

            this.latestVdop = nmeaParts[17].split("\\*")[0];
        
    


    if (nmeaParts[0].equalsIgnoreCase("$GPGGA")) 
        if (nmeaParts.length > 8 &&!Utilities.IsNullOrEmpty(nmeaParts[8])) 
            this.latestHdop = nmeaParts[8];
        

        if (nmeaParts.length > 11 &&!Utilities.IsNullOrEmpty(nmeaParts[11])) 
            this.geoIdHeight = nmeaParts[11];
        

        if (nmeaParts.length > 13 &&!Utilities.IsNullOrEmpty(nmeaParts[13])) 
            this.ageOfDgpsData = nmeaParts[13];
        

        if (nmeaParts.length > 14 &&!Utilities.IsNullOrEmpty(nmeaParts[14]) && !nmeaParts[14].startsWith("*")) 
            this.dgpsId = nmeaParts[14].split("\\*")[0];
        
    

从Lightweight GPS Logging Application For Android找到实现

【讨论】:

【参考方案3】:

您可以从 GpsStatus 对象中的 GpsSatellite 对象中获得 DOP 值的粗略估计(技术上它是原始值)。这使得您无需解析 NMEA 字符串,而且您不仅可以获得 H(水平)、V(垂直)和 P(位置)DOP;您还可以获得 N(orth)、E(ast)、T(ime) 和 G(eometric) DOP。

对于每个 GpsSatellite 对象,您需要获取仰角、方位角、usedInFix 和 snr。 首先过滤掉所有卫星,只保留snr>0和usedInFix==true的卫星。

为每个卫星创建一个矩阵,其中每个卫星代表矩阵中的一行(表示为双精度数组)以创建我们将调用 A 的矩阵:

注意:要使其正常工作,您至少需要 4 颗卫星

el=高度,单位为 弧度

az=方位角,单位为弧度

Sv=GpsSatellite 的集合

A[n]=sin(Sv[n].az)*cos(Sv[n].el), cos(Sv[n].az)*cos(Sv[n].el), sin (Sv[n].el), 1d

有趣的部分来了

DOP矩阵方程如下

At = 转置矩阵 A

(At*A)^-1 = inverse(转置(A).times(A)) =

EDOP^2 x x x x NDOP^2 x x x x VDOP^2 x x x x TDOP^2

明显的 DOP:

EDOP = sqrt(EDOP^2)

NDOP = sqrt(NDOP^2)

VDOP = sqrt(VDOP^2)

TDOP = sqrt(TDOP^2)

派生的 DOP:

GDOP = sqrt(EDOP^2+NDOP^2+VDOP^2+TDOP^2)

HDOP = sqrt(EDOP^2+NDOP^2)

PDOP = sqrt(EDOP^2+NDOP^2+VDOP^2)

【讨论】:

对于所有想知道这个数学从何而来的人,它来自books.google.com/…。我使用弧度而不是度数的原因是因为 java 的 Math.sin 和 Math.cos 需要弧度【参考方案4】:

Accuracy 通常指位置类中 GPS 的 HDOP。但是,如果您想要两者都需要,您可以尝试 NmeaListener 获取原始 NMEA 字符串并对其进行解析以获取 HDOP 和 VDOP。

【讨论】:

【参考方案5】:

您需要注册一个NMEAListener 并尝试解析GSA 语句(包含HDOP、VDOP 和PDOP)或GGA 语句(其中包含用于修复的HDOP)。

有关详细信息,请参阅 NMEA 0183 标准。

【讨论】:

以上是关于如何从 GPS LocationManager 获取 HDOP 或 VDOP 值?的主要内容,如果未能解决你的问题,请参考以下文章

当 gps 关闭时,.isProviderEnabled(LocationManager.NETWORK_PROVIDER) 总是返回 false?

如何不断地将 GPS 数据从 android 发送到服务器,直到应用程序关闭

LocationManager-定位方式原理解析

Android LocationManager 标准

无法通过 LocationManager.GPS_PROVIDER 获取 GPS 坐标

不适用于 Android Studio-locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this)