# 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__
[ESP32_BNO085] IMU 값 받기 (0) | 2021.01.18 |
---|
댓글 영역