핀수로그
  • GPS 보정하기 - 02
    2023년 11월 20일 23시 15분 30초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    들어가며

     

    GPS 보정하기 - 01

    사실 이 알고리즘은 이전 프로젝트에서 개발 되었던 것인데, GPS 정확도 개선을 위한 좌충우돌 얼레벌레 MapMatching 구현기들어가며 정말 오랜만에 글을 쓰는 것 같다. 못해도 한달에 한개는 작성

    www.pinslog.com

    먼저 작성한 알고리즘에 문제가 있었다고 했다. 이를 해결하기 위해 어떤 것들을 수정 또는 추가 하였는지 간략하게 작성해보려고 한다.

    0. 데이터 형식 변경 (보정 대상)

    이전 프로젝트는 경로가 노드 정보로만 이루어져 있었다. 그래서 노드들을 이으면 링크가 되었기 때문에 노드를 이은 리스트가 매칭 대상이 되었는데, 이번 프로젝트 같은 경우 같은 경로 안내이지만 노드와 링크 정보가 모두 존재하였다. 따라서, 링크 정보를 받아 보정 대상을 생성해주었다. 그대로 사용하지 않고 새로 생성해준 이유는 또 옵션에 따라 경로 안내 방식이 변경되는데, 이 과정에서 링크 정보가 약간 틀어지기 때문이었다. 그래서 가장 원초적인(?) 형태 [[링크 시작점 - 링크 끝점], [링크 시작점 - 링크 끝점], [링크 시작점 - 링크 끝점] ... ] 로 만들어주었다.


    1. 일정 반경내에 들어오는 선분 수집

    GPS 보정을 알아보다 보면(?) 알겠지만 직선 구간의 경우는 보정하기 쉽다.
    가장 쉬운 방식인 수선의 발을 통해 보정을 하기 때문이다. (선분 AB에 현재위치 P를 수직으로 그어 만나는 지점)
    그런데 너무 당연히 보정이 되어야할 구간인데 보정을 수행하지 못하는 것이다.
    확인해보니 현재 위치와 대상 선분의 거리를 구하는 함수에 문제가 있었다. 그래서 찾아보다 google maps sdk에서 제공해주는 메소드를 찾아 함수 내부를 수정해주었다.
    (해당 프로젝트는 naver maps sdk와 google maps sdk를 사용중이다.)

    PolyUtil.distanceToLine(
        currentLocation,
        segment.start,
        segment.end
    )

     
    위의 distanceToLine은 segment (링크) 와 현재 위치 currentLocation 간의 거리를 반환해주는 함수이다. (단위 m)

    2. 수선의 발 (보정값)

    알고리즘 적용을 위해 시뮬레이션 앱을 따로 만들어 돌려보고 있었는데 출발지 부근에서 갑자기 엄한 곳으로 보정이 되는 것을 보고 놀라 원인을 찾아보다 '과연 수선의 발을 제대로 내려지고 있는가?' 하는 근본적인 질문을 던지게 되었다. 그런데 실제로 획득한 GPS가 후보 선분 바깥에 존재할 경우 제대로 보정값을 반환하지 않는 것을 확인했다. (이때 정말 허탈해서 내 자신이 10초 정도 싫었었다.) 

    현재 위치가 후보 선분 바깥에 위치할 때는 어떻게 하면 좋을지를 고민하다 이전 위치 데이터를 가지고 있기 때문에 그걸로 평균 이동 거리를 구해 후보 선분의 시작점에서부터 이동 거리만큼 이동한 좌표를 반환하도록 해 추정값을 사용하도록 했다.
    해당 함수도 google maps sdk에서 제공하는 것을 사용했다.

    SphericalUtil.interpolate(
        pointFA.toGoogleLatLng(),
        pointFB.toGoogleLatLng(),
        fraction
    )

    출발지 pointFA와 도착지 pointFB 사이의 fraction에 해당하는 좌표를 반환하는 함수이다.
     

    기존 알고리즘과 비교해보기

    각 함수별로 나타난 문제점들을 수정해가며 알고리즘을 수정하였고
    기존의 알고리즘과 비교해보았을 때 개선된 것을 알 수 있었다.
    (노란색 : 경로 / 초록색 : 실제 GPS / 빨간색 : 보정 결과)

    기존 알고리즘 수정된 알고리즘

     

    사용자의 움직임을 감지하기

    알고리즘을 조금이나마 개선하고 늘 그랬듯 나가서 테스트를 했다. GPS는 어느정도 보정이 되었는데...횡단보도를 건너려고 정지해서 대기중일 때 안내 화면과 안내 음성이 미친듯이 바뀌기 시작했다. (과장을 좀 보탰고요 미친듯이 그런건 아닙니다 흠흠) 그 이유는 사용자가 정지해있는 동안에도 계속해서 GPS를 수집해왔고, 알다시피 GPS는 부정확하고, 그래서 팝콘처럼 여기저기 튀는 GPS를 모두 보정하다보니 이 링크에 붙었다 저 링크에 붙었다를 반복했던 것이다.....그래서 사용자의 움직임을 판단해 정지상태이면 GPS를 수집하지 않기로 했다. (수집된 데이터를 버림)
     
    사용자의 움직임은 이전 위치와 현재 수집된 위치의 거리를 계산해 1미터 이상 차이가 나면 사용자가 움직이는 것으로 판단을 했다. 어디에 레퍼런스가 있었던 것은 아니고, 이리저리 구글링하다 누군가 써놓은 것을 보고 아이디어를 얻은 것이다.....(링크를 찾으면 첨부해야겠다. 'how to know person movement in android location' 라는 키워드로 검색을 했었다...🤔) 1미터는 내가 직접 걸어다니면서 찾아낸 수치이다...(보행자 또는 교통약자를 위한 내비게이션이기 때문에 걸어서도 사용이 가능해야 한다.) 다행히 아직까지는 사용자의 움직임을 잘 잡아내고 있다. 그래서 움직임이 있을 때만 보정을 수행하도록 했고, 미친듯한 안내는 자취를 감추었다.....홀홀
     
     


    이제 끝인가? 싶겠지만 아니! 내 고통은 이제부터가 시작이었다..
    내비게이션의 꽃, 경로이탈이 남았기 때문
    다음 글에서는 경로이탈을 잡아내기 위해 어떻게 접근했는지에 대해 작성해보려고 한다.
    그럼 이만...

    728x90
    반응형

    'Android' 카테고리의 다른 글

    [Kotlin] Scope Function 범위 지정 함수  (0) 2023.12.09
    GPS 보정하기 - 03  (0) 2023.11.22
    GPS 보정하기 - 01  (0) 2023.11.02
    GPS 보정하기 - 프롤로그  (0) 2023.11.01
    [Android] Hilt와 Room  (0) 2023.09.29
    댓글