본문 바로가기
Projects

[Project] ST Fair Route: 모두가 공평한 네비게이션 앱

by jangThang 2022. 3. 23.
반응형

[ Contents ]

     

     

    1. 프로젝트 개요

    • 분류: 안드로이드 앱
    • 일시: 2021.09. ~ 2021.10.
    • 스택: Java, Android Studio
    • 주제: 장애인, 외국인도 모두 사용할 수 있는 서울과기대 캠퍼스 앱

     

     

    GitHub - ChoWook/ST-Fair-Route

    Contribute to ChoWook/ST-Fair-Route development by creating an account on GitHub.

    github.com

     


     

     

     

    2. 프로젝트 소개

    ST Fair Route

     장애인, 외국인, 노인 모두 편하게 사용할 수 있는 내비게이션 앱을 만들고자 했습니다.

     영어를 병기해서 외국인도 이용할 수 있고, Zoom in/out을 통해 시력이 좋지 않은 장애인이나 노인분들도 이용할 수 있습니다. 장애인 시설 위치도 표기했으며, 휠체어를 타신 분들은 경사로나 계단이 없는 길로 안내합니다.

     그 외, 일반 사용자들도 당연히 동일한 기능을 이용할 수 있으며, 흡연부스나 주차장 위치도 지도를 통해 확인할 수 있습니다.

     

     

    ● 프로젝트 배경

    • 캠퍼스가 너무 넓어서 '지도 및 표지판'으로는 찾기가 어려우며, 걷는 도중 방향을 잊어버리거나 잃는 경우가 많음
    • 주로 차량을 위한 안내 표지판으로, 캠퍼스 내의 보행객에는 맞지 않음
    • 타 학교보다 건물(특히 대형, 고층건물)이 많아서 복잡하고 난잡함
    • 2020년 교육부 국립특수교육원 베리어프리 실태조사에서 서울과기대는 최하위 등급을 받았으며, 외국인이나 장애인, 노약자를 위한 배려가 필요 

     

    ● 프로젝트 목표

    • 모두가 공평하게 이용할 수 있는 편리한 캠퍼스 내비게이션 앱 개발
    • 영어 병기표기, Zoom in/out, 장애시설 위치표시 및 휠체어 길안내
    • 캠퍼스 지도, 경로, 거리, 예상 도착시간 정보 제공
    • 흡연구역, 주차장, 건물 정보, 사진, 학교 전화번호 등 부가정보 제공

     

     

     

    3. 기능 및 구성

    Usecase Diagram

      ST-Fair-Route는 팀 프로젝트로 진행했습니다. 'UI/UX 디자인', '안드로이드 앱 개발', '길찾기 알고리즘 및 기능 구현'으로 총 3 Part로 역할을 나눴습니다. 그중 저는 길찾기 알고리즘 및 기능을 구현했습니다.

     

     

    2022.03.16 - [Projects] - [Project] SNUT RoadSign: SeoulTech 길찾기 프로그램

     

    [Project] SNUT RoadSign: SeoulTech 길찾기 프로그램

    [ Project ] 1. 프로젝트 개요 분류: 맵 애플리케이션 일시: 2020.05. ~ 2020.06. 스택: Java 주제: 서울과학기술대학교 내 길 찾기를 도와주는 프로그램 제작 GitHub - jangThang/SNUT_RoadSign Contribute to ja..

    star7sss.tistory.com

     해당 프로젝트는 개인 프로젝트로 진행했던, SNUT RoadSign의 연장선에 있습니다. 위 프로젝트를 했던 경험을 바탕으로 기획해서 제작했습니다. 확실히 Java 자체 GUI 라이브러리인 JavaFX로 구현한 것보다 개발도 편하고 기능성도 좋았습니다.

     

     

    System Architecture

     

    Class Diagram

     어플리케이션 구조는 크게 2 부분으로 나누어집니다. 'Google Map API를 받아와 서울과기대 캠퍼스 지도 및 위치를 표시하는 인터페이스 Part'와 '위치정보를 바탕으로 다익스트라 알고리즘을 이용해 최단 거리 및 경로를 산출하는 Part'로 구성되어 있습니다.

     

     

     

    1) Google Map API를 이용한 거리 측정

        // 위도와 경도를 기준으로 두 지점 간의 거리측정
        public int calDistance(Vertex p){
            int R = 6378137; // 지구 반지름
            double dLat = Math.toRadians(p.latitude - this.latitude);
            double dLong = Math.toRadians(p.longitude - this.longitude);
    
            double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                            Math.cos(Math.toRadians(this.latitude)) 
                            * Math.cos(Math.toRadians(p.latitude)) 
                            * Math.sin(dLong / 2) * Math.sin(dLong / 2);
            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            double d = R * c;
            return (int)d; // returns the distance in meter
        }

     길찾기 알고리즘 내 그래프는 총 43개의 Node와 73개의 간선으로 구성되어 있습니다. 간선의 가중치인 '거리'를 측정하기 위해서 Google Map API로부터 위치정보를 받아옵니다. 위치정보는 위도와 경도로 주어지며, 두 위치 간 거리는 제공해주지 않습니다.

     따라서, 두 위치 간 거리를 '위도와 경도'를 이용해서 계산해야 합니다. 지구는 구에 가까우며, 두 위치 간의 거리는 '원주'를 계산해서 구할 수 있습니다. 위 코드는 원주를 계산하는 식입니다.

     


     

     

     

     2) 다익스트라 알고리즘을 이용한 최단경로 탐색

    길찾기 기능 Sequence Diagram

     다익스트라 알고리즘을 이용해서 사용자가 입력한 출발지부터, 도착지까지의 최단 경로를 탐색합니다. 다익스트라 알고리즘은 그리디 방식으로, 출발지로부터 가까운 노드부터 탐색해서 최단거리를 계산합니다. 계산한 최단 거리를 토대로, 목적지까지의 최단거리를 계산합니다.

     

    2022.03.22 - [Algorithm] - [Algorithm] 다익스트라(Dijkstra), 지름길의 지름길로 찾는 최적경로

     

    [Algorithm] 다익스트라(Dijkstra), 지름길의 지름길로 찾는 최적경로

     다익스트라는 출발지부터 목적지까지의 최적 경로를 탐색해주는 알고리즘입니다. 다익스트라의 이론적 설명과 구현 방법, 경로 추적까지 살펴보겠습니다. [ Contents ] 1. 다익스트라(Dijkstra) 알

    star7sss.tistory.com

     다익스트라에 대한 개념 설명과 코드는 위 글에서 보실 수 있습니다.

     

     

    public void calDaijkstra(Context context, boolean disabled, ArrayList<Vertex> vertex) throws IOException {
    
            // 장애유무에 따라 간선정보를 다르게 입력합니다.
            InputStream is;
            if (disabled == TRUE)
                is = context.getResources().openRawResource(R.raw.edge_disabled);
            else
                is = context.getResources().openRawResource(R.raw.edge);
    
            // 간선정보를 입력할 인접리스트
            ArrayList<Spot>[] SpotList;
            SpotList = new ArrayList[NODE + 1];
            for(int i = 0; i < NODE + 1; i++){
                SpotList[i] = new ArrayList<>();
            }
    
            // 인접리스트 초기화
            for(int i = 1 ; i <= NODE; i++){
                SpotList[i] = new ArrayList<>();
            }
    
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            String line;
    
            while ((line = reader.readLine()) != null) {
                String[] st = line.split(" ");
    
                int start = Integer.parseInt(st[0]);
                int end = Integer.parseInt(st[1]);
                int cost = vertex.get(start).calDistance(vertex.get(end));
    
                SpotList[start].add(new Spot(end, cost));
                SpotList[end].add(new Spot(start, cost));
            }
    
            // 최단경로를 저장한다.
            dist = new int[NODE + 1];
            // 경로 추적을 위한 부모노드 정보를 저장한다.
            parent = new int[NODE + 1];
            //거리를 무한대로 초기화
            Arrays.fill(dist, INFINITE);
            spotCnt = 0;
    
            // 다익스트라를 이용하여 최단거리를 구합니다.
            PriorityQueue<Spot> pq = new PriorityQueue<>();
            boolean[] check = new boolean[NODE + 1];
    
            pq.add(new Spot(startNode, 0));
            dist[startNode] = 0;
    
            while(!pq.isEmpty()){
                Spot curSpot = pq.poll();
                int cur = curSpot.end;
    
                if(check[cur]) continue;
                check[cur] = true;
    
                for(Spot Spot : SpotList[cur]){
                    if(dist[Spot.end] > dist[cur] + Spot.cost){
                        dist[Spot.end] = dist[cur] + Spot.cost;
                        pq.add(new Spot(Spot.end, dist[Spot.end]));
                        parent[Spot.end] = cur;
                    }
                }
            }
    
            Stack<Integer> stack = searchPath(startNode, endNode);
    
            StringBuilder sb = new StringBuilder();
            while(!stack.isEmpty()){
                int spot = stack.pop();
                sb.append(spot + " ");
            }
    
            meter = dist[endNode];
            pathNode = sb.toString();
            trableTime = (int)(meter/1.1); // 초속 1.1m/s로 계산했을 때
        }

     다익스트라 알고리즘을 '싱글톤 패턴'으로 구현한 코드입니다. 다익스트라 최단경로를 계산하는 객체는 최초 한 번만 메모리를 할당하면 되고, 계산한 값을 효율적으로 공유할 수 있습니다.

     

     다익스트라 역시 효율적으로 구현하기 위해서, 우선순위 큐(최소 힙)를 사용했습니다. 우선순위 큐를 통해 가까운 거리에 있는 노드부터 탐색할 수 있습니다.

     

    2022.02.20 - [Algorithm] - [Algorithm] 힙(heap), 최소/최대로 정렬하는 우선순위 큐

     

    [Algorithm] 힙(heap), 최소/최대로 정렬하는 우선순위 큐

     그래프의 트리 구조 중 하나인 '힙'과 구현 방법에 대해 알아보고, 그와 관련된 우선순위 큐도 살펴보겠습니다. [ Contents ] 1. 완전 이진트리(Complete Binary Tree) 완전 이진트리: 왼쪽부터 오른쪽으

    star7sss.tistory.com

     우선순위 큐에 대한 설명과 코드는 위 글에서 보실 수 있습니다.

     

     

        public static Stack<Integer> searchPath(int startNode, int endNode){
            Stack<Integer> stack = new Stack<>();
            int cur = endNode;
    
            while(cur != startNode) {
                stack.push(cur);
                spotCnt++;
    
                cur = parent[cur];
            }
            stack.push(cur);
            spotCnt++;
    
            return stack;
        }

     다익스트라는 최적경로의 '거리'를 계산해줍니다. 경로를 출력하기 위해서는 역으로 추적해서 찾아내야 합니다.

     최적경로를 갱신할 때 이전 노드를 저장하고, 저장한 이전노드를 토대로 목적지에서 출발지까지 추적합니다.

     


     

     

     

     3) 부가 편의기능

    서울과학기술대학교 캠퍼스

     '서울과학기술대학교'의 캠퍼스 부지는 52만㎡ (15.4만 평)으로, 서울 소재 대학교 중 5번째로 넓습니다. 이 넓은 캠퍼스 내에 장애시설이나 경사로, 계단, 흡연부스, 주차장 위치는 학교 홈페이지에도 나와있지 않았으며, 행정부서도 따로 정리해두지 않았습니다.

     

     

    장애인 전용 주차구역 / 흡연 부스

     따라서 팀원이 직접 전수조사를 해야만 했습니다. 코로나 19로 비대면 수업을 했기 때문에, 각자 지방에서 올라와 하루 종일 캠퍼스를 돌아다니며 조사했습니다. 초가을 무더위와 함께, 반나절 안에 끝내기 위해 고군분투하며 강행군을 자처했던 기억이 납니다.

     

     

     덕분에 어느 캠퍼스 앱보다도 자세하고, 정확한 내비게이션 앱이 탄생했습니다.

     학교 내 흡연부스, 주차장, 장애시설(경사로, 장애인 주차구역) 위치를 볼 수 있습니다. 휠체어를 타고 있는 장애우 분들은 계단이 없는 경사로 길로 최단경로를 안내합니다.

     


     

     

     

    4. 프로젝트 필요성 및 기대효과

     1) 필요성

    • 넓은 캠퍼스 부지와 복잡한 건물 배치로 길 찾기가 어려움

     서울 소재 대학교 중 5번째로 넓으며, 총 52만㎡ (15.4만 평)에 이릅니다. 건물도 45여 개로 많으며, 복잡한 건물 배치 때문에 방문객이 혼란을 겪는 일이 많습니다.

    • 차량 위주의 안내 표지판과 부족한 캠퍼스 지도

     캠퍼스 내에는 캠퍼스 지도가 없으며, 도보로 이동하는 방문객을 위한 표지판이 부족합니다.

    • 편의성 및 다양성을 고려하지 못함 (2020 교육부 주관 베리어프리 평가 최하위)

     기존 지도는 외국인을 배려한 영문 표기가 없으며, 노인분들이 보기 어렵습니다. 시인성이 부족해서 넓은 캠퍼스 지도에서 건물 이름과 길을 찾기 힘듭니다. 또한 다리가 불편한 장애인을 위한 시설 위치나 약도도 없습니다.

     

     

    ST Fair 시연영상

     

     2) 성과 및 효과

    • 모두가 공평하게 이용할 수 있는 네비게이션 앱

     외국인, 노인, 장애우 모두 편리하게 길찾기 앱을 이용할 수 있습니다. 영어 병기가 되어있고, 확대/축소가 가능합니다. 장애시설의 위치가 표시되어 있으며, 다리가 불편한 장애우를 위해 경사로 길 안내도 지원합니다.

    • Google Map API를 이용해 쉽게 길 찾기 가능

     캠퍼스 내 원하는 목적지까지의 경로를 쉽게 찾을 수 있으며, 캠퍼스를 둘러볼 수 있는 지도 기능도 수행합니다. 주요 건물과 시설에는 마커가 찍혀있으며, 마커를 누르면 관련 정보를 볼 수 있습니다.

    • 다양한 편의 기능을 탑재

     경로, 거리, 예상 도착시간 등 기본적인 내비게이션 기능을 제공합니다. 그 외에도 흡연부스, 주차장, 건물별 입구 위치, 사진, 정보, 전화번호 등의 부가 정보도 제공합니다. 

     

     

    서울과학기술대학교 붕어방

     

    반응형

    댓글