인공지능캡스톤디자인 계획서

캡스톤디자인 번호	2021-08
캡스톤디자인 분야	자율주행
캡스톤디자인 지도교수	노기섭 교수님
캡스톤디자인 명	(국문) 자율주행 자동차
	(영문) Self-driving car
캡스톤디자인 책임자	팀 명		Credere(크레데레)
	학 과		인공지능 소프트웨어 학과
	성 명		김현기			학 번
	휴대폰					E-mail
캡스톤디자인 세부현황	번 호	세부역할			성 명		전 공		학 번
	1	소스코드 작성			김현기		인공지능 소프트웨어
	2	제품 제작			정상필		인공지능 소프트웨어
	3	제품 제작			윤유탁		인공지능 소프트웨어
캡스톤디자인 수행기간	2021년 3월 25일부터 2021년 6월 30일 까지(00주)
2021년도 캡스톤디자인을 성실히 수행하고자 캡스톤디자인 계획서를 제출합니다. 2021 . 03 . 25 . 캡스톤디자인 책임자 김현기 서명 인공지능소프트웨어 전공PD 귀하

1. 요약서

※ 본 요약서는 캡스톤디자인 전체에 대한 요약서임. 캡스톤디자인 전체의 총괄적인 내용을 위주로 간략하게  1page 이내로 작성함

캡스톤디자인 번호	2021-08
캡스톤디자인 명	자율주행 자동차
캡스톤디자인 책임자	김현기

○ 캡스톤디자인 목표

자동차 모형에 카메라를 부착하여 차선을 인식할 수 있게 딥러닝을 사용하여 학습을 시키고 사람이 운전하는 것처럼 만들 것이며, 현재 테슬라의 오토파일럿이 가장 큰 문제가 다른 센서 없이 카메라로만 작동하고 있다. 이러한 이유로 많은 과학자가 걱정하는 것이 카메라 센서만으로 자율주행은 가능하나 엄청난 위험이 있을 수가 있다고 한다. 우리는 카메라로만 작동하는 자동차의 한계를 극복할 것이고 최종 목표로 정하게 되었다.

○ 캡스톤디자인 내용

실제 도로와 비슷한 환경을 OpenCV로 영상분석을 하여 직선과 차선들을 구별하여 자율주행 때 넘어가지 않도록 한다. 라즈베리파이를 통한 자동차키트와 컴퓨터의 통신을 한다. 딥러닝은 차량을 조종하여 어떻게 주행해야 하는지 학습시킬 것이다.

○ 캡스톤디자인 개발에 따른 기대성과

실제 시중의 자동차를 주행할 기회는 없지만, 모형 차를 사용하여 카메라를 사용한 자율주행을 할 때 한계에 부딪히고 보는 이들에게 카메라를 사용한 자율주행이 얼마나 큰 어려움이 있는지 일깨워줄 것이며 비록 실제 자동차를 이용한 연구는 아니지만, 간접적으로 자율주행 자동차를 연구해보고, 딥러닝을 경험해봄으로써 최신 유행에 맞추어 알맞은 지식을 쌓아가는 것이 우리 팀의 목표이다.

캡스톤디자인 계획서

캡스톤디자인 명 : 자율주행 자동차

캡스톤디자인 책임자 : 인공지능 소프트웨어 학과 / 김현기

1. 캡스톤디자인의 필요성

현재 자율주행에서 사용하고 있는 센서로 카메라와 라이다가 있다 우리가 주로 알고 있는 카메라는 테슬라에서 적극적으로 사용하고 있으며 대부분 구글 웨이모와 GM 사는 라이다 센서를 사용하고 있다 많은 전문가는 카메라로만 주행하기에는 라이다보다 부족하며 각 센서에서 인식할 수 있는 정도 또한 카메라가 훨씬 떨어진다고 한다. 우리 팀은 카메라가 아직 라이다 센서 더 싸다는 점과 쉽게 구할 수 있다는 장점을 높이 샀고 그에 따라 카메라만으로도 최고의 성능을 끌어올릴 필요성을 느꼈다.

2. 캡스톤디자인의 목표 및 내용

가. 캡스톤디자인 디자인 목표

