GPS 将 16 位十六进制值转换为经度和纬度

Posted

技术标签:

【中文标题】GPS 将 16 位十六进制值转换为经度和纬度【英文标题】:GPS conversion 16digit hexadecimal value to longitude and latitude 【发布时间】:2021-12-26 16:05:00 【问题描述】:

从设备我得到以下类型的十六进制值 3305511C0424573C(存储在 sql 数据库中)。我需要从中得到经度和纬度。

我也得到这种格式的经度和纬度值(单精度浮点数):

经度 = 1083419342 纬度 = 1112302388

我知道结果是:

经度 = 4.6146 纬度 = 51.09688

我尝试在 C# 中编写多个转换代码,但所有结果都不正确。

来自 sql server 的数据:

StreamID = 15620,GPS0 = 3305511C0424573C,GPS1 = 0000000000000000,GPS 经度 = 1083419342,GPS 纬度 = 1112302388

标签 = GPS 经度,单位 = 度,DataItemType = 单精度浮点数,精度 = 0,字节位置 = 11 label = GPS 纬度,Unit = 度,DataItemType = Single-Precision Float,Precision = 0,BytePosition = 12

数据如何进入 sql 对我来说是个未知数。

我如何使用坐标:<script> var XMarker = L.marker([51.09688, 4.6146]).addTo(mymap); </script> 这是您需要在您的 html 或 web 应用程序中添加的内容,以在您的地图上获得由 leafletjs 创建的额外标记(链接:leafletjs.com)

因此我需要知道转换来自:

3305511C0424573C -> 经度 = 4.6146,纬度 = 51.09688 330D262A030C1247 -> 经度 = 3.19325013523526,纬度 = 51.222186941538

C# 答案

public static double GPSCoordinateConversion(string GPSCoordinate)
    
        double coordinate = 0;
        byte[] _byte = new byte[GPSCoordinate.Length / 2];
        double value1 = 0;
        double value2 = 0;

        for (int i = 0; i < _byte.Length; i++)
        
            string byteValue = GPSCoordinate.Substring(i * 2, 2);
            _byte[i] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
        

        value1 = Convert.ToDouble(_byte[2]) / 100;
        value2 = Convert.ToDouble(_byte[3]) / 10000;

        coordinate = Convert.ToDouble(_byte[0] + ((_byte[1]+value1+value2) / 60));

        return coordinate;
    

    public static double GetLatitude(string GPSHexCoordinate)
    
        double latitude = 0;

        latitude = GPSCoordinateConversion(GPSHexCoordinate.Substring(0, 8));

        return latitude;
    
    public static double GetLongitude(string GPSHexCoordinate)
    
        double longitude = 0;

        longitude = GPSCoordinateConversion(GPSHexCoordinate.Substring(8, 8));

        return longitude;
    

【问题讨论】:

您使用的是哪个 dbms? 我使用的是 microsoft SQL server management studio,但我使用 C# (visual studio) 制作的应用程序读取了 sql server。在我想要进行转换的应用程序代码中。 我不是第一次看到这样的数据,但据我所知,如何转换它并没有明确的答案。你能从众所周知的坐标中计算出上述数字吗?这将有助于找出编码 ***.com/questions/17355604/… 经度 (4.6146) 和纬度 (51.09688) 是 3305511C0424573C 的正确结果。我希望坐标保持这种格式,我可以直接在leaflet.js插件中输入。 【参考方案1】:

您要求找到两种不同的解码方式。

第一部分(原始问题),是关于转换

longitude = 1083419342
latitude = 1112302388

longitude = 4.6146
latitude = 51.09688

