一、概述
ROS是机器人操作系统,是一个开源的、灵活的、分布式的软件平台,可以帮助我们快速开发机器人应用程序。ROS中的通信是机器人应用程序开发中最重要的部分之一,它是实现多模块协作和互联的关键。ROS提供了多种通信方式来支持不同类型的应用场景,包括如下:
- Publisher/Subscriber方式:发布者和订阅者模式,用于实时传输数据。
- Service/Client方式:客户端和服务端模式,用于请求和响应一个计算任务。
- Action Server/Action Client方式: 提供了对连续和异步处理的支持。
二、Publisher/Subscriber方式
Publisher/Subscriber(发布者和订阅者)方式是ROS中最常用的通信方式,它是基于消息传递的。通过这种方式,我们可以在一个节点中发布消息,而在其他节点中订阅这个消息。它的原理类似于生产者-消费者模型,其中Publisher(发布者)是生产者,而Subscriber(订阅者)是消费者。
下面是Python代码示例
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def callback(data):
rospy.loginfo("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”的消息。回调函数callback()是Subscriber()从ROS Master获取到信息后需要执行的任务。在此示例中,Subscriber将从话题“chatter”读取消息,并在终端窗口中打印它。
三、Service/Client方式
Service/Client(服务端和客户端)方式是RPC(Remote Procedure Call)风格的模式,可以像调用本地函数一样调用远程计算机上的函数。其中,Service Server提供一个服务,而Service Client向Service Server发送请求。一旦Service Server收到请求,它将计算请求并将结果发送回Service Client。
下面是Python代码示例:
#!/usr/bin/env python
from beginner_tutorials.srv import AddTwoInts,AddTwoIntsResponse
import rospy
def handle_add_two_ints(req):
result = req.a + req.b
rospy.loginfo("Returning [%s + %s = %s]", req.a, req.b, result)
return AddTwoIntsResponse(result)
def add_two_ints_server():
rospy.init_node('add_two_ints_server')
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
rospy.loginfo("Ready to add two ints.")
rospy.spin()
if __name__ == "__main__":
add_two_ints_server()
在此示例中,代码定义了一个名为“add_two_ints”的服务。handle_add_two_ints()函数是处理“AddTwoInts”服务请求的回调函数,它将两个整数相加并返回结果。add_two_ints_server()函数初始化ROS节点并创建一个服务,当它收到请求时,它调用handle_add_two_ints()函数处理请求,并将其响应返回给Service Client。
四、Action Server/Action Client方式
Action Server/Action Client方式提供了对连续和异步处理的支持。在ROS中,Action是一个新的消息类型,相对于ROS中的其他消息类型来说,它保留了更多的信息,比如跟踪Action调用的进度等。Action Server等待Action Client发送请求,一旦收到请求,就可以在内部执行类似于后台进程的操作。
下面是Python代码示例:
#!/usr/bin/env python
import rospy
import actionlib
from beginner_tutorials.msg import FibonacciAction, FibonacciGoal, FibonacciResult
class FibonacciActionServer(object):
_feedback = FibonacciFeedback()
_result = FibonacciResult()
def __init__(self):
self._as = actionlib.SimpleActionServer("fibonacci", FibonacciAction, self.goal_callback, False)
self._as.start()
def fibonacci(self, n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return self.fibonacci(n-1) + self.fibonacci(n-2)
def goal_callback(self, goal):
r = rospy.Rate(1)
success = True
for i in range(1, goal.order+1):
if self._as.is_preempt_requested():
rospy.loginfo('Goal was Preempted')
self._as.set_preempted()
success = False
break
self._feedback.sequence.append(self.fibonacci(i))
self._as.publish_feedback(self._feedback)
r.sleep()
if success:
self._result.sequence = self._feedback.sequence
rospy.loginfo('Goal was successfully completed')
self._as.set_succeeded(self._result)
if __name__ == '__main__':
rospy.init_node('fibonacci_action_server')
server = FibonacciActionServer()
rospy.spin()
在此示例中,代码定义了一个名为“fibonacci”的Action。FibonacciActionServer()类是Action Server,它等待Action Client发送请求。goal_callback()函数是执行操作的回调函数。在这里,它通过计算斐波那契数列来演示操作的执行。在此过程中,它将生成的数据(响应)发送给Action Client。如果Action Client的请求被取消,它将发布Preempted(已取消)状态,如果操作成功完成,它将发布Succeeded(成功)状态,并带上最终响应。