카메라를 장착한 자동차 모형을 사용하고, 딥러닝을 이용하여 차선을 인식할 수 있도록 학습시켜 거의 모든 상황에 대하여 스스로 대처할 수 있도록 하는 것이 목표이다.

나. 캡스톤디자인 내용

	실제 도로와 비슷한 환경의 도로를 OpenCV로 영상분석을 하여 직선을 구분하고 그 차선들을 구별하여 자율주행 때 이탈하지 않도록 한다. 라즈베리파이를 통한 자동차키트와 컴퓨터의 통신을 한다. 또한 딥러닝을 통해 운전 방법을 학습한다.

3. 캡스톤디자인의 추진전략 및 체계

1. 차량 키트를 구매하고 딥러닝 과 opencv를 습득 및 작성한다.

2. 모형을 제작하고 소스 코딩 값을 입력한다. 작동이 순조롭게 될 때까지 수정 및 보완작업을 실행한다.

3. 작품이 완성되면 담당 교수님께 보여주고 피드백을 받아서 추가적인 수정 및 보완 또는 문제점들을 적절하게 조치한다.

4. PPT에 일부 코드 및 시행착오 영상을 보여드려 차량이 주행법을 학습하여 실력이 향상되는 것을 보여줄 것이다.

4. 캡스톤디자인의 기대효과 및 활용방안

졸음운전, 음주운전 등 사회적 문제가 커지는 추세다.

비록 실제 자동차를 이용하여 개발하는 것은 아니지만, 유사한 환경을 이용하여 연구하면서

자율주행 자동차가 상용화가 된다면 졸음운전과 음주운전으로 인한 사고를 큰 폭으로 줄이거나 아예 없앨 수 있다고 생각한다.

사람이 운전하지 않고 컴퓨터가 스스로 운전한다면 배송업무, 장거리 운전 등을 이제 사람이 직접 하지 않아도 될 것으로 예상한다.

6. 작업분할 구조도(WBS, Work Breakdown Structure)

6. 참여인력

가. 인력 편성표

						캡스톤디자인 책임자
						(김현기)
	소스코드 작성 / 제품 제작						소스코드 작성 / 제품 제작						소스코드 작성 / 제품 제작
김현기						윤유탁						정상필
1. OpenCV (회색조 변환하기, 이진화하기, 윤곽선 검출하기, 직선 검출 하기) 2. 상황 판단 및 전략 수립 (차로변경, 끼어들기 등) 3. 주행능력 테스트 4. 현장별 테스트 5. 계획서 작성						1. 차량 조립 2. 차선 검출하기 3. 신호등 불 인식 4. 주행능력 테스트 5. 현장별 테스트						1. 자율주행 기록 기반 주행 알고리즘 작성 2. 차선 검출하기 3. 신호등 불 인식 4. 주행능력 테스트 5. 현장별 테스트

나. 참여 인력 현황

번호	분 야	학 번	성 명	참여율(%)
1	소스코드 작성 / 제품 제작	16315012	김현기	34%
2	소스코드 작성 / 제품 제작	15931031	윤유탁	32.5%
3	소스코드 작성 / 제품 제작	15422003	정상필	32.5%

다. 캡스톤디자인 책임자 및 참여인원의 상세 정보

1) 인적사항
	성 명		김현기
	학 번					생년월일
	주 소
	연 락 처		핸드폰				e-mail
	공학 인증		참여				미참여
2) 학적 사항
연도	학적변동 사항
2016	신입학
2017	군휴학
2019	군복학
2019	희망전과
3) 현장실습, 인턴쉽, 어학연수, 교육연수 현황
연도(부터～까지)		연수 명			연수기관
4) 자격증 현황
자격증 명		발행기관			취득년도
1종 보통		충북지방경찰청			2017
2종 보통		충북지방경찰청			2016
지게차 운전 기능사		국토교통부			2017

1) 인적사항
	성 명		정상필
	학 번					생년월일
	주 소
	연 락 처		핸드폰				e-mail
	공학 인증		참여				미참여
2) 학적 사항
연도	학적변동 사항
2015.3.2.	청주대 입학
2017.4.24.	군입대
2019.1.15.	군전역
2021.3.2.	복학
3) 현장실습, 인턴쉽, 어학연수, 교육연수 현황
연도(부터～까지)		연수 명			연수기관
4) 자격증 현황
자격증 명		발행기관			취득년도
1종보통		서울지방경찰청			2015

