본문 바로가기
C, C++

GPS데이터로 거리계산하기 - 소스코드

by I!i어★떤☆날★에Ι!i 2022. 4. 6.
반응형

GPS 데이터를 수신하면 위도(latitude)와 경도(longitude) 정보를 얻을 수 있다. 이 위도와 경도 데이터를 통해 두 GPS 데이터 값을 이용하여 거리 차이를 계산할 수 있다. 두 거리를 프로그래밍해 보고 다양한 애플리케이션에 적용해 보자.

 

* GPS NMEA 메시지 규격

 

GPS로 정보를 수신하면 보통 NMEA라는 규격화된 메시지 포맷을 이용한다. 이 NMEA에는 GGA, GLL등 다양한 GPS 타입에 대한 메시지 포맷을 정의하고 있다. 메시지 정보에는 시간, 위경도 정보, 위성수 등 다양한 정보를 포함하고 있다.

 

https://ko.wikipedia.org/wiki/NMEA_0183

 

NMEA 0183 - 위키백과, 우리 모두의 백과사전

$ELEXTECH, Inc G1800s $HW Version 1.6 $SW Version 231.000.100 $Startup 4 $TOW: 0 $WK: 1192 $POS: 6378137 0 0 $Baud rate: 9600 System clock: 24.553MHz $GPGGA,114455.532,3735.0079,N,12701.6446,E,1,03,7.9,48.8,M,19.6,M,0.0,0000*48 $GPGSA,A,2,19,25,15,,,,,,,,,

ko.wikipedia.org

 

 

* GPS데이터로 이동거리 계산

 

이러한 GPS 데이터 정보 중에서 위도(latitude)와 경도(longitude) 정보를 이용하여 GPS 이동 거리를 계산할 수 있다.

일반적은 두점간의 거리는 제곱근으로 계산하고, 지구에서의 위치를 나타내는 지리좌표는 둥근 지구에서 계산이 되므로 조금 더 복잡한 수식으로 표현된다.

 

https://ko.wikipedia.org/wiki/%EC%A7%80%EB%A6%AC%EC%A2%8C%ED%91%9C_%EA%B1%B0%EB%A6%AC

 

지리좌표 거리 - 위키백과, 우리 모두의 백과사전

지리좌표 거리(Geographical distance)는 경위도좌표계를 기반으로 하는 좌표체계에서 얻어지는 두 지점의 좌표로 부터 측정되는 거리측량을 가리킨다. GPS로 부터 좌표값을 얻어 두 지점간의 지리좌

ko.wikipedia.org

 

* GPS 데이터를 이용한 거리계산 소스코드

 

이러한 수식을 바탕으로 두 GPS값으로 이동 거리를 계산할 수 있다.

나는 잘 짜여져 있는 오픈소스가 있어서 이 코드를 이용하고 있다.

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::                                                                         :*/
/*::  This routine calculates the distance between two points (given the     :*/
/*::  latitude/longitude of those points). It is being used to calculate     :*/
/*::  the distance between two locations using GeoDataSource(TM) products.   :*/
/*::                                                                         :*/
/*::  Definitions:                                                           :*/
/*::    South latitudes are negative, east longitudes are positive           :*/
/*::                                                                         :*/
/*::  Passed to function:                                                    :*/
/*::    lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees)  :*/
/*::    lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees)  :*/
/*::    unit = the unit you desire for results                               :*/
/*::           where: 'M' is statute miles (default)                         :*/
/*::                  'K' is kilometers                                      :*/
/*::                  'N' is nautical miles                                  :*/
/*::  Worldwide cities and other features databases with latitude longitude  :*/
/*::  are available at https://www.geodatasource.com                         :*/
/*::                                                                         :*/
/*::  For enquiries, please contact sales@geodatasource.com                  :*/
/*::                                                                         :*/
/*::  Official Web site: https://www.geodatasource.com                       :*/
/*::                                                                         :*/
/*::           GeoDataSource.com (C) All Rights Reserved 2022                :*/
/*::                                                                         :*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

#include <math.h>

#define pi 3.14159265358979323846

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::  Function prototypes                                           :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
double deg2rad(double);
double rad2deg(double);

double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
  double theta, dist;
  if ((lat1 == lat2) && (lon1 == lon2)) {
    return 0;
  }
  else {
    theta = lon1 - lon2;
    dist = sin(deg2rad(lat1)) * sin(deg2rad(lat2)) + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * cos(deg2rad(theta));
    dist = acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    switch(unit) {
      case 'M':
        break;
      case 'K':
        dist = dist * 1.609344;
        break;
      case 'N':
        dist = dist * 0.8684;
        break;
    }
    return (dist);
  }
}

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::  This function converts decimal degrees to radians             :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
double deg2rad(double deg) {
  return (deg * pi / 180);
}

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::  This function converts radians to decimal degrees             :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
double rad2deg(double rad) {
  return (rad * 180 / pi);
}

 

distance 함수에 GPS1, GPS2의 데이터를 대입하면 거리가 출력된다. 마지막 인자는 옵션으로써,  M(기본값)은 마일(miles), K는 킬로미터(kilometers), N은 해리(nautical miles)를 단위로 계산하게 된다.

 

double my_distance = distance( GPS1.latitude, GPS1.longitude, GPS2.latitude, GPS2.longitude, K );
printf("이동한 거리는 %ld킬로미터 이다.\n", my_distance);

 

 

참고로, 이 코드는 LGPLv3의 라이선스를 갖고 있다. LGPL은 GPL 보다 덜 엄격한 라이선스로써, 응용프로그램을 정적 또는 동적으로 링크시킨다고 해도 소스코드를 공개할 필요는 없다.

 

다음 사이트에 C언어 이외에 Go, Java, JavaScript 등 다양한 언어로 코딩된 코드를 얻을 수 있다.

https://www.geodatasource.com/developers/c

 

Calculate Distance by Latitude and Longitude using C

Sample code to calculate Distance by Latitude and Longitude using C.

www.geodatasource.com

 

반응형

댓글