[ROS] Tutorials
rospy는 ROS를 파이썬으로 사용하기위해 최적화된 라이브러리 중 하나다.
C++ 버전으로 사용하는 roscpp이랑 비교하자면 OOP 방식으로 돌아가니 별반 차이는 없을 듯 하다.
연구실 과제로 TurtleBot3를 사용 중인데 사용하는 프로그램이 python으로 돌아가다보니 rospy에 대한 정보를 찾아보게 되었고 이에 공부한 정보를 토대로 나의 편의성을 위해 블로그에 자료를 정리하기로 했다.
참고사항으로 노트북에서 ROS를 돌리고 이 글을 적는 환경은 Desktop이니 때문에 실습 화면은 없을 예정이다.
Tutorials
rospy_tutorials - ROS Wiki
시작하기에 앞서 다음 튜토리얼을 진행하기 위해 ros_tutorials 파일을 저장해두자.
~$ cd catkin_ws
~/catkin_ws$ cd src
~/catkin_ws/src$ git clone https://github.com/ros/ros_tutorials.git
~/catkin_ws/src$ cd ros_tutorials
~/catkin_ws/src/ros_tutorials$ roscd rospy_tutorials
~/catkin_ws/src/ros_tutorials/rospy_tutorials$ ls
001_talker_linstner/
002_headers/
003_listener_with_user_data/
004_listener_subscribe_notify/
005_add_two_inits/
006_parameter/
007_connection_header/
008_on_shutdown/
009_advanced_publish/
010_publish_pointcloud2/
|
Creating a ROS Package
ROS/Tutorials/CreatingPackage - ROS Wiki
튜토리얼을 진행하기 전에 ROS 패키지를 만드는 방법에 대해 알아볼 필요가 있다.
패키지를 만들기 위해선 catkin을 이용해 사전 준비 파일을 만들어야 하는데 차례대로 알아보자.
- Catkin compliant package.xml
패키지에 대한 meta 정보를 만들어낸다.
- CMakeLists.txt which uses catkin
Writing the Publisher Node (Talker.py)
rospy_tutorials/Tutorials/WritingPublisherSubscriber - ROS Wiki
"Node"란 Ros Network에서 사용하는 실행 파일을 의미한다.
이 예제에서 메세지를 보내는 Publisher 역할의 "talker" 노드를 만들어보자.
그 전에 CMakeLists.txt 안에 아래 문구를 넣어줘야 스크립트가 제대로 동작하니 확인해주도록 하자.
catkin_install_python(PROGRAMS scripts/talker.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
|
~/catkin_ws/src/ros_tutorials/rospy_tutorials/001_talker_linstner$ gedit talker.py
1 #!/usr/bin/env python
2 # license removed for brevity
3 import rospy
4 from std_msgs.msg import String
6 def talker():
7 pub = rospy.Publisher('chatter', String, queue_size=10)
8 rospy.init_node('talker', anonymous=True)
9 rate = rospy.Rate(10) # 10hz
10 while not rospy.is_shutdown():
11 hello_str = "hello world %s" % rospy.get_time()
12 rospy.loginfo(hello_str)
13 pub.publish(hello_str)
14 rate.sleep( )
16 if __name__ == '__main__':
17 try:
18 talker()
19 except rospy.ROSInterruptException:
20 pass
1 #!/usr/bin/env python
코드의 항상 위에 아래 선언문을 작성해줘야 ROS Python 노드가 제대로 동작할 수 있다.
* The first line makes sure your script is executed as a Python script.
3 import rospy
4 from std_msgs.msg import String
Ros Node를 작성하기위해 rospy를 불러온다.
String Message 타입을 Publishing하기 위해 std_msgs.msg만 따로 불러온다.
7 pub = rospy.Publisher('chatter', String, queue_size=10)
String.string 타입의 메세지를 사용하는 'chatter' topic를 publishing한다.
queue_size를 제한함으로서 구독자는 데이터 패킷을 적당히 받도록 조절할 수 있는듯 하다.
8 rospy.init_node('talker', anonymous=True)
다음 구문은 우리가 만드는 노드의 이름을 초기화해주는 아주 중요한 부분이다.
* 초기화없이는 ROS Master와 통신이 이뤄질 순 없다.
anonymous=True로 설정하면 노드의 이름 뒤에 임의 숫자가 붙어 unique한 이름을 가질 수 있도록 도와준다.
9 rate = rospy.Rate(10) # 10hz
sleep( ) method의 도움으로 원하는 Rate만큼 반복시킬 수 있다.
위 구문에서 나타내는 말은 1초에 10번 반복 시행함을 의미한다. (즉, 10Hz)
10 while not rospy.is_shutdown():
11 hello_str = "hello world %s" % rospy.get_time()
12 rospy.loginfo(hello_str)
13 pub.publish(hello_str)
14 rate.sleep()
while문에서 rospy.is_shudown()가 의미하는바 가장 쉬운 예로 Ctrl - C 를 이용해서 프로그램이 끝나는 경우를 확인한다.
rospy.loginfo(hello_str)를 이용하면 우리가 보내려는 메세지를 화면에 출력시킬 수 있다. 그리고 Node의 log와 rosout에 기록됨
pub.publish(hello_str) 구문으로 해당 문자열을 'Chatter' topic으로 Publish할 수 있다.
17 try:
18 talker()
19 except rospy.ROSInterruptException:
20 pass
rospy.ROSInterruptException은 sleep() 명령어 이후에도 코드가 계속 진행되는 것을 막기위해 예외처리하는 구문이다.
Writing the Publisher Node (Listener.py)
rospy_tutorials/Tutorials/WritingPublisherSubscriber - ROS Wiki
먼저 Listener.py를 사용하기위해 CMakeLists.txt에서 다음과 같이 수정하도록 하자.
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )
|
01 #!/usr/bin/env python
02 import rospy
03 from std_msgs.msg import String
04
05 def callback(data):
06 rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
07
08 def listener():
09
10 # In ROS, nodes are uniquely named. If two nodes with the same
11 # name are launched, the previous one is kicked off. The
12 # anonymous=True flag means that rospy will choose a unique
13 # name for our 'listener' node so that multiple listeners can
14 # run simultaneously.
15 rospy.init_node('listener', anonymous=True)
17 rospy.Subscriber("chatter", String, callback)
19 # spin() simply keeps python from exiting until this node is stopped
20 rospy.spin()
22 if __name__ == '__main__':
23 listener()
구조는 talker.py와 유사하지만 메세지를 구독하는 새로운 callback 방식이 있다.
15 rospy.init_node('listener', anonymous=True)
'listener'라는 노드를 초기화 생성한다.
만약, 같은 이름의 노드가 나타나면 그 이전 노드와 충돌하기 때문에
ROS는 항상 개별 노드들이 unique한 이름을 가지도록 함을 알고있자.
앞선 예제와 마찬가지로 anynoymous=True로 함으로서 비슷한 이름의 노드가 들어올 때 마다 각 개별 노드에 번호를 부여해 수많은 다중의 listener.py 노드를 쉽게 만들고 돌아가도록 할 수 있다.
17 rospy.Subscriber("chatter", String, callback)
String 타입으로 'chatter' topic을 새로 구독한다.
그러면 새로운 메세지를 받을때, 첫 번째 인수로 그 메시지와 함께 callback이 호출된다.
19 # spin() simply keeps python from exiting until this node is stopped
20 rospy.spin()
노드를 끝내기 전까지는 종료하지않도록 잡아주는 역할을 한다.
Building your nodes
rospy_tutorials/Tutorials/WritingPublisherSubscriber - ROS Wiki
파일 설정을 비롯해서 코드 작성이 끝났으면 노드 작성을 하도록 하자.
위치는 catkin_ws 에서 아래와 같이 명령어를 입력해주면 여러창이 좌르륵 뜰거다.
$ cd ~/catkin_ws
$ catkin_make
|
shell 1 ~ $ roscore
|
shell 2 ~ $ rosrun beginner_tutorials talker.py
|
shell 3 ~ $ rosrun beginner_tutorials listener.py
|
댓글