9.1 撰寫publisher node

回想一下, node在ROS裡面扮演的角色為一個在ROS network當中的可執行檔(executable), 我們現在來寫一個為一直持續廣播(broadcast) message的publisher

roscd beginner_tutorials
mkdir scripts
cd scripts
wget https://raw.github.com/ros/ros_tutorials/indigo-devel/rospy_tutorials/001_talker_listener/talker.py
chmod +x talker.py

或是也可以直接將以下這段code貼上

1 #!/usr/bin/env python
2 # license removed for brevity
3 import rospy
4 from std_msgs.msg import String
5 
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()
15 
16 if __name__ == '__main__':
17     try:
18         talker()
19     except rospy.ROSInterruptException:
20         pass

接下來逐步解釋

1 #!/usr/bin/env python

在ROS中, 所有以python寫成的node都必須在第一行宣告這一行, 確保script是以python來執行

3 import rospy
4 from std_msgs.msg import String

3.寫python ROS node時需要import rospy 4.此為publish資料時所指定的資料類型

7     pub = rospy.Publisher('chatter', String, queue_size=10)
8     rospy.init_node('talker', anonymous=True)

7.node會publish類型為String的資料到'chatter' topic, 並且queue_size=10來避免任意的subscriber來不及接收訊息 8.初始化名稱為talker的node, anonymous=True表示可以執行多個這種node, 系統會自動給這些皆為talker的node另一個unique的名稱, 在未執行這行前, node無法與ROS master溝通, 也就無法與其他node溝通, 注意node名只能為base name, 即不能夠有'/talker'這種名稱

9     rate = rospy.Rate(10) # 10hz

9.創造Rate object rate, 其會有一個function為sleep, 用以讓迴圈以固定的頻率執行, 在此即為每秒鐘會運行10次loop, 下面會看到如何使用

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()

10.檢查node是否關閉(ctrl-c, 關閉視窗等) 12.rospy.loginfo做三件事:i.將訊息印到螢幕, ii. 將訊息寫到node的log file, iii. 將訊息寫到rosout中(就可以在rqt_console看到它, 方便debug) 13.在pub這個物件中, hello_str為要publish的message, message會再經過String的轉換如:String(data=hello_str) 14.如前一段所敘述, 跟9.做搭配使用

17     try:
18         talker()
19     except rospy.ROSInterruptException:
20         pass

rospy.ROSInterruptException可以被rospy.sleep()和rospy.Rate.sleep()丟出, 而丟出的條件即為按下ctrl+c或關閉視窗等

9.2 撰寫Subsriber node

可以複製檔案或是直接複製code

roscd beginner_tutorials/scripts/
wget https://raw.github.com/ros/ros_tutorials/intido-devel/rospy_tutorials/001_talker_listener/listener.py
chmod +x listener.py

code如下

1 #!/usr/bin/env python
2 import rospy
3 from std_msgs.msg import String
4 
5 def callback(data):
6     rospy.loginfo(rospy.get_caller_id() + "I heard %s", data.data)
7     
8 def listener():
9 
10     # In ROS, nodes are uniquely named. If two nodes with the same
11     # node 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)
16 
17     rospy.Subscriber("chatter", String, callback)
18 
19     # spin() simply keeps python from exiting until this node is stopped
20     rospy.spin()
21 
22 if __name__ == '__main__':
23     listener()

以下逐步解釋code, 與publisher重複的就略過不提

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

當接收到data時, 就以loginfo來處理

17     rospy.Subscriber("chatter", String, callback)
20     rospy.spin()

17.從'chatter' topic接收type為String的message, 如果接到就將其作為參數丟給callback 20.直到我們關閉node前, 避免python將node(script)結束掉

9.3 即使是script, 你還是最好build一下

官網說:

We use CMake as our build system and, yes, you have to use it even for Python nodes. This is to make sure that the autogenerated Python code for messages and services is created.

不過我仍舊不太懂, 只有改script應該不影響message和service的生成?

# 在你的catkin_ws下
catkin_make

9.4 testing publisher/subscriber

roscore # terminal A
source your_catkin_ws/devel/setup.bash
rosrun beginner_tutorials talker.py # terminal B
rosrun beginner_tutorials listener.py # terminal C

觀察一下terminal B/C的輸出

results matching ""

    No results matching ""