22. [ROS RC์นด] ์นด๋ฉ๋ผ ROS ์ฐ๋
ํ์ด์ฌ์ ์ฌ์ฉํด์ ์ ฏ์จ ์นด๋ฉ๋ผ๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
์ด์ ์๊ฐ์ ๋ณต์ต์ ํด๋ณผ๊น์??
์นด๋ฉ๋ผ ์ฐ๊ฒฐ ํ์ธ
$ cd ~/Downloads
$ git clone https://github.com/JetsonHacksNano/CSI-Camera.git
$ gst-launch-1.0 nvarguscamerasrc sensor_id=0 ! \
'video/x-raw(memory:NVMM),width=3280, height=2464, framerate=21/1, format=NV12' ! \
nvvidconv flip-method=2 ! 'video/x-raw,width=960, height=720' ! \
nvvidconv ! nvegltransform ! nveglglessink -e
# ์ข
๋ฃ๋ ctrl + c๋ก ๊ฐ๋ฅํฉ๋๋ค!!
sensor_id
์ flip
์ ๋ฐ๋์ ํ์ธํด์ฃผ์ธ์!! -
์ด๋ ์นด๋ฉ๋ผ ์ฐ๊ฒฐ ์ ์ฌ์ฉํ ์ฌ๋กฏ๊ณผ ์ฐ๊ด์์ต๋๋ค!!
์ด๋ฒ ์๊ฐ์ ๋ค๋ฃจ๋ ์์ ๋ค์ ๋ชจ๋ donkey_ros/csi_camera ํด๋์ ์์นํด ์์ต๋๋ค.
OpenCV4 ์ค์น, Setup
์ถํ ๋ง์ ํ๋ก์ ํธ์ ๋๋นํ์ฌ Jetson์ OpenCV4๋ฅผ ์ค์นํ๊ณ , ๊ทธ ์ดํ ROS cv_bridge๊ฐ ์๋ก ์ค์นํ OpenCV๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก ์์ ํด ๋ณด๊ฒ ์ต๋๋ค.
- ๋๋ต 2์๊ฐ 30๋ถ ์ ๋๊ฐ ์์๋ฉ๋๋ค. ๐๐
$ cd ~/Downloads
$ git clone https://github.com/JetsonHacksNano/buildOpenCV
$ cd buildOpenCV
$ ./buildOpenCV.sh |& tee openCV_build.log
$ sudo gedit /opt/ros/melodic/share/cv_bridge/cmake/cv_bridgeConfig.cmake
# ์์ ์
set(_include_dirs "include;/usr/include;/usr/include/opencv")
# ์์ ํ
set(_include_dirs "include;/usr/include;/usr/include/opencv4")
Webcam Publish - Desktop
#!/usr/bin/env python
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FPS, 30)
rospy.init_node("webcam_pub", anonymous=True)
image_pub = rospy.Publisher("webcam_image", Image, queue_size=1)
bridge = CvBridge()
while not rospy.is_shutdown():
# Capture frame-by-frame
ret, cv_image = cap.read()
# Display the resulting frame
# cv2.imshow('frame',cv_image)
# cv2.waitKey(3)
image_pub.publish(bridge.cv2_to_imgmsg(cv_image, "bgr8"))
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
- ๋จผ์ ์คํ๋ถํฐ ์์ผ๋ณด๊ฒ ์ต๋๋ค ๐
$ roscore
$ rosrun csi_camera webcam_pub.py
$ rosrun image_view image_view image:=/webcam_image
# jetson
$ roscore
$ rosrun csi_camera csi_pub.py
$ rosrun image_view image_view image:=/csi_image
image_view
์ด๋ฏธ์ง topic์ ์ดํด๋ณผ ์ ์๊ฒ ํด์ฃผ๋ ํด์ ๋๋ค. ๋๋ถ์ด, ๋ง์ฐ์ค ์ค๋ฅธ์ชฝ ํด๋ฆญ์ ํ๋ฉด, ํ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํ ์๋ ์๋ต๋๋ค. ๐ต๏ธโโ๏ธ
image:=/
๋ค์ ์ดํด๋ณด๊ณ ์ถ์ ์ด๋ฏธ์ง ํ ํฝ
์ด๋ฆ์ ์จ์ ๋ณผ ์ ์์ต๋๋ค.
์ฝ๋ ์ค๋ช ์ผ๋ก ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
- import
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
์์ cv_bridge
๊ฐ opencv4
๋ฅผ ๋ฐ๋ผ๋ณด๋๋ก
๋ฐ๊พธ์์ง์??
- video stream ์ค์
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FPS, 30)
rospy.init_node("webcam_pub", anonymous=True)
image_pub = rospy.Publisher("webcam_image", Image, queue_size=1)
bridge = CvBridge()
๊ฐ๋ก, ์ธ๋ก, Frame Per Second ๋ฑ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํ๊ณ
Publisher
๋ฅผ ์์ฑํ์์ต๋๋ค.
- Publish
while not rospy.is_shutdown():
# Capture frame-by-frame
ret, cv_image = cap.read()
# Display the resulting frame
# cv2.imshow('frame',cv_image)
# cv2.waitKey(3)
image_pub.publish(bridge.cv2_to_imgmsg(cv_image, "bgr8"))
opencv์ ros์์ ์ฌ์ฉํ๋ ์ด๋ฏธ์ง ํฌ๋งท์ด ๋ค๋ฅด๊ธฐ ๋๋ฌธ์,
cv2_to_imgmsg
๋ฅผ ํตํด ๋ณํํด์ฃผ๊ณ ์์ต๋๋ค.
- ์ข ๋ฃ ์ฒ๋ฆฌ
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
์น์บก์ด ์๋, CSI ์นด๋ฉ๋ผ๋ฅผ ์ฌ์ฉํด ๋ด ์๋ค.
csi_pub
$ roscore
$ rosrun csi_camera csi_pub.py
$ rosrun image_view image_view image:=/csi_image
- csi_pub.py
#!/usr/bin/env python
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
def gstreamer_pipeline(
capture_width=640,
capture_height=480,
display_width=640,
display_height=480,
framerate=60,
flip_method=0,
):
return (
"nvarguscamerasrc ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
% (
capture_width,
capture_height,
framerate,
flip_method,
display_width,
display_height,
)
)
cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=2), cv2.CAP_GSTREAMER)
rospy.init_node("csi_pub", anonymous=True)
image_pub = rospy.Publisher("csi_image", Image, queue_size=1)
bridge = CvBridge()
while not rospy.is_shutdown():
# Capture frame-by-frame
ret, cv_image = cap.read()
# Display the resulting frame
# cv2.imshow('frame',cv_image)
# cv2.waitKey(3)
image_pub.publish(bridge.cv2_to_imgmsg(cv_image, "bgr8"))
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
ํจ์ ํ๋๊ฐ ์ถ๊ฐ๋์๋๋ฐ์, ์ด๊ฒ์ ๋ํด์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
"nvarguscamerasrc ! "
"video/x-raw(memory:NVMM), "
"width=(int)%d, height=(int)%d, "
"format=(string)NV12, framerate=(fraction)%d/1 ! "
"nvvidconv flip-method=%d ! "
"video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
"videoconvert ! "
"video/x-raw, format=(string)BGR ! appsink"
์ด ๊ธด ๋ฌธ์์ด์ ๋ฌด์์ผ๊น์?? ๊ฐ์ ์ด๋ฐ์ ๋ณต์ตํ๋ฉด์ ์ดํด๋ณด์๋ ์ปค๋งจ๋ ๋ผ์ธ์ด ๊ธฐ์ต๋์๋์?
$ gst-launch-1.0 nvarguscamerasrc sensor_id=0 ! \
'video/x-raw(memory:NVMM),width=3280, height=2464, framerate=21/1, format=NV12' ! \
nvvidconv flip-method=2 ! 'video/x-raw,width=960, height=720' ! \
nvvidconv ! nvegltransform ! nveglglessink -e
์ด ํจ์๋ ๋น๋์ค ํ์ดํ๋ผ์ธ์ ๋ค๋ฃจ๊ธฐ ์ํ ์ด ์ปค๋งจ๋ ๋ผ์ธ์ ํ์ด์ฌ ์ฝ๋๋ก ๊ตฌํํ ๊ฒ์ด๋๋๋ค. ๐
๋๋จธ์ง ๋ถ๋ถ์ ์์ ์์ ์ ๊ฐ์ต๋๋ค.
๋ณด๋์ค!! ์ด๋ฏธ์ง Streaming ์๋ฒ
$ sudo apt-get install ros-melodic-web-video-server -y
$ roscore
$ rosrun csi_camera csi_pub.py
$ rosrun web_video_server web_video_server
# chrome
http://localhost:8080
ros์์ ๊ธฐ๋ณธ ์ ๊ณตํ๋ ์ด๋ฏธ์ง ์คํธ๋ฆฌ๋ฐ ์น์๋ฒ์ ๋๋ค. ์น ๊ฐ๋ฐ์์๋ผ๋ฉด, ์ด๋ฅผ ์ด์ฉํ ์ฌ๋ฌ๋ถ๋ง์ ์น์ฑ์ ๋ง๋ค์ด ๋ณผ ์ ์๊ฒ ์ง์? ๐๐๐
์นด๋ฉ๋ผ๋ฅผ ROS๋ก ๋ค๋ค๋ณด๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ๋ํด ๋ฐฐ์๋ณด์์ต๋๋ค. ๋ค์ ๊ฐ์์์๋ ๋๋ค๋ฅธ ํ๋ก์ ํธ๋ฅผ ์งํํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ๐ธ๐ธ๐ธ