1) 인적사항
	성 명		윤유탁
	학 번					생년월일
	주 소
	연 락 처		핸드폰				e-mail
	공학 인증		참여				미참여
2) 학적 사항
연도	학적변동 사항
2015	입학
2017	군휴학
2019	복학/전과
2020	휴학
2021	복학
3) 현장실습, 인턴쉽, 어학연수, 교육연수 현황
연도(부터～까지)		연수 명			연수기관
4) 자격증 현황
자격증 명		발행기관			취득년도
항공무선통신사		한국전파진흥원			2016
1종보통

7. 소요장비 및 재료

장비 및 재료 명	규격	수량	용 도	비 고
개인용 컴퓨터 (PC)		3	소스코드 제작
웹 브라우저 (Chrome)		3	정보 및 자료 검색
한컴오피스 한글 2020		3	문서 작성
Microsoft Power Point		3	PPT 제작
스마트폰		3	팀원 간 연락
십자드라이버		1	조립 제작
플라이어		1	조립 제작
메이커스: 어른의 과학 Vol.05 AI자율주행자동차 조립 키트		1	자동차 몸체
절연 테이프		3	조립 제작
합판		4	임시 차도로

8. 캡스톤디자인 추진일정 계획

	세부 추진 내 용						추 진 일 정 (월)
							3	4	5	6
자율주행 자동차	1	차량조립	차량 조립	모터제어	방향전환
					속도조절
			도로제작
	2	OpenCV	차선 인식	회색조 변환하기
				이진화하기
				윤곽선 검출하기
				직선 검출 하기
	3	딥러닝	상황 판단 및 전략 수립(차로변경, 끼어들기 등)	자율주행 기록 기반 주행 알고리즘	카메라	차선 검출하기
						신호등 불 인식
	5	테스트		주행능력 테스트
				현장별 테스트
	:	:	:	:

물품명 및 가격	스펙 및 부품	주소
메이커스: 어른의 과학 Vol.05 AI자율주행자동차 조립 키트 1개 178,600원	몸체 바퀴 카메라	https://mechasolution.com/shop/goods/goods_view.php?goodsno=583336&category=
십자드라이버 1개 330원	80mm	https://mechasolution.com/shop/goods/goods_view.php?goodsno=543372&category=
플라이어 1개 1,210원원	10cm	https://mechasolution.com/shop/goods/goods_view.php?goodsno=330473&category=
절연 테이프 개당 770원 총3개 2,310원	19mm 총길이 10m	https://mechasolution.com/shop/goods/goods_view.php?goodsno=539466&category=
합판 3mm 4개 1,000원 (배송비 2500원) 6500원	200X300mm 두깨 3mm	http://item.gmarket.co.kr/DetailView/Item.asp?goodscode=210589130&GoodsSale=Y&jaehuid=200002657&service_id=estimatedn/g마켓http://itempage3.auction.co.kr/DetailView.aspx?ItemNo=B299601
총액 188,950원

9. 구매 품목

캡스톤 디자인 결과보고서(結果報告書)

목  차

1. 차량 구조 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	19
1.1. 차량 조립법 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	19
2. 오렌지파이∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	30
2.1. 각부 명칭 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	30
2.2. 회로도 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	31
2.3. 오렌지파이∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	32
3. 차량 작동법 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	35
3.1. 코드 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	35
4. 마무리 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	41
4.1. 향후 추진 계획 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	41
4.2. 정리 ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙	41

1. 차량 구조

1.1. 차량 조립법

본 차량은 오렌지 파이와 카메라를 기반으로 차선을 인식하여 차선 안에서 중심을 찾아 자동으로 주행하는 것으로 모터 4개를 장착하여 각각 다르게 작동을 할 수 있으나 실제 차량과 같이 작동을 하게 하였다.

조립법은 다음과 같습니다.

2. 오렌지 파이

2.1. 각부 명칭

2.2. 회로도

2.3. 오렌지파이

2.3.1 사용법

차량의 시스템 화면을 노트북 및 다른 컴퓨터에서 무선으로 보기위해 와이파이를 연결 하기위한 절차 이다.

vnc 뷰어를 이용하기 위한 연결 방법

