상세 컨텐츠

본문 제목

[Python-ROS 통신] Python으로 ROS 메세지 통신 (QR코드 인식해서 ROS로 보내기)

Implement/__Embedded

by 2_54 2020. 9. 5. 01:08

본문

# Python ROS 메세지 통신

 

이번 대회 준비하며 ros로 메세지를 통신해야하는데

나는 python 코드를 실행하며 통신을 해야해서

이에 대해 짧게 구현해보았다.

 

 

★ 1. 패키지 만들기 ★

cd ~/catkin_ws/src
catkin_create_pkg rosa_python std_msgs rospy

catkin_ws/src 폴더에 들어가서 패키지를 만든다.

catkin_create_pkg (원하는 패키지 이름) std_msgs rospy

이름은 마음대로 하면 된다.

 

★ 2. 메세지 파일 생성하기 ★

 

roscd rosa_python
mkdir msg
echo "int64 num"> msg/Num.msg

위에서 만든 패키지에 들어가서 메세지파일을 만든다.

 

★ 3. Package.xml 수정하기

 

gedit package.xml

package.xml 파일을 수정해야한다.

 

밑에 내리다보면

 

<build_depend>message_generation</build_depend>

<exec_depend>message_runtime</exec_depend>

이 놈들이 주석되어있는데 주석을 풀어준다.

 

★ 4. Publisher 생성하기 ★

 

mkdir scripts
cd scripts
gedit talker.py

퍼블리셔를 생선한다.

python파일에 아래와 같이 입력하고 저장한다.

 

Tap 잘 맞춰서 해주기!

#!/usr/bin/env python   
# 스크립트가 실행 가능한지 확인


import rospy

from std_msgs.msg import String

def talker(): 
      pub = rospy.Publisher('chatter',String,queue_size=10) # chatter 토픽에게 publisher하겠다고 선언
      rospy.init_node('talker', anonymous = True) #코드 이름을 알려주기, 이 정보를 얻기 전까지 ros master와 통신x
      rate = rospy.Rate(10) #10hz

      while not rospy.is_shutdown(): #ctrl+c 눌러서 멈추기 전까지 실행
            send_str = "hello world %s" % rospy.get_time()
            rospy.loginfo(send_str)                                                       #화면에 프린트, 노드의 로그파일에 기록, rosout에 기록
            pub.publish(send_str)                                                           #위 pub에 send_str를 인수로 준다.(토픽에게 publisher)
            rate.sleep() 

if __name__=='__main__':
      try:
            talker()
     except rospy.ROSInterruptException:
            pass

입력 후

chmod +x talker.py

실행 가능한 파일로 퍼미션 변경을 해준다.

 

★ 5. Subscriber 생성하기 ★

gedit listner.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import String

def callback(data):
      rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)

def listener():     
      rospy.init_node('listener',anonymous=True)
      rospy.Subscriber("chatter", String, callback)
      rospy.spin()

if __name__=='__main__':
      listener()
chmod +x listener.py

퍼블리셔와 마찬가지로 실행가능한 파일로 퍼미션 변경을 해준다.

 

그 후

터미널을 3개 열어서

roscore
rosrun rosa_python talker.py
rosrun rosa_python listener.py

각 터미널에 한 줄씩 입력하면 값이 보내지고 받아지는 것을 확인할 수 있다.

 

 

★ 5. 응용 ★

 

나는 QR코드를 인식해서

ros로 메세지를 보내기 위해

QR코드 python코드에 ros 코드를 추가하였다.

#!/usr/bin/env python
import pyzbar.pyzbar as pyzbar
import cv2
import rospy from std_msgs.msgimport String
import sys

def qr_cord():
     cap = cv2.VideoCapture(0)

     while (cap.isOpened()):
             ret, img = cap.read()
             pub = rospy.Publisher('chatter',String,queue_size=10)
             rospy.init_node('talker', anonymous = True)

             if not ret:
                          continue

             gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
             decoded = pyzbar.decode(gray)

             for d in decoded:
                          x, y, w, h = d.rect
                          barcode_data = d.data.decode("utf-8")
                          barcode_type = d.type
                          cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
                          text = '%s (%s)' % (barcode_data, barcode_type)
                          cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2, cv2.LINE_AA)
                          send_str = barcode_data
                          rospy.loginfo(send_str)
                          pub.publish(send_str)
                          rospy.sleep(0.25)
             cv2.imshow('img', img)

             key = cv2.waitKey(1)
             if key == ord('q'):
                          break

if __name__=='__main__':
             while(1):
                          try:qr_cord()
                          except rospy.ROSInterruptException:pass
cap.release()
cv2.destroyAllWindows()

실행 결과

 

잘 보내지고 잘 받아지는 것을 확인할 수 있다. *^^*

 

혹시나!!

 

실행했을 때

ImportError: /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so: undefined symbol: PyCObject_Type

이렇게 ros와 python이 충돌하는 오류가 생길 수 있다.

 

블로그를 뒤져서 해결하였다.

 

cd /usr/local/lib/python3.5/dist-packages

위 폴더에 들어간다.

sudo mv /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so /opt/ros/kinetic/lib/python2.7/dist-packages/cv2.so.old

그리고 원래 있던 python2.7버전의 cv2.so 이름을 바꿔준다.

그리고

ls -al /opt/ros/kinetic/lib/python2.7/dist-packages

sudo ln -s `pwd`/cv2.cpython-35m-x86_64-linux-gnu.so `pwd`/cv2.so

ls -al

위를 순서대로 수행한다.

 

이렇게 했더니 난 오류가 해결되었다.

 


휴..

이제 집에 가야지..

 

__END__

반응형

'Implement > __Embedded' 카테고리의 다른 글

[ESP32_BNO085] IMU 값 받기  (0) 2021.01.18

관련글 더보기

댓글 영역