[英]How to convert latitude and longitude of NMEA format data to decimal?
我有NMEA格式的经纬度,我想把它转换成十进制值。 有什么公式吗? 例如,NMEA 格式纬度 = 35.15 N 和经度 = 12849.52 E
NMEA 坐标的格式为 (d)ddmm.mmmm
d=度和 m=分钟
一个度数有 60 分钟,因此将分钟数除以 60,然后将其添加到度数中。
对于纬度=35.15 N
35.15/60 = .5858 牛顿
对于经度 = 12849.52 E,
128+ 49.52/60 = 128.825333
在 php 中,你可以这样做:
<?php
$lng = "12849.52 W";
$brk = strpos($lng,".") - 2;
if($brk < 0){ $brk = 0; }
$minutes = substr($lng, $brk);
$degrees = substr($lng, 0,$brk);
$newLng = $degrees + $minutes/60;
if(stristr($lng,"W")){
$newLng = -1 * $newLng;
}
?>
是的,NMEA 格式为 ddmm.mmmm、n/s (d)ddmm.mmmm、e/w
要从度数和分钟数到十进制度数,您可以使用以下公式:
(d)dd + (mm.mmmm/60)(* -1 代表 W 和 S)
这里有一个不错的小计算器: http : //www.hiddenvision.co.uk/ez/
这是一个极简的 C 函数来做到这一点。
它返回十进制坐标,并应提供 NMEA 坐标和相应的象限或“指示器”字符(N、S、E、W)。 例如:
float latitude= GpsToDecimalDegrees("4349.7294",'N');
// latitude == 43.82882
float longitude= GpsToDecimalDegrees("10036.1057",'W');
// latitude == 43.82882
它没有经过优化,但应该是可读的,应该是安全的并且可以完成工作:
/**
* Convert NMEA absolute position to decimal degrees
* "ddmm.mmmm" or "dddmm.mmmm" really is D+M/60,
* then negated if quadrant is 'W' or 'S'
*/
float GpsToDecimalDegrees(const char* nmeaPos, char quadrant)
{
float v= 0;
if(strlen(nmeaPos)>5)
{
char integerPart[3+1];
int digitCount= (nmeaPos[4]=='.' ? 2 : 3);
memcpy(integerPart, nmeaPos, digitCount);
integerPart[digitCount]= 0;
nmeaPos+= digitCount;
v= atoi(integerPart) + atof(nmeaPos)/60.;
if(quadrant=='W' || quadrant=='S')
v= -v;
}
return v;
}
这适用于存在双值问题的小型设备。 它是用 c 代码完成的,但可以轻松地更改为另一种语言:
void GetGPSPos(char *str,char *NMEAgpspos,uint8_t sign)
{
unsigned short int u=0,d=0;
unsigned int minutes;
unsigned char pos,i,j;
for(pos=0;pos<strlen(NMEAgpspos) && NMEAgpspos[pos]!='.';pos++);
for(i=0;i<pos-2;i++)
{
u*=10;
u+=NMEAgpspos[i]-'0';
}
d=(NMEAgpspos[pos-2]-'0')*10;
d+=(NMEAgpspos[pos-1]-'0');
for(i=pos+1,j=0;i<strlen(NMEAgpspos) && j<4;i++,j++) //Only 4 chars
{
d*=10;
d+=NMEAgpspos[i]-'0';
}
minutes=d/60;
sprintf(str,"%d.%04d",(sign?-1:1)*u,minutes);
}
如果您没有 sprintf 或者它不允许“%04”(就像我的情况),只需将 sprintf 行更改为:
pos=0;
if(sign)
str[pos++]='-';
if(u>100)
str[pos++]=u/100+'0';
if(u>10)
str[pos++]=u/10%10+'0';
str[pos++]=u%10+'0';
str[pos++]='.';
str[pos++]=minutes/1000+'0';
str[pos++]=minutes/100%10+'0';
str[pos++]=minutes/10%10+'0';
str[pos++]=minutes%10+'0';
str[pos++]=0;
另一个 C 函数。
这个允许在 nmea 字符串中使用可变数量的小数位。
以 (d)ddmm.mmmm 格式为其提供纬度或经度字符串,
和 N、S、E、W 方向(也作为空终止字符串)。
它将返回一个表示十进制等效值的双精度值。
在 ESP32 上测试(比传统的 arduino 允许更长的浮点精度)
double convertToDecimalDegrees(const char *latLon, const char *direction)
{
char deg[4] = {0};
char *dot, *min;
int len;
double dec = 0;
if ((dot = strchr(latLon, '.')))
{ // decimal point was found
min = dot - 2; // mark the start of minutes 2 chars back
len = min - latLon; // find the length of degrees
strncpy(deg, latLon, len); // copy the degree string to allow conversion to float
dec = atof(deg) + atof(min) / 60; // convert to float
if (strcmp(direction, "S") == 0 || strcmp(direction, "W") == 0)
dec *= -1;
}
return dec;
}
// C# 版本
public double NmeaToDecimal(double ll, int hemisph) { return Math.Round((Convert.ToInt32(ll / 100) + (ll - Convert.ToInt32(ll / 100) * 100) / 60) * hemisph,5); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.