3. 차량 작동법

3.1. 코드

Newbase.py
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213214 215 216 217 218	import xhat as hw import sys import cv2 import math import time import numpy as np def detect_edges(frame): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) lower_black = np.array([0, 0, 0], dtype = "uint8") upper_black = np.array([350, 55, 100], dtype="uint8") mask = cv2.inRange(hsv,lower_black,upper_black) edges = cv2.Canny(mask, 50, 100) cv2.imshow("edges",edges) return edges def region_of_interest(edges): height, width = edges.shape mask = np.zeros_like(edges) polygon = np.array([[ (0, height), (0, height/2), (width , height/2), (width , height), ]], np.int32) cv2.fillPoly(mask, polygon, 255) cropped_edges = cv2.bitwise_and(edges, mask) return cropped_edges def detect_line_segments(cropped_edges): rho = 1 theta = np.pi / 180 min_threshold = 10 line_segments = cv2.HoughLinesP(cropped_edges, rho, theta, min_threshold, np.array([]), minLineLength=5, maxLineGap=150) return line_segments def average_slope_intercept(frame, line_segments): lane_lines = [] if line_segments is None: print("no line") return lane_lines height, width,_ = frame.shape left_fit = [] right_fit = [] boundary = 1/3 left_region_boundary = width * (1 - boundary) right_region_boundary = width * boundary for line_segment in line_segments: for x1, y1, x2, y2 in line_segment: if x1 == x2: print("skipping vertical lines (slope = infinity") continue fit = np.polyfit((x1, x2), (y1, y2), 1) slope = (y2 - y1) / (x2 - x1) intercept = y1 - (slope * x1) if slope < 0: if x1 < left_region_boundary and x2 < left_region_boundary: left_fit.append((slope, intercept)) else: if x1 > right_region_boundary and x2 > right_region_boundary: right_fit.append((slope, intercept)) left_fit_average = np.average(left_fit, axis=0) if len(left_fit) > 0: lane_lines.append(make_points(frame, left_fit_average)) right_fit_average = np.average(right_fit, axis=0) if len(right_fit) > 0: lane_lines.append(make_points(frame, right_fit_average)) return lane_lines def make_points(frame, line): height, width, _ = frame.shape slope, intercept = line y1 = height y2 = int(y1 / 2) if slope == 0: slope = 0.1 x1 = int((y1 - intercept) / slope) x2 = int((y2 - intercept) / slope) return [[x1, y1, x2, y2]] def display_lines(frame, lines, line_color=(0, 255, 0), line_width=6): line_image = np.zeros_like(frame) if lines is not None: for line in lines: for x1, y1, x2, y2 in line: cv2.line(line_image, (x1, y1), (x2, y2), line_color, line_width) line_image = cv2.addWeighted(frame, 0.8, line_image, 1, 1) return line_image def display_heading_line(frame, steering_angle, line_color=(0, 0, 255), line_width=5 ): heading_image = np.zeros_like(frame) height, width, _ = frame.shape steering_angle_radian = steering_angle / 180.0 * math.pi x1 = int(width / 2) y1 = height x2 = int(x1 - height / 2 / math.tan(steering_angle_radian)) y2 = int(height / 2) cv2.line(heading_image, (x1, y1), (x2, y2), line_color, line_width) heading_image = cv2.addWeighted(frame, 0.8, heading_image, 1, 1) return heading_image def get_steering_angle(frame, lane_lines): height,width,_ = frame.shape if len(lane_lines) == 2: _, _, left_x2, _ = lane_lines[0][0] _, _, right_x2, _ = lane_lines[1][0] mid = int(width / 2) x_offset = (left_x2 + right_x2) / 2 - mid y_offset = int(height / 2) elif len(lane_lines) == 1: x1, _, x2, _ = lane_lines[0][0] x_offset = x2 - x1 y_offset = int(height / 2) elif len(lane_lines) == 0: x_offset = 0 y_offset = int(height / 2) angle_to_mid_radian = math.atan(x_offset / y_offset) angle_to_mid_deg = int(angle_to_mid_radian * 180.0 / math.pi) steering_angle = angle_to_mid_deg + 90 return steering_angle video = cv2.VideoCapture(0) time.sleep(1) ##fourcc = cv2.VideoWriter_fourcc(*'XVID') ##out = cv2.VideoWriter('Original15.avi',fourcc,10,(320,240)) ##out2 = cv2.VideoWriter('Direction15.avi',fourcc,10,(320,240)) speed = 8 lastTime = 0 lastError = 0 prev_time = 0 FPS = 10 kp = 0.4 kd = kp * 0.65 while True: ret,frame = video.read() current_time = time.time() - prev_time if (ret is True) and (current_time > 1./ FPS) : prev_time = time.time() cv2.imshow('VideoCapture', frame) if cv2.waitKey(1) > 0 : break edges = detect_edges(frame) roi = region_of_interest(edges) line_segments = detect_line_segments(roi) lane_lines = average_slope_intercept(frame,line_segments) lane_lines_image = display_lines(frame,lane_lines) steering_angle = get_steering_angle(frame, lane_lines) heading_image = display_heading_line(lane_lines_image,steering_angle) cv2.imshow("heading line",heading_image) now = time.time() dt = now - lastTime deviation = steering_angle - 90 error = abs(deviation) k = cv2.waitKey(5) if k!= -1: print(k) if k == ord('q'): break if k == ord('s'): if start_flag == False: start_flag = True else: start_flag = False print('start_flag: ', start_flag) if deviation < 5 and deviation > -5: deviation = 0 error = 0 hw.motor_one_speed(30) hw.motor_two_speed(30) elif deviation > 5: hw.motor_one_speed(15) hw.motor_two_speed(80) elif deviation < -5: hw.motor_one_speed(80) hw.motor_two_speed(15) derivative = kd * (error - lastError) / dt proportional = kp * error PD = int(speed + derivative + proportional) spd = abs(PD) lastError = error lastTime = time.time() ## out.write(frame) ## out2.write(heading_image) video.release() ##out.release() ##out2.release() cv2.destroyAllWindows() hw.motor_clean()

