简体   繁体   English

如何将NMEA格式数据的经纬度转换为十进制?

[英]How to convert latitude and longitude of NMEA format data to decimal?

I have latitude and longitude of NMEA format, and I want to convert it into decimal value.我有NMEA格式的经纬度,我想把它转换成十进制值。 Is there any formula?有什么公式吗? For example, NMEA format Latitude = 35.15 N and Longitude = 12849.52 E例如,NMEA 格式纬度 = 35.15 N 和经度 = 12849.52 E

The format for NMEA coordinates is (d)ddmm.mmmm NMEA 坐标的格式为 (d)ddmm.mmmm
d=degrees and m=minutes d=度和 m=分钟
There are 60 minutes in a degree so divide the minutes by 60 and add that to the degrees.一个度数有 60 分钟,因此将分钟数除以 60,然后将其添加到度数中。

For the Latitude=35.15 N对于纬度=35.15 N
35.15/60 = .5858 N 35.15/60 = .5858 牛顿

For the Longitude= 12849.52 E,对于经度 = 12849.52 E,
128+ 49.52/60 = 128.825333 E 128+ 49.52/60 = 128.825333

In php, you could do this:在 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;
}

?>

Yes, NMEA format is ddmm.mmmm, n/s (d)ddmm.mmmm, e/w是的,NMEA 格式为 ddmm.mmmm、n/s (d)ddmm.mmmm、e/w

To get to decimal degrees from degrees ad minutes, you use the following formula:要从度数和分钟数到十进制度数,您可以使用以下公式:

(d)dd + (mm.mmmm/60) (* -1 for W and S) (d)dd + (mm.mmmm/60)(* -1 代表 W 和 S)

There is a nice little calculator here: http://www.hiddenvision.co.uk/ez/这里有一个不错的小计算器: http : //www.hiddenvision.co.uk/ez/

Here is a minimalist C function to do it.这是一个极简的 C 函数来做到这一点。

It returns decimal coordinates and shall be fed with the NMEA coordinate and respective quadrant or "indicator" character (N,S,E,W).它返回十进制坐标,并应提供 NMEA 坐标和相应的象限或“指示器”字符(N、S、E、W)。 Eg:例如:

float latitude= GpsToDecimalDegrees("4349.7294",'N');
// latitude == 43.82882

float longitude= GpsToDecimalDegrees("10036.1057",'W');
// latitude == 43.82882

It is not optimized but should be readable, should be safe and does the job:它没有经过优化,但应该是可读的,应该是安全的并且可以完成工作:

/**
 * 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;
}

This is for small devices where double values are a problem.这适用于存在双值问题的小型设备。 It is done in c code but can be changed to another language easily:它是用 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);
}

if you dont have sprintf or it doesn't allow "%04" (like it is my case), just change the sprintf line for:如果您没有 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;

Another C function.另一个 C 函数。
This one allows for variable number of decimal places in the nmea string.这个允许在 nmea 字符串中使用可变数量的小数位。
Give it the latidude or longitude string in (d)ddmm.mmmm format,以 (d)ddmm.mmmm 格式为其提供纬度或经度字符串,
and the N,S,E,W direction (also as a null terminated string).和 N、S、E、W 方向(也作为空终止字符串)。
It will return a double representing the decimal equivalent.它将返回一个表示十进制等效值的双精度值。


Tested on ESP32 (which allows longer float precision than conventional arduino)在 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# version // C# 版本

public double NmeaToDecimal(double ll, int hemisph) { return Math.Round((Convert.ToInt32(ll / 100) + (ll - Convert.ToInt32(ll / 100) * 100) / 60) * hemisph,5); 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM