GPS Map Making (in Unity)(3)

이민철·2022년 1월 31일
0

GPSMap

목록 보기
3/3

✔ 알고리즘 적용

맵을 클릭하였을 때 GPS값이 나오도록 만들었다.

X : 1px 당 0.09577588(m)
Y : 1px 당 0.0959613(m)

의 실험적인 결과를 통하여 마우스의 상대적인 위치를 계산하여 GPS값이 출력되도록 만들었다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class GoogleMap : MonoBehaviour
{
    float pivotX = 450; //맵 X 중심점 
    float pivotY = 450; //맵 Y 중심점

    float mapsize = 800; //맵 사이즈

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log(Input.mousePosition);
            Debug.Log(Flat2LLh(float.Parse(LATInput.text), 
            		float.Parse(LONInput.text), 
            		(Input.mousePosition.x - pivotX) * 0.095775f, 
            		(Input.mousePosition.y - pivotY) * 0.095961f));
        }
            
    }
    string Flat2LLh(float startLAT, float startLON, float x, float y)
    {
        startLAT *= (Mathf.PI / 180.0f); 
        startLON *= (Mathf.PI / 180.0f);

        float re = 6378137;
        float e = 0.0818f;


        print("re : " + re + "   e : " + e);
        float RN = re / Mathf.Sqrt(1 - e * e * Mathf.Sin(startLAT) * Mathf.Sin(startLON));
        float RM = RN * (1 - e * e) / Mathf.Sqrt(1 - e * e * Mathf.Sin(startLAT) * Mathf.Sin(startLON));
        Mathf.Atan2(1, RN * Mathf.Cos(startLAT) : " + Mathf.Atan2(1, RN * Mathf.Cos(startLAT))) ;
        float Lat = (y * Mathf.Atan2(1, RM) + startLAT) * (180.0f / Mathf.PI) * 100000;
        float Lon = (x * Mathf.Atan2(1, RN * Mathf.Cos(startLAT)) + startLON) * (180.0f / Mathf.PI) * 100000;
        print(">>> LAT : " + Lat + " Lon : " + Lon);
        string result = "Lat : " + Lat.ToString() + "Lon : "+ Lon.ToString();
        return (result);
    }
}

✔ Mathf 클래스의 문제

💢 하지만 심각한 문제가 발생하였다...

유니티에서 소수점 계산에 대한 정확도 문제가 발생하여 위도 경도를 소수점 5번째 자리까지 계산한다.... 현실에서는 수 m 까지 오차가 발생하기 때문에 cm, mm 까지 계산하도록 정확도를 높여야 한다.

C# 소수점 정확도 문제를 해결하기 위해 decimal 자료형이 있지만 Mathf 라이브러리는 float형식만 지원하기 때문에 사용이 불가능하다.



✔ 해결과정

using UnityEngine; //Unity Mathf class

❗❗ 알고보니 Mathf 클래스는 UnityEngine에 있었고 이는 float 파라미터와 리턴 값이 모두 float형 이였다.

using System; //C# Math class

❕❕ 그래서 using System 을 추가하여 C# 에서 자체적으로 지원하는 Math 클래스를 사용하여 해결하였다.
C# Math Class

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class GoogleMap : MonoBehaviour
{
    float pivotX = 450; //맵 X 중심점 
    float pivotY = 450; //맵 Y 중심점

    float mapsize = 800; //맵 사이즈

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Debug.Log(Input.mousePosition);
            Debug.Log(Flat2LLh(double.Parse(LATInput.text),
            double.Parse(LONInput.text),
            (double)(Input.mousePosition.x - pivotX) * 0.095775f, 
            (double)(Input.mousePosition.y - pivotY) * 0.095961f));
        }
            
    }

    string Flat2LLh(double startLAT, double startLON, double x, double y)
    {
        startLAT *= (Math.PI / 180.0f); 
        startLON *= (Math.PI / 180.0f);

        double re = 6378137;
        double e = 0.0818f;


        print("re : " + re + "   e : " + e);
        double RN = re / Math.Sqrt(1 - e * e * Math.Sin(startLAT) * Math.Sin(startLON));
        double RM = RN * (1 - e * e) / Math.Sqrt(1 - e * e * Math.Sin(startLAT) * Math.Sin(startLON));
        print("RN : " + RN + "   RM : " + RM);
        print("Mathf.Atan2(1, RM) : " + Math.Atan2(1, RM) + "   Mathf.Atan2(1, RN * Mathf.Cos(startLAT) : " + Math.Atan2(1, RN * Math.Cos(startLAT))) ;
        print(Mathf.PI);
        print(180.0f / Mathf.PI);
        double Lat = (y * Math.Atan2(1, RM) + startLAT) * (180.0f / Mathf.PI);
        double Lon = (x * Math.Atan2(1, RN * Math.Cos(startLAT)) + startLON) * (180.0f / Math.PI);
        print(Math.Round(Lat,7)+","+ Math.Round(Lon, 7));
        string result = ">>>>" + Lat.ToString() + ","+ Lon.ToString();
        return (result);
    }
}

코드를 float형을 모두 double 형으로 바꾸고 Mathf Class를 Math Class로 바꾸니 해결되었다.

결과는 소수점 16번째 정도까지 계산이 되었고 소수점 아래 7자리까지 사용하였다.

✔ 결과

(추후 방향 표시를 위해 화살표 UI를 추가하였다.)

유니티에서 기준점을 잡고 끝 4점을 클릭하였을때 GPS값이 다음과 같이 출력되는 것을 볼 수 있다.

이 결과를 https://staticmapmaker.com/google/
이 사이트에 GPS값을 입력하여 확인해본 결과
네 꼭짓점 모두 정확하게 나오는 것으로 확인된다.


이렇게 유니티를 이용하여 GPS MAP을 만들고 임의의 점을 클릭했을 때 GPS 데이터가 출력되게 하였다.

❓ 구글의 이상한 문제 ❓

같은 구글 맵을 사용하였지만 GoogleStaticMap API와 map.google.com에 같은 GPS값을 입력했을 때 오차가 발생했다.

꼭짓점의 GPS좌표가 2개로 나타난다. 뭐가 맞는 데이터 인지는 모르겠지만 이는 기준점(centerGPS)이 동일하게 설정된다면 추후에 문제가 발생하지 않기 때문에 시스템 동기화 문제일 것으로 예상하고 넘어가도록 해야겠다..

💬 다음으로 해야할 것

◽ GPS데이터가 실시간으로 MAP에 반영되도록 화살표를 움직이기
◽ N방향을 기준으로 ±180°의 각도 데이터가 들어오면 화살표 UI가 방향에 맞게 회전하게 만들기
◽ Unity - ROS 통신하는 방법 공부하기

0개의 댓글