
프로그래머스에서 진행중인 자율주행 데브코스 - Planning & Control : ROS 기초부터 정리를 시작한다. 강의에서는 Ubuntu 18.04 - ROS Melodic로 진행하였으나 필자는 WSL - Ubuntu 20.04 - ROS Noetic 환경에서 강의를 복기한다.
강의는 OpenCV 개론 및 ROS를 제외한 Open CV 실습이 있으나 이 부분은 모두 생략하고, 바로 ROS + OpenCV로 진행한다.
패키지의 의존성은 std_msgs, rospy로 설정하여 생성한다
$ catkin_create_pkg my_cam std_msgs rospy
다음으로 WSL에서 usb webcam 사용을 위한 사전설정을 해야 하는데 이는
아래 포스트를 참조하여 웹켐 설치 및 설정을 진행한다.
https://velog.io/@tbvjvsladla/WSL-usb-webcam%EC%82%AC%EC%9A%A9#5-%EC%9B%B9%EC%BA%A0-%EC%8B%A4%ED%96%89
PowerShell 관리자권한 실행
usbipd wsl attach --busid [웹켐 버스 아이디]
usbipd wsl list->이 명령어로 웹켐이 WSL우분투에 연결됨을 확인
우분투 터미널에서 USB Webcam 디바이스 확인 및 권한 설정
$ lsusb-> 디바이스가 연결되었는지 확인
$ ll /dev/video*-> 디바이스가 USB웹캠이니 video번호 확인
$ shdo chmod 777 /dev/video0-> 디바이스 0번 권한 최대권한으로
첫번째로 roslaunch 파일을 아래와 같이 작성했다
edge_cam.launch
<?xml version="1.0" encoding="utf-8"?>
<launch>
<node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen">
<!-- ROS의 USB_CAM 패키지를 사용한다. 아래는 USB_CAM의 설정해야할 파라미터 -->
<param name="video_device" value="/dev/video0" />
<param name="image_width" value="640" />
<param name="image_height" value="480" />
<param name="camera_frame_id" value="USB_CAM" />
<param name="io_method" value="mmap"/>
<!-- USB 웹캠의 속도 문제로 아래의 설정으로 해야한다. -->
<param name="pixel_format" value="yuyv" />
<param name="framerate" value="5"/>
<!-- 아래 부분은 카메라 노출값 조정인데 일단 적용하지 않는다. -->
<!-- <param name="autoexposure" value="false"/> -->
<!-- <param name="exposure" value="48"/> -->
>
</node>
>
<node name="my_cam_node" pkg="my_cam" type="edge_cam.py" output="screen"/>
</launch>
위 코드에서 카메라 노출값 조정 부분은 주석처리했고
나머지 설정중에서 좀 중요한 부분이
<param name="pixel_format" value="yuyv" />
<param name="framerate" value="5"/>
인 부분인데

[ERROR][1692695639.869789555]: select timeout
[usb_cam-2] process has died [pid 8540, exit code 1, cmd /opt/ros/noetic/lib/usb_cam/usb_cam_node name:=usb_cam log:=/home/ash/.ros/log/375e7bba-40cc-11ee-9381-13e069639e24/usb_cam-2.log].
이렇게 에러 메세지가 올라오면서 USB 웹켐이 활성화가 되지 않는다.
이게... USB 대역폭 문제인 것으로 보이는데

위 사진처럼 guvcview 로 USB웹캠을 구동하면 MJPEG 파일 포맷으로 30fps로 출력이 나오긴 한다.
하지만 yuyv(YUV420)포맷으로 진행할 시 5fps로 설정해야 그나마 USB웹캠의 화면이 출력된다...
이 대역폭 문제는 좀 해결하려면 구글링을 더 해봐야 할 것 같은데
필자의 경우 ROS - 웹캠은 일단 연결해보는 것에 만족하고
OpenCV는 빠르게 넘어갈 생각이기에 5FPS로 설정하고 넘어간다.
다음으로는 edeg_cam.py코드 작성이다.
#!/usr/bin/env python #-*- coding:utf-8 -*- import cv2 import rospy import numpy as np from sensor_msgs.msg import Image from cv_bridge import CvBridge bridge = CvBridge() cv_image = np.empty(shape=[0]) def img_callback(data): global cv_image cv_image = bridge.imgmsg_to_cv2(data, "bgr8") rospy.init_node('cam_tune_node', anonymous=True) rospy.Subscriber("/usb_cam/image_raw/", Image, img_callback) while not rospy.is_shutdown(): if cv_image.size != (640*480*3): continue gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY) blur_gray = cv2.GaussianBlur(gray, (5, 5), 0) edge_img = cv2.Canny(np.uint8(blur_gray), 60, 70) cv2.imshow("Origin", cv_image) cv2.imshow("Gray", gray) cv2.imshow("Blur", blur_gray) cv2.imshow("edge", edge_img) cv2.waitKey(1)
위 코드에서 중요하게 볼 부분은
from cv_bridge import CvBridge
cv_image = bridge.imgmsg_to_cv2(data, "bgr8")
이 부분으로
원래 ROS에서 Image 데이터의 송/수신은 sensor_msgs.msg/Image를 통해서 진행된다.

그런데 이게 OpenCV 라이브러리에서 정의한 이미지 포맷과는 매칭이 되지 않는 부분이 있다.
이게 단순 데이터 포맷만 매칭하는거면 상관없는데 OpenCV는 라이브러리 개념으로 무게가 나가는 코드 집합이다 보니
ROS에서는 CV_Bridge라는 브릿지 패키지를 제공함으로써
ROS내 이미지 데이터 포맷과 OpenCV 이미지 데이터 포맷을 전환해주는
컨버팅 작업을 지원하고 있다.

대체로 ROS와 다른 프로그램 혹은 라이브러리가 연동된다 하면
위와 같은 Bridge가 컨버드 역활을 수행하여 연동을 매끄럽게 지원해준다 알고 넘어가면 된다.
그 외 코드는 중요한 부분은 없고
차선 검출(엣지 검출)을 하려면 아래 절차를 꼭 수행한다 보면 된다.

솔직히 OpenCV로 무언가 처리된 이미지를 출력(전처리 과정)은
구글링 하면 필터 적용 과정부터 파라미터 조정 값까지 전부 공개되어 있고
필자는 영상쪽은 관심이 없어서 이렇게 짧게 인지하고 넘어간다.
아무튼 위 코드를 다 작성후 결과물은 아래와 같이 구동될 것이다.

FPS가 5FPS이기 때문에 카메라 품질은 거의 박살난 수준이지만
일단 이정도로 하고 넘어간다.
다음 차선 검출 알고리즘이 더 중요하고 급하다...