권영재_자율주행 RC카 제작 결과 보고서
활동 보고서
권*재
2024-07-26
[프로젝트 개요] 파이썬과 아두이노를 이용하여 자율주행을 하는 RCCAR를 3D모델링으로 제작한뒤 주행시키는 프로젝트이다
[설계 및 계획] 나는 전륜 구동 4륜 자동차를 만들었고 앞 범퍼부분과 보조배터리 및 회로 수납칸을 솔리드웍스 프로그램을 통해 디자인 한뒤 3D프린터를 이용하여 제작 하였다.
[제작 과정] 먼저 골지판으로 차량의 뼈대를 구성하고 실리콘으로 모터를 골지판과 접합시킨 뒤 그 위에 아두이노 판을 실리콘으로 접합하고 나머지를 수납하기 위한 3D프린터 출력물로 실리콘으로 접합시킨뒤 그 위에 보조배터리와 모터드라이브, 배터리셀등을 장착 시켰다. 또한 앞쪽 범퍼 부분에 ESP32(카메라)를 부착시켰다. 먼저 ESP32 환경 세팅을 해주고 이를 아두이노에 연결 시킨뒤에 파이썬으로 ESP32로 부터 획득한 사진을 가우시안 필터링 및 에지검출을 이용하여 캘리브레이트를 해줘 트랙의 파란 라인의 중심값을 읽어 낸뒤 그걸 따라가도록 자율주행 할수 있는 코드를 작성하여 실행시켰다.
[코드 구조 및 설명] import cv2 import urllib.request import numpy as np import time IP_ADDR = '192.168.0.75' def go_backward(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=a') time.sleep(0.05) def turn_left(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=c') time.sleep(0.1) def turn_right(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=b') time.sleep(0.1) def calibrate_left(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=c') time.sleep(0.04) def calibrate_right(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=b') time.sleep(0.04) def go_forward(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=d') time.sleep(0.1) def stop(): urllib.request.urlopen('http://'+IP_ADDR+':80/command?cmd=e') def onMouse(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: print(x, y) cv2.namedWindow("live transmission", cv2.WINDOW_AUTOSIZE) stop_cnt = 0 while True: img_resp = urllib.request.urlopen('http://'+IP_ADDR+'/cam-hi.jpg') imgnp = np.array(bytearray(img_resp.read()), dtype=np.uint8) frame = cv2.imdecode(imgnp, -1) (h1, w1) = frame.shape[:2] frame = frame[600:h1, :] (h, w) = frame.shape[:2] topLeft = (348, 0) # x+y가 가장 값이 좌상단 좌표 topRight = (1335, 0) # x+y가 가장 큰 값이 우하단 좌표 bottomLeft = (0, 588) # x-y가 가장 작은 것이 우상단 좌표 bottomRight = (1600, 600) pts1 = np.float32([topLeft, topRight, bottomRight, bottomLeft]) w1 = abs(bottomRight[0] - bottomLeft[0]) w2 = abs(topRight[0] - topLeft[0]) h1 = abs(topRight[1] - bottomRight[1])+600 h2 = abs(topLeft[1] - bottomLeft[1])+600 width = int(max([w1, w2])) # 두 좌우 거리간의 최대값이 서류의 폭 height = int(max([h1, h2])) # 두 상하 거리간의 최대값이 서류의 높이 pts2 = np.float32([[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]]) # 변환 행렬 계산 mtrx = cv2.getPerspectiveTransform(pts1, pts2) # 원근 변환 적용 frame = cv2.warpPerspective(frame, mtrx, (width, height)) # 파란색, 빨간색, 초록색 채널 추출 blue_channel = frame[:, :, 0] green_channel = frame[:, :, 1] red_channel = frame[:, :, 2] # 조건에 맞는 픽셀 필터링 blue_filtered = np.zeros_like(blue_channel, dtype=np.uint8) blue_mask = np.logical_and(blue_channel >= 170, np.logical_and(red_channel <= 177, green_channel <= 172)) blue_filtered[blue_mask] = 255 # 이진화를 위해 255로 설정 kernel = np.ones((5, 5), np.uint8) blue_filtered = cv2.morphologyEx(blue_filtered, cv2.MORPH_OPEN, kernel) edges = cv2.Canny(blue_filtered, 10, 100, apertureSize=3) (w, h) = blue_filtered.shape[:2] points = cv2.findNonZero(blue_filtered) if points is not None: meaned_point = np.mean(points, axis=0)[0] meaned_point_x = int(meaned_point[0]) meaned_point_y = int(meaned_point[1]) cv2.circle(frame, (meaned_point_x, meaned_point_y), 5, (255, 255, 255), -1) cv2.line(frame, (h//3, 0), (h//3, w), (255, 255,255), 5) cv2.line(frame, (h//3*2, 0), (h//3*2, w), (255, 255,255), 5) if meaned_point_x < (h//3): calibrate_left() elif meaned_point_x > (h//3*2): calibrate_right() else: go_forward() else: go_backward() frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) cv2.imshow("live transmission", blue_filtered) cv2.setMouseCallback("live transmission", onMouse) key = cv2.waitKey(5) if key == ord('q'): stop() break stop() cv2.destroyAllWindows() ESP32로 얻은 사진을 캘리브레이션을 통해 라인의 중간값을 얻어내어 그 중간지점을 따라 주행하도록 설게된 코드이다. 블루, 그린, 레드 채널의 값을 수정하여 보다 깔끔하게 캘리브레이션할 수 있도록 수정할 수 있다. 위에 방향 조절 함수는 타임 딜레이 값을 수정하여 자율주행의 속도를 개선할 수 도 있다.
[성능 테스트 및 평가] 코드를 수정하지 않고 그대로 실행시켰을 때 불안정 하지만 완주에 성공하였다. 하지만 수정을 거치자 우회전을 잘 안하게 되어 문제가 생겼다. 고치려 해봐도 계속 우회전대신 좌회전을 하려는 경향을 보여 애를 먹었다. 그래도 완주에 한번 성공한 것에 의의를 두려 한다.
[결과 및 결론] 블루필터값을 섬세하게 수정하는 것과 타임 딜레이를 최상의 조건으로 맞추는 것이 안정적인 자율주행과 자율주행속도를 높이는 것의 핵심임을 꺠달았다. 비록 완주시간이 아쉬웠지만 그래도 무사히 교육을 잘 따라가 주행을 마쳐서 뿌듯했다. 3D모데링 실력과 가우시안필터, 다양한 컴퓨터 비전 지식, 자율주행 원리 등등 정말 많은 것을 배웠다. 이번 프로그램에서 많은 걸 배우고 나니 다음에 또 이런 자율주행 모델 개발 및 3D모델링 프로그램이 있으면 흥미를 가지고 다시한번 참여하고 싶다. 이런 프로그램을 진행해주신 모든 분꼐 감사의 말씀을 전한다.