数字是现代计算机上的浮点数的整数表示(因此 IEEE 754 单精度二进制表示和普通整数表示。[注意:我们没有负数,所以我们不知道符号是怎样的代表]

算法(第一个问题)

获取每个数字(不带分隔字段的C) 将其转换为字节数组(4 个字节) 读取浮点数等字节(浮点数具有标准格式)。

在 C 中,uint32_tfloat 之间的联合。在 Python 中struct.unpack('&gt;f', bytearray.fromhex(hex(your_number)[2:])。 C# 有 BitConverter,您可以在 bitconverter documentation 中看到一个示例。我让对方写一个正确的 C# 答案。注意:我们仍然需要测试负数,但它们应该没问题(几个月前我们收到了与澳大利亚类似的问题,因此是负纬度)。

现在,你问的是十六进制数字表示,这与第一个问题无关(所以你的软件已经做了如何转换坐标)。

问题是我无法获得精确的坐标,但我非常精确,误差高达 0.02 度。也许还有一个基准转换(您的坐标 WGS84 是否符合 GPS 的预期?)。还是数据库将坐标转换成不同的数据?

无论如何第二种编码的解决方案:

将字符串分成两半 8 个字符。前半部分是纬度,后半部分是经度。

第一组两个字符是度数

第二组两个字符是质数(或分钟)。所以你应该把坐标写成 4'36"52.56, 3'11"35.70, 51'5"48.77, 51'13"19.87

那我不知道。可能第二组是第二组,然后是两位小数,或者可能是四位小数。

再次:我不知道负纬度或经度是如何编码的。考虑到经度可以有 360 个值,但在两个字符中您最多只能编码 256 个值。

几个月前我再也找不到类似的问题(未回答),澳大利亚坐标。这可能有助于证实这一点。但是您可以尝试更多的坐标,并检查错误(也许要找出是否还有基准转换[因此有两种不同的坐标约定])。但我认为(只有 4 个数据)这样的方法已经足够精确了。

【讨论】:

我在 wpf 应用程序中尝试了这个作为测试并得到以下结果:纬度 6.915902E-22,经度 0.01313115。位转换器代码为:float value1 = BitConverter.ToSingle(byteLatitude, 0)。切掉 C 也不是一种选择,然后 bitconverter 抱怨。 我用的是python版本,得到了正确的结果,所以我想现在是我不太了解的部分:C#。但我不明白你在做什么。取数字(不带C),转换为数字。然后提取 4 个字节(移位和位与操作,或仅模块 256 操作,4 次)。然后将这 4 个字节放入 bitConverter。 EV。颠倒顺序。 我添加了我的测试代码和一个额外的坐标示例:330D262A030C1247 -> 经度 = 3.19325013523526,纬度 = 51.222186941538 错误是您将字符串拆分为2个字符并转换为字节。你应该使用这个3305511 作为整数,然后你会找到这个字符串的字节(div/mod 256)[它们应该正好是 4 个字节]。然后你在 BitConverter 中给出这个。 [你有一个十进制数字,而不是十六进制数字,所以你不能一次用 2 个字符进行快捷方式] 但在第二个示例中,很明显给定的 GPS 字符串是十六进制而不是整数。可以给python代码吗?【参考方案2】:

从 3305511C0424573C 到经度 = 4.6146 和纬度 = 51.09688 的转换如下。

    将 16 个字符分成两个单独的 8 个字符的字符串。

    将 8 个字符长的字符串拆分为 4 个字节(2 个字符长)的字节数组。

    那么计算如下:byte[0]+((Byte[1]+(byte[2]/100)+(byte[3]/10000))/60)

对经度和纬度执行这些步骤。

    public static double GPSCoordinateConversion(string GPSCoordinate)
    
        double coordinate = 0;
        byte[] _byte = new byte[GPSCoordinate.Length / 2];
        double value1 = 0;
        double value2 = 0;

        for (int i = 0; i < _byte.Length; i++)
        
            string byteValue = GPSCoordinate.Substring(i * 2, 2);
            _byte[i] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
        

        value1 = Convert.ToDouble(_byte[2]) / 100;
        value2 = Convert.ToDouble(_byte[3]) / 10000;

        coordinate = Convert.ToDouble(_byte[0] + ((_byte[1]+value1+value2) / 60));
        return coordinate;
    

    public static double GetLatitude(string GPSHexCoordinate)
    
        double latitude = 0;
        latitude = GPSCoordinateConversion(GPSHexCoordinate.Substring(0, 8));
        return latitude;
    

    public static double GetLongitude(string GPSHexCoordinate)
    
        double longitude = 0;
        longitude = GPSCoordinateConversion(GPSHexCoordinate.Substring(8, 8));
        return longitude;
    

【讨论】:

以上是关于GPS 将 16 位十六进制值转换为经度和纬度的主要内容,如果未能解决你的问题,请参考以下文章

如何在目标c中将gps北和gps西转换为纬度/经度

python 纬度经度十进制/十六进制转换

Orchid Tracking 软件 - 如何将十进制值转换为 GPS 度/分/秒

Ruby 将 64 位 IEEE 754 十六进制转换为双精度

如何将 GPS exif 转换为地理?

将 GPS 纬度/经度从不同格式转换为一种格式(在 PHP 中)