2.1 創建 ROS 功能包
ROS(Robot Operating System)是一種開源的機器人軟件框架,廣泛用於機器人開發中。通過使用 ROS,開發者可以輕鬆創建和管理機器人應用程序。在本節中,我們將介紹如何創建一個 ROS 功能包並實現一些基本功能。
2.1.1 使用 ROS 主題
ROS 主題(Topic)是一種發佈/訂閲機制,允許節點之間進行通信。每個節點可以發佈主題消息或訂閲主題消息來獲取數據。以下是如何使用 ROS 主題的步驟:
創建功能包
首先,我們需要創建一個新的 ROS 功能包。在終端中運行以下命令:
catkin_create_pkg de_ws my_robot rospy roscpp
此命令創建一個名為 my_robot 的功能包,並聲明瞭對 std_msgs、rospy 和 roscpp 的依賴。
創建發佈者節點
接下來,我們在功能包中創建一個發佈者節點。新建一個名為 talker.py 的文件,並添加以下內容:
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
此代碼定義了一個發佈者節點 talker,它每秒鐘發佈一條 "hello world" 消息到主題 chatter。
2.1.2 創建 ROS 節點
ROS 節點是 ROS 系統中的基本執行單元。每個節點可以執行一個任務,如傳感器數據處理、運動控制等。下面我們創建一個訂閲者節點來接收 talker 節點發布的消息。
創建訂閲者節點
新建一個名為 listener.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()
此代碼定義了一個訂閲者節點 listener,它接收主題 chatter 上的消息並打印出來。
2.1.3 編譯節點
在我們運行節點之前,需要編譯功能包。確保在功能包的 CMakeLists.txt 和 package.xml 文件中正確配置了依賴項。然後在終端中運行以下命令:
cd ~/catkin_ws
catkin_make
編譯完成後,可以運行節點:
roscore
rosrun my_robot talker.py
rosrun my_robot listener.py
此時,你應該可以看到 listener 節點打印出 talker 節點發布的消息。
添加自定義的 .msg 文件和 .srv 文件
在 ROS 中,自定義消息類型和服務類型是很常見的需求。我們可以定義自己的消息和服務文件來滿足特定的應用需求。
創建自定義 .msg 文件
首先,在 my_robot 功能包的 msg 目錄下創建一個新的消息文件,例如 CustomMessage.msg:
string content
int32 number
然後,在 CMakeLists.txt 文件中添加以下內容:
add_message_files(
FILES
CustomMessage.msg
)
在 package.xml 文件中添加依賴:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
最後,重新編譯功能包:
catkin_make
創建自定義 .srv 文件
類似地,我們可以在 srv 目錄下創建一個新的服務文件,例如 CustomService.srv:
string request
---
string response
然後,在 CMakeLists.txt 文件中添加以下內容:
add_service_files(
FILES
CustomService.srv
)
在 package.xml 文件中添加依賴:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
重新編譯功能包:
catkin_make
2.3 使用 ROS 服務
ROS 服務是一種請求/響應機制,允許節點之間進行同步通信。
2.3.1 使用 ROS actionlib
actionlib 是 ROS 中用於處理長時間運行任務的庫。它提供了一種客户端-服務器架構,允許客户端請求服務器執行某些任務,並在任務完成時收到通知。
創建動作服務器
在 my_robot 功能包中創建一個新的 Python 文件 action_server.py:
#!/usr/bin/env python
import rospy
import actionlib
from my_robot.msg import CustomAction, CustomActionFeedback, CustomActionResult
class CustomActionServer(object):
_feedback = CustomActionFeedback()
_result = CustomActionResult()
def __init__(self):
self._as = actionlib.SimpleActionServer("custom_action", CustomAction, self.execute_cb, False)
self._as.start()
def execute_cb(self, goal):
rospy.loginfo('Executing goal: %s', goal)
success = True
for i in range(1, goal.order):
if self._as.is_preempt_requested():
rospy.loginfo('Goal preempted')
self._as.set_preempted()
success = False
break
self._feedback.sequence = i
self._as.publish_feedback(self._feedback)
rospy.sleep(1.0)
if success:
self._result.sequence = goal.order
self._as.set_succeeded(self._result)
if __name__ == '__main__':
rospy.init_node('custom_action_server')
server = CustomActionServer()
rospy.spin()
創建動作客户端
在 my_robot 功能包中創建一個新的 Python 文件 action_client.py:
#!/usr/bin/env python
import rospy
import actionlib
from my_robot.msg import CustomAction, CustomActionGoal
def feedback_cb(feedback):
rospy.loginfo('Feedback: %s', feedback)
if __name__ == '__main__':
rospy.init_node('custom_action_client')
client = actionlib.SimpleActionClient('custom_action', CustomAction)
client.wait_for_server()
goal = CustomActionGoal()
goal.order = 10
client.send_goal(goal, feedback_cb=feedback_cb)
client.wait_for_result()
rospy.loginfo('Result: %s', client.get_result())
2.3.2 編譯 ROS 動作服務器和客户端
在編譯功能包之前,確保在 CMakeLists.txt 和 package.xml 中添加了對 actionlib 和自定義消息的依賴。
然後在終端中運行以下命令:
catkin_make
啓動動作服務器和客户端:
rosrun my_robot action_server.py
rosrun my_robot action_client.py
2.4 創建啓動文件
啓動文件用於同時啓動多個 ROS 節點,簡化了複雜系統的啓動過程。
創建一個新的啓動文件 my_robot.launch:
<launch>
<node pkg="my_robot" type="talker.py" name="talker" output="screen"/>
<node pkg="my_robot" type="listener.py" name="listener" output="screen"/>
</launch>
運行啓動文件:
roslaunch my_robot my_robot.launch
2.5 主題、服務和 actionlib 的應用
在實際應用中,主題、服務和 actionlib 可以結合使用,實現複雜的機器人行為。例如,一個機器人可以通過主題獲取傳感器數據,通過服務進行路徑規劃,通過 actionlib 執行長時間的導航任務。
以下是一個綜合應用示例:
- 主題用於發佈傳感器數據。
- 服務用於路徑規劃。
- actionlib 用於執行導航任務。
2.6 總結
本文介紹瞭如何創建 ROS 功能包,並使用主題、服務和 actionlib 實現機器人功能。通過這些基礎知識,您可以構建複雜的機器人應用程序。
2.7 問題
在學習和使用 ROS 的過程中,可能會遇到以下問題:
- 功能包無法編譯:檢查依賴是否正確添加。
- 節點無法通信:確保主題和服務名稱一致。
- 動作服務器和客户端無法連接:檢查 actionlib 配置是否正確。