9줄~16줄은 기본 화면에서 검은색과 가장자리를 검출하는 함수이다.

18줄~29줄은 프레임의 한 영역에만 관심영역을 폴리곤으로 설정하는 함수이다.

31줄~37줄은 1픽셀단위의 거리정밀도와 180라디안의 각도정밀도를 가지고 hough변환을 사 용하여 라인을 감지하기 위해 쓰이는 함수이다.

39줄~70줄은 앞에서 hough변환을 사용하여 감지된 라인의 기울기를 구하기 위해서 필요한 함수이다. 가운데 직선을 0이라고 치면 왼쪽선분과 오른쪽선분의 기울기가 다르기 때문에 정확하게 하기위해서 영역을 가운데를 기준으로 반반 나누고 왼쪽은 음의 기울기, 오른쪽은 양의 기울기를 각각 가진다.

72줄~81줄은 차선의 경계좌표를 반환해주는 average_slope_intercept()함수를 도와주는 함수이다.

83줄~90줄은 프레임에 차선을 표시해주는 함수이다.

93줄~103줄은 메인 선을 그려질 프레임과 각도를 입력으로 사용하는 함수이다.

105줄~123줄은 선 개수에 따른 메인 선을 구하기 위해 사용하는 함수이다. 선이 두 개일 경우, 한 개일 경우, 감지되지 않을 경우를 설정한다.

125줄은 비디오캡처를 위한 부분이다.

142줄부터는 메인함수이다. 143줄~152줄은 비디오캡처를 출력하는 부분이고 157줄~164줄은

위에서 정의한 함수들을 불러오는 부분이다. 166줄~ 모터의 속도를 제어하기위한 부분인데 q를 입력하면 정지하고 s를 입력하면 출발한다. 또한 169줄에서 정의한 deviation은 105줄에서 정의한 함수에 의해 구해진 값에서 90을 뺀다. 이 뺀 값이 0이되도록 진행이 되어야 직선구간에서 일직선으로 간다고 할 수 있다. deviation이 0에 가까워지면 그만큼 직선에 가깝다는 거기에 양쪽바퀴를 동일한 속도로 작동시킨다. deviation가 너무 커서 양수쪽으로 간다면 앞에서 구한 값이 양수가되어 직선기준 오른쪽으로 진행중인 상태이므로 왼쪽으로 진행해야하므로 왼쪽바퀴인 moter_one_speed를 낮게주고 moter_two_speed를 높게줘서 왼쪽으로 방향전환을 하도록 하고 음수가되면 오른쪽으로 진행해야하므로 moter_one_speed를 높게주고 moter_two_speed를 낮게줘서 오른쪽으로 방향전환을 하도록 하였다.

