on
후기
헤븐(HEVEN, Hybrid and Electric Vehicle ENgineering)은 성균관대학교 유일의 자작 자동차 동아리이다. 시스템경영공학과 학생이 자동차 동아리에서 잘 할 수 있는 일은 프로젝트 매니징이다. 나는 2018년도 국제대학생 창작자동차 경진대회 자율주행자동차 부문에 팀장으로 참여했다. 순전히 개인적인 입장에서, 대회를 준비하며 겪고 생각한 것들을 시간 순으로 정리해 보았다.
2017년 가을, 겨울
팀장이 되어버렸다
8월 대회 끝나고 탈-헤븐 했어야 했는데, 어쩌다 보니 적격자가 나 뿐이었다. 헤븐은 원래 하이브리드 자동차나 전기 자동차를 만드는 동아리였어서 그 당시 구성원의 대부분이 기계과나 전기과였다. 그리고 그 중 코딩에 관심이 없는 분이 다수였다. 나는 헤븐 내에 몇 없는 시스템과인데다 당시 연계전공을 통해 파이썬 개발을 해 본 사람이었고, 결정적으로 여름에 8월 대회 기술아이디어 부문 준비할 때 같이 코딩한 사람들이 전부 탈-헤븐에 성공해버렸다. 따라서 나는 2018 자율차 팀의 프로젝트 매니저가 되었다. (PM, Project Manager 라고 하는 건 내가 팀 내에서 실제로 한 일을 살펴보고 추후에 자체적으로 붙인 직무 이름이고, 대회에 명단을 제출할 때의 명칭은 팀장이 맞다.)
박주은이 자율차 팀장이 된 이유
- 당시 헤븐 내에 코딩에 관심 있는 사람이 몇 없었는데 그 중 하나였다
- (헤븐에 몇 없는) 시스템경영공학과 학생: 파이썬을 전공과목으로 배웠다 (파이썬은 자율차 2017팀이 선택한 언어이다)
- 연계전공으로 코딩을 배우는 중이었다
- 이미 동아리 내에서 대회를 나갔던 경험이 있었다 (두 번, 2017.05, 2017.08)
- 동아리 전반의 상황을 잘 알고 있었다
- 플랫폼 보조 프레임 제작에 필요한 공작 기계(고속 절단기, 드릴링 머신, 밀링 머신, 그라인더 등)들을 사용해 보았다
- 직전 대회에서 기술아이디어 부문을 준비할 때 같이 코딩한 사람들이 모두 탈-헤븐에 성공했다…
인수인계 (2017팀의 코드 요약)
프로젝트 구성 초기에는 2017팀의 프로그램 구조와 개발 방식을 학습한 뒤에 좋은 점은 본받고 아쉬웠던 점을 보완하는 방향으로 가닥을 잡기로 마음먹었다. 2017팀은 같은 대회 같은 부문에서 주행 은상(2등)을 수상한 경력이 있다. 처음 팀장을 맡게 되었을 때 가장 큰 부담은 그것이었다. 작년 팀의 결과보다 안 좋으면 마음 아플 테니까. 그렇지만 반대로 생각하면, 일을 계획할 때 선례가 있다는 것은 큰 도움이 된다.
2017팀장은 나윤서 씨로 당시 4학년이었고, 내가 대회를 나가게 될 2018년에는 이미 졸업해 있을 사람이었다. 그래서 윤서 님이 졸업하기 전에 여러 가지 질문을 하고 이야기들을 들었다. 각 세부 알고리즘의 경우에도 팀 내에서 각 파트를 맡은 개발자 분들께 수소문을 해 (그 분들 또한 졸업하거나 졸업 준비로 바빠지기 전에) 직접 만나뵙거나 온라인 상으로 질문을 드렸다. 2017팀은 python2.7을 썼고, 코드 버전 관리를 공유 드라이브로 했다.
자율주행 프로그램의 아키텍처를 간단히 설명하자면 다음과 같다. 크게 인지, 판단, 제어의 세 부분으로 이루어진다. 프로그램은 각종 센서를 통해 주변 상황을 인지한다. 인지한 데이터를 통해 앞으로 어느 방향으로 주행해야 할 것인지 판단한다. 그리고 주행해야 할 계획을 따라 자동차의 속력과 방향을 제어하여 움직이도록 한다. 이 구조를 대략적으로 이해한 뒤 2017팀의 내용을 인수인계받았다.
자율주행 프로그램의 간단한 아키텍처
- 인지(Perception): 센서 데이터 처리 (차선, 표지판, 장애물 등을 인식하기 위한 sensor parsing)
- 판단(Planning): 경로 생성 (길 찾기)
- 제어(Control): 차량을 움직이게 함 (속력, 조향 제어)
2017팀은 인지의 경우, 센서로 웹캠, 라이다(LiDAR), GPS 및 IMU를 사용하려고 계획했으나 사실상 GPS는 센서 하드웨어 자체의 정확도 문제로 사용하지 않았다. 경기장 크기가 내 고등학교 운동장(진짜 작다)보다도 작은데, 그에 비해 GPS의 오차 범위가 턱없이 크다고… IMU도 GPS와 함께 global mapping을 위해 사용하려던 계획이었어서, GPS가 사용하기 어렵게 되자 IMU 처리 프로그램 또한 중간에 자연스럽게 개발을 중단했다고 한다.
LiDAR 센서로는 장애물을 인식해 array에 표시하였다. 웹캠 센서로는 차선과 표지판을 인식했다. 차선 영상은 필터를 거친 뒤 경계를 따고 차선과 아스팔트를 구분하는 비전 처리 알고리즘을 거쳐 차선이 추출되었고, array에 표시되었다. 이 때 데이터 보정을 위해 ransac 알고리즘을 사용했다고 한다. 표지판은 머신러닝 모델을 통해 어떤 표지판인지 인식되었다. 그러나 2017팀의 표지판 인식 프로그램을 개발하신 분들의 말씀에 따르면, 머신러닝 된 모델이 정교하지 않아 시간에 따라 햇빛의 각도가 달라지면 정확도가 변하는 문제가 있었다.
판단과 제어의 경우 2017팀은 차량의 주변 상황을 array로 다루어 차선과 장애물을 표시한 뒤 A* 알고리즘을 이용해 경로를 판단했다. 그 뒤 실험적으로 얻어낸 차량에 주는 값과 실제로 차량이 움직이는 값의 관계를 가지고 제어를 시도했고, 제어 시 비례-적분-미분(PID) 제어기의 비례항만을 사용했다고 한다(조향에서인지 속력에서인지 기억이 안 난다).
위와 같은 알고리즘들은 연산 속도가 완전 순식간!이 아닌 이상은 동일한 시점에서 받은 데이터를 가지고 처리해야 데이터가 시간차를 두고 꼬이는 일이 없다. 라이다로 보는 앞이랑 웹캠으로 보는 앞이랑 동기화가 안 되면 얼마나 위험하겠는가. 그리고 프로세서와 플랫폼 간의 통신 시에도 신호를 주는 일과 받는 일이 동시에 일어나고 있어야 한다. 따라서 순차 처리가 아니라 병렬 처리가 필요하다. 2017팀은 스레드를 이용해 이 문제를 해결했다. 모든 세부 프로그램들에 스레드를 적용했다.
또한 자율차는 실시간으로 값을 주고받는 일이 아주 중요하다. 실제로 대회용 차량 플랫폼은 프로세서로부터 1초 이상 새로운 데이터를 전달받지 못하면 E-Stop 모드로 들어가고 급정지한다. 윤서 님은 우리에게 그 부분도 신경쓰며 개발하라고 알려주었다. 실제 자율주행 자동차를 생각하더라도 프로세서에서 어떤 문제가 있어서 새로운 제어 값을 업데이트해주지 못하면 앞을 안 보고 자동차가 움직이는 셈이니, 아주 위험할 것이다. 어려운 점은 비전 처리와 경로 찾기 같은 연산량이 많은 알고리즘을 실행시켜야 한다는 점이다. 그러면서도 정해진 시간 내에 연산을 끝낼 수 있게 설계하여 프로세서와 자동차간의 통신이 연속적이도록 보장해야 한다. 또한 센서 데이터를 받아 연산을 마치고 제어 신호를 한 번 줄 때까지의 주기가 곧 자율주행차가 주변을 인지하는 주기이므로, 빠르면 빠를수록 좋다.
2017 팀이 잘 한 점
- 차선 인식 알고리즘: 비전에서 데이터를 받은 후 ransac을 이용한 보정
- 멀티스레딩 사용: 플랫폼과의 통신, 센서 데이터 처리(인지), path planning(판단), control(제어)의 모든 기능을 스레드를 통해 병렬 실행하여 각 프로그램에서 쓰이는 데이터의 동일성 보장
2017 팀원들이 생각한: 아쉬웠던 점 혹은 2018팀이 신경쓰면 좋겠다고 생각한 점
- 표지판 인식 알고리즘: 머신 러닝 된 모델이 정교하지 않아 역광 등 햇빛 각도나 날씨의 영향을 많이 받음
- 연산 속도
- 자동 주차 알고리즘
내가 생각한: 2018 팀이 신경쓰면 좋겠다고 생각한 점
- 정교하지 않은 협업 방식 및 툴 개선
- 코드의 재사용성이 떨어지는 것 개선
팀 꾸리기
2017팀에서 대회에 출전했던 사람들은 2018팀에 한 명도 포함되지 않았다. 그래서 팀장만 있는 상태에서 팀을 처음부터 꾸리기 시작했다.
작년 팀에는 컴공 및 소프트과 분들이 없었기 때문에 일부라도 구성원에 포함시키고 싶었다. 또는 적어도 한 가지 이상의 컴퓨터 언어를 공부해 본 경험이 있는 사람이 팀에 들어왔으면 좋겠다고 생각했다. 우리 학교의 최근 입학생부터는 공학 계열의 경우에도 1학년 때 C언어와 파이썬 과목을 필수 수강하도록 바뀌어서, 해당 과목을 수강한 곧 2학년이 될 학생 분들도 홍보 타겟으로 삼고자 했다. 그래서 다음과 같은 이상한 공고 포스터를 만들었었다. 이 공고를 통해 구성된 초기 팀은 나를 포함해서 10명보다 조금 많았던 것으로 기억한다.
[사진 - 이상한 모집 공고]
2018년 1월부터 5월 대회까지
언어 및 프로세서, 운영체제
2017팀이 C++이나 LabView가 아니라 특별히 python을 사용한 이유는 사실 조금 이상했다. 지도 조교의 추천을 받아 개발 초기에 프로세서를 엔비디아의 젯슨TX를 사용하려고 마음먹고 파이썬으로 이미 개발을 꽤 진행했는데, 겨울방학 중 대회측에서 발표한 프로세서 규정에 따르면 젯슨 사용이 불가능했다. 그러나 이미 개발은 해 뒀고 아까워서 별 수 없이 프로세서만 PC로 바꾸고 개발을 계속 진행해서 완성한 것이라고 한다. 이 때 PC의 운영체제는 우분투를 사용했다.
나는 2018버전 개발을 시작하기 전에는 C++사용을 고민했으나, 일단 그 당시 내가 C++을 안 써봤었고… 우리 학교가 1학년 때 파이썬을 가르치고 있다는 점과 작년 팀의 소스가 이미 그것으로 짜여져 있다는 점을 감안하여 팀원들의 의견을 받아 파이썬으로 확정했다. 전체 알고리즘은 달라지더라도 라이다 파싱이나 플랫폼 통신 코드는 일부 재활용이 가능했기 때문이다. 그리고 팀원들이 이미 배운 적 있는 언어여야 개발 속도가 날 것으로 예상했고, 파이썬은 사용 가능한 라이브러리가 많아 연산 속도 면에서도 나쁘지 않을 것이라 생각했다. 따라서 일단은 2017팀과 같이 우분투 환경에서 파이썬을 사용하기로 결정했다. 그러나 웹캠 여러 개 동시 사용 문제 때문에 개발 도중 윈도우로 변경된다. 프로세서는 새로 살 돈이 없었기 때문에 그냥 같은 컴퓨터를 받아서 사용했다.
2017팀
- 언어: Python2.7
- 프로세서: 조립PC (Intel Core i7-7700K, 24GB RAM, GeForce GTX1070 G1)
- 운영체제: Ubuntu14
2018팀
- 언어: Python3.6
- 프로세서: 2017과 동일
- 운영체제: Windows10
연구계획서
12월에 기말고사가 끝나자마자, 대회 측에 연구계획서를 작성해서 제출해야 했다. 그래서 우리 팀의 첫 모임은 기말고사가 끝난 직후였다. 연구계획서는 다음 링크에서 읽을 수 있다. [연구계획서] 2017팀을 계승하겠다고 주장하고 있다. 그러나 프로그램이 완성될 시기에는 이 계획서와는 꽤 다른 방향으로 흘러갔다.
협업과 프로그램 설계
겨울 방학 중에는 일주일에 두 번 전체 팀원이 오프라인에서 정기 미팅을 가졌다. 프로젝트 관리는 깃허브 저장소를 이용했다. 학생 계정을 이용하면 무료로 private repository를 이용할 수 있다. 대회 준비 기간 동안에는 다른 팀에 보여주면 안 되니까 프라이빗 저장소가 필요하다. 작년 팀에서 아쉬웠던 점이 코드 버전 관리가 미흡했다는 것인데, 나는 개인 과제 프로젝트에서 깃허브를 써 본 적이 있어서 팀에 도입하기로 결정했다(사실 팀에서 깃허브를 쓰기 전에 내가 먼저 써 보기 위해서 개인 프로젝트에 사용해본 것이다). 또한 대회에 제출해야 하는 위한 잡다한 서류들이나 매번 미팅 때의 기록물들은 구글 드라이브를 공유해 관리했으며, 카카오톡 단체 채팅방으로 팀 내의 실시간 연락책을 두었다.
사용한 방법과 도구
-
오프라인 정기 미팅: 작업실에서 주 2회 (개강 후 주 3회)
-
github 저장소: 프로젝트 관리
-
구글 드라이브: 미팅 기록 및 제출 서류 관리
-
카카오톡 단체 채팅방: 팀 내 실시간 연락책
프로젝트 저장소 내부에 작성될 코드들의 구조도 설계했다. 각 코드가 전체 프로그램에서 무슨 일을 하는지를 고려해서 구조를 설계했고, 따라서 팀원들의 분업도 자연스럽게 ‘어떤 역할을 하는 코드는 내가 짤게!’로 진행됐다. 내가 저장소를 만들고 처음 한 일은 xxx.py의 이름을 갖는 파일들을 잔뜩 생성한 것이다. 그 파일들의 속은 비어 있고, 앞으로 팀원들이 작성한다. 코드 파일 자체가 모듈로 import가 되는 파이썬의 속성을 활용한 분업 방법이다. 그러나 지금 와서 생각해보면 이러한 구조는 자율주행 프로그램의 요구 사항을 고려했을 때 단점을 조금 가지고 있어서 보완해야 한다고 느껴진다. 프로그램 구조는 본 프로젝트 레포지토리의 README에서 살펴볼 수 있다. [HEVEN_AutonomousCar_2018 github repository]
대회 측 교육
겨울 방학 중에 있는 대회 측 교육에서는 그냥 자율차 프로그램 기본 구조를 알려주고, 센서 파싱법을 LabView로 알려준다. 우리는 랩뷰를 사용할 예정이 전혀 없었기 때문에 그냥 구경만 하다 왔다(…). 그래도 이론은 어차피 통하고, 개발하면서 궁금했던 점을 질문할 수 있는 기회이기도 하니 듣기를 추천한다. 사실 출석 안 하면 대회를 못 나가기도 한다. 또한 다른 학교 팀은 어떻게 개발을 진행하고 있는지 네트워킹할 수 있는(?) 기회이기도 하다. 다른 팀에서 질문하는 내용을 유심히 들어보면 느낌을 알 수 있…다고 주장해본다. 물론 가장 좋은 것은 다른 팀에게 직접 말을 걸어서 서로 정보를 공유하는 것이 아닐까(하고 생각만 해 봤다).
개발과 제작
서론: 당부의 말씀, PM과 PL
2018팀의 프로그램은 대회에서 주행 장려상(6등)을 수상했다(예선 기록 40%와 본선 기록 60%를 반영한 최종 등수이다). 따라서 절대 완벽한 코드라고 말할 수 없을 것이다. 그러나 우리 학교 팀이든 다른 학교 팀이든, 우리가 왜 실패했는지 안다면 더 잘 연구할 수 있을 것으로 기대한다. 따라서 아래와 같이 세부 개발 및 제작 내용과 그 과정을 기록하여 공개한다. 각 내용에 대해서는 간략한 설명만을 작성하고, 상세한 내용은 레포지토리 위키에 각 담당 개발자가 작성한 글이 있는 경우 그것을 링크하여 찾아갈 수 있도록 했다. (전체 구조에 대한 가장 자세한 설명은 대회 측에 제출한 기술보고서에 작성되어 있다.) 자율주행차에 관심 있는 학부생 분들이 이 글을 읽고 계시다면, 그리고 읽다가 ‘전체 구조나 세부 알고리즘에서 이렇게 바꾸면 더 나을 것 같은데’ 하는 생각이 들었다면, 대회에서 보여주셨으면 좋겠다는 마음이다.
개발 내용을 설명하기에 앞서, 나는 모든 개발에 참여했으나, 모든 개발에 참여하지 않았다(?)는 사실을 밝힌다. 사실상 나의 주된 업무는 프로젝트 총 일정 관리, 프로그램 구조 관리, 대회 측이 필요로 하는 각종 문서 작성(연구 계획서, 개발 기술 보고서, 그 외 잡다한 신청서, 지도교수님 싸인 받기,,,어쩌고) 등의 잡일이었다. 혹시 이 글을 읽는 분들 중 정말로 자율차 팀에 들어가고 싶은 분이 계실까봐, 만일 ‘개발’을 하고 싶어서 자율차 팀에 들어오려는 것이라면 절대 팀장은 하지 않기를 추천한다… 는 좀 어불성설이고, 팀 내에서 PM과 PL의 직무를 적절히 나누는 것도 괜찮겠다는 생각을 했었다.
PM은 Project Manager로 프로젝트 일정 관리, 팀 내 소통, (메일 주고받기 같은) 대외 소통 등을 보통 담당하며, PL은 Project Leader로 프로젝트의 기술적 구조, 실제 개발 과정 관리 등을 담당한다. 이렇게 직무를 나누면 각자가 실제 코드 작성에도 참여할 수 있을 것 같다. 팀장은 말 그대로 대회에 제출하기 위해 작성하는 명단에서의 이름일 뿐이라서, PM이나 PL중 아무나 써도 괜찮을 것 같다는 생각을 했다. 그러나 나는 사실상 둘 다 함 ㅂㄷ
읽기 전에, 앞서 설명했던 자율차의 대략적 구조를 다시 보자.
자율주행 프로그램의 간단한 아키텍처
- 인지(Perception): 센서 데이터 처리 (차선, 표지판, 장애물 등을 인식하기 위한 sensor parsing)
- 판단(Planning): 경로 생성 (길 찾기)
- 제어(Control): 차량을 움직이게 함 (속력, 조향 제어)
아래에는 위와 같은 구조의 개발 과정을 대략적인 시간 순으로 설명했다.
라이다 파싱은 껌이지
사실 그렇게 껌은 아닌데, 다른 센서에 비해서 파싱 과정이 간단해서 ‘비교적’쉽다. 통신 코드를 짜고, 값을 받아와서, 사용하면 된다. 주의할 점은 값이 극좌표계로 와서, 다루기 쉽게 하려면 직교좌표계로 바꾸는 과정이 필요하다. 물론 그대로 다룰 수 있으면 프로핏. 필요한 경우 라이다가 받아오는 값 중 판단 알고리즘이 고려하는 범위 내에 있는 값들로만 잘라서 연산을 수행하면 연산 속도를 조금 최적화할 수 있다. 우리가 사용한 라이다는 SICK사의 LMS-151이며, 통신은 이더넷을 사용한다. 라이다는 장애물 회피 알고리즘의 기초 데이터가 되기 때문에 초기에 개발을 완성했다.
길찾기라기보단 즉각적 반응 같은데요
원래 자율차라면 GPS와 IMU를 사용해 global mapping을 진행하는 것이 일반적이라고 한다. 그러나 우리가 가진 해당 센서는 오차 범위가 너무 컸고, 새로 살 돈도 없었고, 대회 미션을 수행하는 데에 글로벌 맵핑이 굳이 필요하지 않기도 했다. 따라서 우리 팀원은 글로벌 맵핑 없이 판단 알고리즘을 개발하기로 했다. [판단 구현 계획] 그래서 거의 눈앞만 보고 가는 이상한 알고리즘이 완성되기는 했는데, 대회 특성상 아무튼 미션은 잘 통과하니 됐다고 생각하기로…
알고리즘을 간단히 설명하면 다음과 같다. 먼저 표지판을 통해 들어오는 정보로 모드를 설정한다. 기본 모드는 차선만을 보고 주행하는 모드이다. 기본 모드의 경우, 차선 데이터를 받아 차선의 각도와 중심으로부터의 거리를 연산하여 제어로 넘겨주기만 한다. 그리고 각 미션 별 모드에서는, 그 미션을 해결하는 데 적절한 방식으로 센서 데이터를 조합해 연산한 뒤 값을 넘겨준다. 특별히 장애물 미션에 관련된 부분의 의사코드는 다음 링크에 있다. [Pseudo code of motion_planning.py] (이 부분은 연산 속도 문제로 추후에 CUDA로 구현된다.)
딥러닝을 만만하게 봤다가는 다쳐
2018팀에서, 표지판 딥러닝 개발의 가장 큰 문제는 처음에 이것을 담당한 사람에 내가 포함되어 있었다는 것이다. 내가 잡일을 이렇게 많이 하게 될 줄 몰랐다. 공부는 미리 시작해두긴 했는데, 막상 겨울 방학 때 대회 기간이 시작되고 나니까 생각보다 다른 관리할 게 많았다. 그래서 개발의 난이도에 비해 내가 투자한 시간이 적었다. 그래서 다른 팀원 한 분이 2월부터 바톤을 넘겨받아 딥러닝 공부를 시작하게 되어 표지판 개발 시작이 늦어졌다. 겨울방학 내내 표지판 인식을 판 사람이 사실상 그 한 분 뿐이었다. 이 초기 인원 배치 미스는 나중에 스노볼링이 되어 대회 전날 다같이 밤을 새는 계기가 되어버린다. (밑에서 다시 설명하겠다.)
자동차가 움직여요
그래도 내가 초기 개발에 참여한 것은 한 개 있었다. 바로 플랫폼 통신 코드 작성인데, 그러나 이것도 2017팀이 이미 작성해 둔 python2.7 코드를 3.6에서 돌아가도록 바꾸고, 다른 프로그램과 조립할 수 있도록 모듈로 만들기만 했을 뿐이다. 통신 프로그램의 역할은 제어 프로그램에서 받은 정보로 통신 패킷을 만들어서 플랫폼으로 보내고(쓰기), 플랫폼에서 통신 패킷을 받아와서 제어 프로그램으로 보내는 것(읽기)이다. 주변 상황을 인지하고 어떻게 움직일지 모든 것을 결정했다면 이제 자동차에게 전달해 주어야 하는데, 전달하기 위해 필요한 데이터는 일정한 규약에 따라 정리되어야 자동차 쪽에서 받아서 쓰므로 정해진 패킷 형식에 맞춰 제작하고, 전송한다. 그리고 자동차 쪽에서 오는 신호도 정해진 패킷 형식에 따라 오므로 그것을 해석해 제어 프로그램에 넘겨 주어서 피드백 알고리즘이 작동할 수 있도록 해 준다. 플랫폼과의 통신은 RS-232를 사용한다. [통신 코드 관련 문서]
내가 유일하게 작성부터 테스트까지 다 한 코드가 이 조그마한 하나 뿐인 것이 안타깝다. 테스트는 그냥 작업실 안에 자동차 두고, 더미로 조향 데이터를 줘서 앞바퀴가 좌우로 움직이는 것을 확인했다. 그리고 이마저도 모듈 완성도가 낮아서 뜯어고치고 싶었는데 엄두를 못 내고 있다가 3월 팀원 충원 때 들어오신 능력자 한 분이 세련되게 갈아엎어주셔서(!) 내가 작성한 부분은 흔적도 없이 사라졌다. 완벽한 PM+PL 달성,,, 덕분에 다음 대회 분들이 만일 파이썬을 사용한다면 통신 코드를 재활용해서 사용하고 다른 알고리즘 개발에 시간을 더 쏟을 수 있게 되었다.
제어는 수식의 연속일 뿐
앞서 설명한 플랫폼 통신 코드와 긴밀한 관계에 있는 것이 바로 제어 코드이다. 물론 제어는 판단과도 긴밀한 관계에 있다. 제어 코드는 판단에서 주는 값을 받아서, 잘 계산해서, 통신 코드에 넘겨준다. 가장 어려운 것은 잘 계산하는 것이다. 2018 프로그램은 Stanley-method를 사용해서 경로를 따라 조향 각을 계산한다. 스탠리 메서드는 스탠포드 대학교가 2005년에 개발한 자율주행차량 Stanley에 적용된 알고리즘이다. [Car Steering 기본 계획]
참고로 2018팀의 제어 코드는 조향 각만을 수식으로 계산하고, 속력은 플랫폼이 패킷으로 요구하는 맵핑된 값 중 적절한 것을 실험적으로 찾아내어 미션 모드 별 상수로 넣어주도록 작성했다. 만일 더 정교한 제어를 원한다면 다른 방법을 연구해볼 수 있는 부분이라고 생각한다. (대회 측에서 제공한 플랫폼은 모터 자체를 제어할 수 있는 것은 아니긴 하다.)
연구 계획 프레젠테이션
이 대회는 연구 계획 발표를 해서 통과한 팀만이 주행 대회에 진출할 수 있었다. 2018년도에는 1월 중순에 진행했다. 그런데 우리 학교는 2017년 대회에서 은상을 받아서 플랫폼을 연구 목적으로 대여받은 상태였다. 즉, 지난 대회에서 상위권이었던 학교를 제외한 다른 학교들은 예선을 통과하기 전까지는 플랫폼이 없는 상태였다. 그러나 발표 준비 당시 우리는 차량 플랫폼을 작업실에 두고 개발하며 이미 프로그램 구조의 틀을 잡은 시점이었기 때문에 연구 계획 발표는 큰 무리 없이 통과하였다.
[사진 - 연구 계획 프레젠테이션 미리 보기]
예선 통과 후 2월에 대회 참가 신청서를 냈다. 이 때 팀원 명단을 함께 제출했다. 하지만 4월 중순까지는 팀원 변경 신청서를 내면 명단을 바꿀 수 있었기 때문에 팀원을 더 뽑을 것을 고려하고 있었다.
차선을 보자
차선 개발도 인원 배치에 변동이 있게 되면서 실질적 프로그램 개발이 조금 늦어진 것 중 하나였다. 처음에는 2017팀이 했던 것처럼 웹캠 한 대를 가운데에 달아서 양쪽 차선을 한 번에 보려고 했다. 그러나 담당 개발자 분이 차량 바로 앞을 보지 못하는 게 마음에 들지 않는다고 했다. 그래서 웹캠을 높이 달기 위한 설계를 이것저것 해 봤는데 각이 잘 안 나왔다. 프레임이 너무 높으면 차량이 불안정해진다. 그래서 광각 카메라를 쓸지 광각 렌즈를 웹캠에 달지 일주일정도 여러 방법을 고민하다가, 간단히 돈을 더 들여 웹캠을 두 대 쓰기로 했다. 두 웹캠이 양쪽 차선을 각각 본다.
보조 프레임이 필요해요
웹캠을 두 개 쓰기로 결정하면서 보조 프레임 제작은 간단해졌다. 금정역 안양국제유통단지에서 알루미늄 프로파일을 사 왔다(우리 학교랑 가까워서 좋다). 자르고, 구멍 내고, 조립하고, 볼팅했다.
[사진 - 보조 프레임을 조립하는 모습]
웹캠을 알루미늄 프로파일 위에 그대로 조립할 수가 없어서, 중간자 역할을 하는 캠 마운트를 따로 캐드로 설계했다. 캠 마운트는 3D프린터로 출력해서 사용했다.
팀 내 중간 발표
중간 발표는 프레젠테이션을 통해 팀원 별 작업 보고 방식으로 각 분야 개발 과정을 상세하게 공유하는 자리이다. 분업 후 팀원들이 각자 자기의 분야만을 열심히 개발하다가 전체 구조를 보지 못할 것을 우려했다. 그래서 중간 발표를 기획했고, 대회 전까지 총 두 번 진행할 수 있었다. 처음은 2월 2일에 했다. 이 때 발표를 준비할 만큼 열심히 개발하지 못한 분들이 팀에서 빠져나갔다. 그래서 2월 동안은 꽤 적은 숫자의 개발자로 개발을 진행했고(한 자리 수의 팀원이었던 것으로 기억한다), 이 때의 사람들이 자율차 초기 멤버로 굳어졌다. 3월 충원 후에는 3월 31일에 두 번째 중간 발표가 있었다. 그 직후 대회 명단에 작성될 팀원 전체(13명)를 확정지었다.
[사진 - 3월 31일 팀 내 중간 발표]
개강과 팀 충원
3월에 개강을 하면서 정기 미팅 횟수를 주 2회에서 주 3회로 늘렸다. 대회가 얼마 남지 않은 시점인데 개발이 원래 계획보다 더뎌졌기 때문이었다. 흔한 일… 그리고 2월에 빠져 나간 인원을 충원하기 위한 공고를 냈다. 헤븐 정기 모집에 맞추어 모집한 것이라 스무스하게 포스터를 만들어 스무스하게 인원을 받았,,,더니 생각보다 많아서 면접을 보기로 했다. 문제를 만들어서 면접 전에 미리 공지하고 생각해 오시라 당부했더니 문제만 읽고 면접을 포기하신 분이 많았다. 띠용? 그래서 그 때 면접을 본 분들은 모두 팀에 우선 합류하기로 했다.
이미지에서 차선을 구별하고 따라가기
양 차선을 두 대의 웹캠으로 각각 보기로 한 뒤에 센서 장착까지 완료했다. 비스듬히 보이는 땅을 bird-eye-view로 펼치는 것도 한두 번의 캘리브레이션을 통해 성공했다. 웹캠 캘리브레이션을 위해서는 자동차를 편평하고 넓은 땅으로 끌고 간 뒤, 웹캠에서 보이는 땅의 실제 위치를 좌표로 측정하면 된다. 그리고 코드 상에서 웹캠 이미지를 그 좌표에 맞게 사다리꼴로 펼치면 땅을 위에서 수직으로 내려다본 모습이 된다. 좌표를 측정하는 방법은 간단하다. 분필로 땅에 표시하고 그 위치를 줄자로 잰다. 우리는 캘리브레이션을 더 쉽게 하기 위해서 바닥에 이미 모눈 같은 게 있으면 좋겠다고 생각하다가, 제 2공대 안쪽 바닥이 네모난 분홍색 타일로 되어 있다는 것을 생각해냈다(…). 그래서 그 곳으로 플랫폼을 끌고 가서 캘리브레이션을 진행했다.
본격적으로 차선 추출 알고리즘을 개발하기 위해 여러 의견을 모았다. 결국은 2017팀과는 다른 영상 처리 방식으로 진행하게 되었다. 공부를 목적으로 하는 학부생 대회이기 때문에, 개발자 분이 하고 싶은 걸 하게 해 주는 게 더 맞는 것 같아서 새로 개발하는 것을 찬성했다. 다음 링크에 차선 구별 필터에 대한 설명이 적혀 있다. [차선 구별 필터]. 영상 처리를 거친 이미지에서 차선을 찾아 추종하도록 하는 알고리즘 또한 작년과는 달리 새로운 방식으로 구현되었다. 이 알고리즘의 개발자가 작성한 깃허브 위키는 없지만, 참고한 문서는 다음과 같다. [Finding Lane Lines(영어)] (그러나 이 또한 대회 측에 제출한 2018팀 기술보고서에는 자세한 설명이 있다.)
예, 그 거북입니다: 차량 외장 (카울)
[사진 - 거의 완성된 거북이 카울]
코딩팀은 2017년 5월대회의 자율차팀을 계승하지만, 자율차 외장팀은 2017년 8월대회의 디자인 금상을 받은 스핑크스 자동차를 제작한 외장팀이 그 전신이다. 2017년과 달리 올해 자율차 대회에서는 디자인 부문 심사가 생겨서 외장팀을 자율차팀에 포함시키기로 결정했다.
외장팀이 작업했던 방식은 다음과 같다. 먼저 인벤터를 이용해 플랫폼을 역설계하고, 플랫폼 크기에 맞추어서 위에 외장을 설계했다. 설계 시 다른 부품과 간섭이 없도록 특별히 주의했다. 설계한 대로 아이소핑크로 틀을 만들고, 유리섬유를 이용해 카울을 제작했다. 외장 팀은 세 명 뿐이었어서 일손이 조금 모자란 감이 있었다. 다 만들고 나서는 락카로 배경 색을 칠하고, 아크릴 물감으로 세부 묘사를 했다. 나는 스핑크스 자동차를 만들 때는 이상한 이집트 무늬 그리기를 했었는데, 이 거북이 자동차에는 등껍질 무늬와 눈을 그려주는 것으로 비슷하게 기여했다.
병렬 처리와 순차 처리
메인 프로그램은 각 세부 프로그램의 실행 순서를 관리한다. 세부 프로그램에서 필요한 부분은 스레드를 통해 병렬로 처리되고(예: 통신), 굳이 병렬 처리가 필요하지 않은 부분은 순차 처리를 통해 루프를 돌도록 했다. 표지판 인식 프로그램 개발이 완료되기 전까지는 프로세서 자체의 연산 속도가 생각보다 빨리 나왔기 때문에 (한 loop당 0.0X 초대) 병렬 처리가 이루어지지 않으면 죽어버리는 통신 코드를 제외하고는 데이터의 흐름에 따라 순차 처리를 하도록 메인 코드를 작성했다. 따라서 2017코드와는 다르게 모든 세부 프로그램에 스레드를 적용하지는 않았다. 설마 이것도 문제였나?
CUDA 적용
연산 가속을 위해 가능한 부분에는 그래픽 카드 병렬 연산을 지원하는 CUDA를 사용했다. PyCUDA 모듈은 파이썬 코드를 이용해 CUDA를 제어할 수 있는 기능을 제공한다. 사용한 부분은 판단 코드에서 장애물을 검사할 때 연산량이 많은 부분이다. 다중 for 문이 사용되어 연산량이 많았다. 이를 그래픽 카드를 이용해 빠르게 처리하도록 개선했다.
모니터링 시스템
실험과 연습 주행 시에는 빠른 디버깅을 위해 모니터링 시스템이 필수이다. 이를 캐치한 팀원 분이 주행에 관련된 정보를 실시간으로 화면에 띄워 주기 위한 프로그램을 작성해 주셨다. 현재 수행중인 미션에 따라 모니터링이 필요한 화면이 자동으로 나타나고 사라진다. [모니터링 시스템]. 이를 이용해 대회 주행 시의 모니터링 화면 전체를 녹화하여 로그로 남겨 두었다.
표지판 인식 알고리즘과 딥러닝 모델
표지판 종류는 딥러닝의 CNN 알고리즘을 통해 구분하도록 구현했다. 딥러닝 프레임워크는 Tensorflow를 이용했다. 텐서플로우에 구현되어있는 Inception v1 모델을 이용했다. 대회 미션에 맞는 표지판 이미지로 데이터 셋을 직접 만드는 데에 시간이 오래 걸렸다. [표지판 인식 딥 러닝]
표지판 인식 알고리즘은 다음과 같다. 먼저, 표지판이 포함된 전방을 주시하는 웹캠의 이미지에서 표지판으로 의심되는 것들을 잘라 모델에 넘겨준다. 이 때 모델의 input에 맞는 사이즈로 변환해야 한다. 그럼 모델은 그 이미지가 어떤 표지판인지 분류해서 값을 반환한다. 표지판으로 의심되는 이미지를 검출하는 영상 처리 알고리즘에 대한 설명은 다음 링크에 있다. [표지판 위치 추출]
실험과 연습 주행
대회 직전에는 대회 측에서 미리 대회장을 개방해 주어서 연습 주행을 할 수 있게 해 준다. 일주일에 한 번씩 총 네 번 열어줬는데, 네 번 다 못 갈줄 알았는데 결국 꾸역꾸역 다녀 왔다. 대회장은 화성시이고 우리 학교는 수원시라서 한 번 실험을 갈 때마다 차량 플랫폼을 싣고 갈 용달 하나와, 팀원들이랑 실험 장비가 타고 갈 렌트카 하나가 필요하다. 렌트카를 타려면 면허를 가진 운전자도 필요하다. 그래도 연습장 사용은 무료이니 꽤 저렴한 가격에(?) 실험이 가능하다. 지원금을 이 때 다 탈탈 털어서 쓴 것 같다. 연습 주행은 날씨의 영향도 많이 타서 갑자기 일정이 바뀌기도 하고, 주중에 진행하는 경우에는 수업도 빠져야 해서 부담이 컸다. 그래서 나조차도 네 번의 연습주행에 모두 참여하지는 못했다. 하지만 역시 아무리 생각해도 실험은 많이 하면 할수록 좋다…
[사진 - 이 사진 진짜 불쌍해 보인다]
첫 번째와 두 번째 연습 주행까지는 전체 프로그램을 실행시켜보지 못하고, 미션 모드를 더미로 주어서 각 미션 별 판단 및 제어 알고리즘이 잘 돌아가는지만 확인하였다. 세 번째에서는 표지판 인식 알고리즘을 작업실에서 테스트 해 보기 위한 데이터를 수집해 왔다. 이 시점에서 표지판 인식 정확도 향상을 위해 보조 프레임을 덧대서 sign cam 센서 위치를 바꾸기로 결정했다. 네 번째 연습 주행인 5월 15일이 되어서야 표지판 인식 알고리즘을 처음으로 테스트해 보고, 연산 속도에 문제가 있다는 것을 깨달았다. 그리고 표지판 프로그램과 판단 프로그램 사이의 값 전달에서 문제가 있다는 것을 이 때 처음으로 발견한다. 너무 늦었다
네 번의 연습 주행에서 있었던 일
4월 27일 금요일
차선 인식이 잘 되는지만 확인. 차선 영상을 녹화해옴.5월 5일 토요일
차선 데이터만을 받아서 차량을 제어하는 기본 주행에 성공. 표지판 프로그램 없이 더미로 미션 모드를 줘서 자동주차, 장애물, 유턴, 횡단보도 미션을 테스트해 봄.5월 11일 금요일
두 번째 연습 주행에서 잘 안 됐던 미션을 디버깅해 테스트. 표지판 영상을 녹화해옴.5월 15일 화요일
표지판 인식 코드가 전체 프로그램의 병목으로 작용하는 것을 확인. 미션 수행 후 다른 표지판을 만났을 때 다시 이전 미션으로 돌아오는 버그 처음 발견. (미션 재진입 버그)
표지판이 너무 느려서 대회 전날 밤을 샘
대회 3일 전 마지막 연습 주행에서 발견한 문제 중, 값 전달 문제도 밤새 해결하던 문제 중 하나였지만, 표지판 인식 프로그램이 병목으로 작용하는 부분이 가장 치명적인 문제였다. 그래서 대회 전날 밤샘은 연산 병목 문제를 해결하는 것이 목표였다. 한 loop에 걸리는 시간이 빠르면 빠를수록 좋아서 그것을 재면서 테스트했는데, 표지판 프로그램의 개발이 완료되지 않아서 그것을 빼고 재는 동안에는 0.0X초대로 작동하여 안심하고 있던 것이 문제였다. 안 해봤으니까 모르죠… 처음에 발견한 문제는 표지판 후보 이미지를 검출해서 넘겨 주는 shape detection 프로그램의 정확도가 낮아서 모델이 검사해야 할 이미지가 많다는 것이었다. 따라서 정확도를 높이고자 했다. 또한 이 디텍션 프로그램의 연산 속도도 줄여보려 노력했다.
또 다른 의심은 연산을 gpu에 안 물리고 cpu에 물려서 느렸던 게 아닐까 한 것이다. 그러나 tensorflow-gpu를 사용해도 표지판을 검출하는 알고리즘이 작동할 때마다 주기가 1.1초 ~ 1.9초대까지 늘어났다. (또한 텐서플로우 gpu버전을 사용할 때 앞서 사용했던 PyCUDA와 충돌 이슈가 있었어서 이를 해결하는 데에도 애를 썼다) 이후에 장비 문제도 있지 않을까 하는 생각에 그래픽카드 오버클럭도 해 보고 GTX1080을 구해 와서 바꿔 끼워 보기도 했다(돈 없어서 사지는 못하고…).
결국은 대회 직전 밤을 새면서 급하게 구글링을 했고, model file을 freeze graph로 만드는 방법을 찾았다. 그리고 담당 개발자 분이 밤새 열심히 노력한 끝에 적용할 수 있었다. .chkp
파일을 freeze 하여 .proto
파일을 추출한 뒤 이용한다. 이 방법으로 한 프레임의 주기를 1초 미만으로 줄였다(로그 영상을 보니 0.5초대였던 걸 확인할 수 있었다). 그러나 이 속도도 처음 목표했던 것에 비해 느렸다. 표지판으로 의심되는 것들을 인식하는 순간부터, 모델에 넘겨주고 어떤 표지판인지 분류하는 연산을 수행하는 동안은 꼼짝 없이 앞을 못 보고 달리는 것이다! 병렬로 처리하면 되잖아 아무리 대회용 차량이라 속도가 느리다고는 해도 꽤 많은 거리를 갈 시간이다. 실제 차량 속도면 무기 수준 별 수 없이 꼼수로, 표지판으로 의심되는 물체가 shape detection이 된 순간에 차량의 속도를 급격히 줄여서 장애물에 부딪히는 일이 생기지 않도록 코드를 수정할 수밖에 없었다.
표지판 인식 연산 병목 문제를 해결하기 위해 시도한 방법들
- shape detection 프로그램의 정확도 및 연산 속도 향상
- 표지판이 주로 등장하는 관심 영역을 설정해 필요한 부분만 연산하기
- 표지판의 색을 이용해 필터 걸기
- 결론적으로, 이 부분은 정확도가 중요할 뿐, 연산 병목은 크게 없었던 것으로 밝혀짐
- gpu를 이용해 연산하도록 코드 수정
- PyCUDA와 충돌 이슈가 있었고, 해결함
- gpu 장비에 손 대보기
- 그래픽카드 오버클럭 시도
- 하드웨어 변경 (GTX1070에서 GTX1080으로)
- tensorflow model freeze
- 가장 효과가 좋았던 방법, 그럼에도 불구하고 여전히 느렸다
- 표지판 인식을 시도하는 경우 트리거를 주어 차량의 속도를 급격히 줄임
- 더 이상 연산 속도를 줄일 수 없어서 맨 마지막으로 시도한 방법
결론: 완성된 듯 완성되지 않은 듯
이렇게 대회 전날 밤샘까지 완벽하게 끝나고 프로그램을 보고 있자니 마음 한 켠이 불안했다. 그렇지만 우리가 열심히 만든 프로그램이니까 자동차가 앞으로 가긴 하겠지!
[표 - 전체 프로그램 구조와 각 세부 프로그램의 개발자]
대회
첫째 날, 5월 18일 예선 주행
글쎄, 자동차가 앞으로 가질 않았다. 비가 왔다. 뽑기를 했는데 첫 번째 순서가 걸렸다. 비가 부슬비라서 괜찮을 줄 알고 첫 순서를 주행하러 나왔는데 플랫폼이 작동을 안 했다. 주행 포기를 선언하고 차고로 돌아왔는데 비가 그쳤다. 팀원들과 상의하고 이의제기를 하기로 했다. 심사위원들은 비가 그친 상태가 모든 팀이 주행을 마칠 때까지 지속되면, 가장 끝 순서에 우리에게 기회를 주겠다고 했다. 비가 더 이상 오지 않았다. 그래서 맨 마지막에 다시 예선 주행 기회를 얻었다. 사실 플랫폼이 작동하지 않았던 건 비가 직접적인 원인은 아니었고, 잠깐의 통신 문제였던 것으로 밝혀졌다. 그렇지만 어떻게 상황이 맞아떨어져서 예선 주행이 무효가 아니게 된 것이 다행이라고 생각한다. 한순간에 그 개고생이 날아갈 뻔했던 하루였다.
예선 주행에서는 꽤 많은 미션을 실패했다. 7등이었다. 대회 측은 예선 주행이 끝난 직후부터 해 지기 전까지와, 둘째 날 해가 뜬 후 대회 준비가 시작되는 9시 전까지는 경기장을 연습 주행장으로 열어주기로 했다. 그래서 해 지기 전까지 연습 주행장을 돌아 보며 로그 동영상을 녹화했다. 팀원들이랑 작업실에서 예선 경기와 연습 주행 로그 동영상을 돌려보고, 밤새 디버깅했다.
예선 주행 미션 실패(4) 원인
- 횡단보도: 표지판 인식하고 미션 진입 후 정지선 인식까지 성공했으나 정지하지 못함. 원인 불명
- 동적 장애물: 이전 미션 탈출 직후 이전 미션 재진입 (값 전달 문제로 추정)
- U-turn: 이전 미션 탈출 직후 이전 미션 재진입 (값 전달 문제로 추정)
- 자동주차: 표지판 인식 후 미션 진입했으나 웹캠 영역 문제로 주차선 인식 실패 - 주차 표지판 인식 후, 주차 공간을 찾으려 시도할 때 곡선 차선을 따라가지 않고 직진하다가 웹캠 영역이 차선을 벗어남
그리고 작업실에서 잠시 눈을 붙이고 둘째날 새벽에 다시 대회장으로 왔다. 아침에 주행장을 돌며 실험해 보았다. 그러나 여러 팀이 함께 사용하는 주행장이기 때문에 충분한 실험을 해 보지는 못한 상태로 본선을 준비했다.
둘째 날, 5월 19일 본선 주행
본선 주행 순서는 예선 주행 결과 순위의 역순으로 했다. 유턴은 우리가 주행하기 전까지의 팀들은 성공하지 못하다가 우리가 처음으로 성공했지만, 주차도 실패하고 장애물과 횡단보도도 실패했다. 주행이 끝나자마자 녹화한 모니터를 다같이 돌려 보면서 대체 왜 실패한 건지 토의했다. 대체 왜!!! 그렇게 미션 실패 원인은 대부분 파악했으나, 대회가 끝난 지금까지 여전히 원인조차 모르는 문제 하나가 있다. 그것이 바로 마지막 연습 주행 때 처음 발견한 미션 재진입 문제이다. 그 문제는 전날 예선 주행이 끝나고 밤새 작업실에서 고민하다 일단은 꼼수로 수정하여 본선 때는 나타나지 않았다. 그러나 본질적인 원인을 디버깅한 것이 아니므로 적절한 해결 방법은 아니었다. 그리고 이후에 그 대회용 프로그램을 다시 돌려 볼 일은 없었기 때문에 아직도 미스테리로 남아있다. 나는 프로젝트 초기에 설계한 프로그램 구조 때문에 이 미션 재진입 버그를 일찍 발견하지 못하고 있었던 것이라고 추측한다. 본선 주행 결과는 6등이었다.
본선 주행 미션 실패(3) 원인
- 횡단보도: 표지판 모양은 디텍션했으나 모델에서 분류 실패 (디텍션 각도가 정방향이 아니었거나 여백의 문제로 추정)
- S-Curve: 표지판 모양 디텍션 후 차량의 속력을 급격히 줄일 때, 속력 값을 너무 낮게 줌. 그래서 가속도가 안 나와 장애물을 만나지 못한 채로 시간이 너무 오래 흘러 미션 탈출 조건으로 진입함. 따라서 장애물 미션을 기본 주행 모드로 달려서 부딪힘.
- 자동주차: 표지판 모양 디텍션 실패 (원인은 역광 등으로 추정)
본선 주행 생중계 녹화 영상 (1시간 25분 20초부터, 소리 해설 있음): 생중계 영상 끊김이 그대로 녹화되어 영상이 조금씩 끊깁니다.
디자인 심사
본선 주행이 끝나고 놀고 있는데 갑자기 심사위원분이 와서 디자인 질문을 하기 시작했다. 디자인 심사위원 분은 외국인이었고, 영어로 질문을 하셔서 당황했으나 영어 잘 하는 팀원이 있어서 외장팀장의 말을 잘 번역해 주었다. 디자인의 심미성뿐만 아니라 적절히 기능하는지나 만들기 전 설계를 미리 잘 했는지도 보는 것 같았다. 우리 팀은 디자인 상을 받지는 못했다.
[사진 - 거북이 카울 모습]
정리하는 글
대회 준비하며 느낀 점 정리
- 인수인계는 미리 받자, 인수인계 해 줄 내용은 틈틈히 정리하자
- 프로그램 구조는 처음부터 더 철저히 짰어야 했다!
- 다시 말하면, 자율주행차에서 중요한 것들이 무엇인지 더 치열하게 생각했어야 했다.
- 요구 사항 분석 시 ‘무엇을 필수로 보장해야 하는가’를 떠올린다면, 제한 시간 내에 모든 연산을 마치는 것을 보장하거나 다른 시스템이 죽었을 때와 같은 최악의 경우에도 보장 가능한 시스템 설계가 중요하다는 것을 알 수 있다…
- 실험은 많이 하자
- 프로그램 구조 설계의 한계를 보완할 수 있다.
- 연구 처음부터 넓은 공터를 구했다면 좋았을 것 같다. (학교 내에는 교칙상 실험용 차량을 공식적으로 굴릴 넓은 장소가 없었다)
- 그러나 연구에는 돈이 든다
여기까지 해서 다사다난한 대회 준비부터 대회 당일까지의 이야기들을 풀어보았다. 인수인계와 팀 꾸리기부터, 프로그램 구조를 설계한 일, 개발하고 실험하고 디버깅한 고통들… 팀장을 하기로 결심한 2017년 10월부터 2018년 5월까지 있었던 일이다. 남은 것은 결과에 대한 아쉬움과 개인적으로 뭘 더 공부해야 할지에 대한 길잡이 정도인 것 같다. 이런 프로젝트는 스스로의 부족함을 아주 잘 깨닫게 해 준다. 결과가 어떻든, 부족함을 구체적으로 깨달았다는 점에서는 만족할 만한 과정이었던 것 같다. 그리고 우리 팀원들은 참 멋진 사람들이었다. 대회 준비하는 동안 도움 주신 분들, 이 긴 글을 읽어주신 분들께도 고맙다는 말씀 드리고 싶다.
HEVEN_AutonomousCar_2018 Project Repository
자율주행 시스템의 요구사항과 프로그램 구조 비교: 대회가 끝나고 난 뒤 프로그램 구조 측면에서 아쉬운 점을 정리한 글