4. 마무리

4.1. 향후 추진계획

향후 추진계획으로는 전반기 기말 발표에서 시연한 자율 주행 자동차를 구현할 때 여건상 개발하지 못한 기능인 ‘장애물 인식’,‘신호등 인식’ 등 카메라를 이용하여 장애물과 빛의 색 등을 인식하여, 그저 차선 안에서만 움직이는 자동차에서 상황에 맞게 멈춰야 할 때, 속도를 줄여야 할 때, 비켜 가야 할 때를 스스로 인식하고 판단하고 움직일 수 있게 만드는 것이 목표이다.

주로 이용하게 될 코드는 Python Opencv 에서 제공하는 오픈소스를 이용하여 비록 실제 자동차는 아니지만, 마치 사람이 직접 조종하는 듯한 느낌을 줄 수 있도록 하는 것이 목표이다. 앞서 선보였던 자율주행 자동차는 많은 기능을 개발하고 싶었던 욕심에 비해 오렌지파이의 성능이 기대에 미치지 못하였기 때문에 향후 더 좋은 성능의 컴퓨터를 활용하여 더 향상된 차선 인식 능력과 그 외 더 많은 기능을 개발할 예정이다.

자율주행 자동차 키트와 온 카메라, 오렌지 파이는 처음에는 영상을 잘 인식하는 듯하였으나, 너무 좁은 시야각, 컴퓨터의 낮은 성능으로 인해 프레임이 안나오는 등 불편한 점이 한 두가지가 아니었으나 후반기 졸업전시회 때는 1학기 때와 비교하여 훨씬 더 고성능의 차량을 제작 할 예정이다.

4.2. 정리

팀원들과 가까이 지내며 우리 스스로 정한 과제를 어떻게 하면 더 잘 만들고, 잘 보여줄 수 있으며, 최대한의 효율로 작업을 할 수 있을까 함께 고민하며 팀원들의 중요성을 느꼈다. 짧았지만, 한 학기 동안 각자 아이디어를 내고 각자 맡은 역할에서 최선을 다하면서 함께 성장해 나가는 것을 느꼈다.

팀원 모두가 관심 있는 아이디어였기 때문에, 의견충돌은 전혀 없었으며 굉장히 화목한 분위기에서 과제를 수행 해 나갔다.

처음에는 OpenCV를 이용하기 때문에 이미 나와 있는 코드를 사용하는 것이라 쉬울 것 이라고 생각 했지만, 결과는 마음처럼 따라주지 않았다. 생각보다 훨씬 낮은 컴퓨터의 성능과 자동차 조립의 어려움, 자동차 균형이 맞지 않는 등 실제 겁먹고 있었던 개발과는 거리가 먼 예상치 못한 부분에서 애를 먹었다. 하지만 모르고 막힐 때 마다 팀원들이 서로 조언과 응원을 하며, 포기하지 않았고, 최종결과물은 학기 초반 상상하던 결과물에 비하면 크게 동떨어졌지만, 이렇게 팀원들과 협업 하며 의사소통의 중요성과 팀플레이의 강력함을 느꼈다. 서로가 서로를 가르쳐주며 팀원들의 실력이 향상에 도움이 되는 효과도 있었으며, 팀플레이를 하지 않는 다른 수업에서 훨씬 더 많은 것을 배워갔다고 생각한다.

앞서 공개한 자율주행자동차를 개발하며 어떤 점이 힘들고, 어떤 점이 불편한지 충분히 파악했으며, 이 경험을 바탕으로 다음 학기에는 더 철저히 계획하고 작업도 효율적으로 할 수 있을 거라 믿어 의심치 않는다. 어떻게 하면 어떤 에러가 나고, 어떤 작업이 생각보다 시간을 많이 잡아먹는지,  데이터를 쌓았기 때문에,  조만간 다가올 졸업전시회 에서는  모두가 깜짝 놀랄만한 작품을 내어놓을 수 있을 것이다.