(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

使用Execute Callback (Python)编写一个简单的行为服务器

Description: 本教程涵盖了使用simple_action_server库来创建一个Fibonacci行为服务器,以Python的形式。这个行为服务器示例会生成一个Fibonacci序列、目标序列、完成反馈序列和最终结果序列。

Tutorial Level: BEGINNER

Next Tutorial: 编写一个行为客户端(Python)

创建行为消息

查看C++ 版本教程 然后当你已经完成创建消息后返回。

编写行为服务器

在本教程中使用到的代码和示例可以在actionlib_tutorials包中找到。你也许应该在开始本教程之前阅读actionlib包。

代码

以下的代码可以在actionlib_tutorials/simple_action_servers/fibonacci_server.py中找到,并且实现了一个python形式的行为服务器用于 fibonacci行为.

   1 #! /usr/bin/env python
   2 
   3 import rospy
   4 
   5 import actionlib
   6 
   7 import actionlib_tutorials.msg
   8 
   9 class FibonacciAction(object):
  10     #创建用于发布反馈(feedback)/结果(result)的消息
  11     _feedback = actionlib_tutorials.msg.FibonacciFeedback()
  12     _result = actionlib_tutorials.msg.FibonacciResult()
  13 
  14     def __init__(self, name):
  15         self._action_name = name
  16         self._as = actionlib.SimpleActionServer(self._action_name, actionlib_tutorials.msg.FibonacciAction, execute_cb=self.execute_cb, auto_start = False)
  17         self._as.start()
  18       
  19     def execute_cb(self, goal):
  20         # helper variables
  21         r = rospy.Rate(1)
  22         success = True
  23         
  24         # 附加种子用于fibonacci序列
  25         self._feedback.sequence = []
  26         self._feedback.sequence.append(0)
  27         self._feedback.sequence.append(1)
  28         
  29         # 发布信息到控制台,用于用户查看
  30         rospy.loginfo('%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i' % (self._action_name, goal.order, self._feedback.sequence[0], self._feedback.sequence[1]))
  31         
  32         # 开始运行行为
  33         for i in range(1, goal.order):
  34             # check that preempt has not been requested by the client
  35             if self._as.is_preempt_requested():
  36                 rospy.loginfo('%s: Preempted' % self._action_name)
  37                 self._as.set_preempted()
  38                 success = False
  39                 break
  40             self._feedback.sequence.append(self._feedback.sequence[i] + self._feedback.sequence[i-1])
  41             # 发布反馈(feedback)
  42             self._as.publish_feedback(self._feedback)
  43             # 这个步骤不是必要的,用于演示效果所以序列会以1Hz完成。
  44             r.sleep()
  45           
  46         if success:
  47             self._result.sequence = self._feedback.sequence
  48             rospy.loginfo('%s: Succeeded' % self._action_name)
  49             self._as.set_succeeded(self._result)
  50         
  51 if __name__ == '__main__':
  52     rospy.init_node('fibonacci')
  53     server = FibonacciAction(rospy.get_name())
  54     rospy.spin()

代码解释

   6 import actionlib

这一行会加载actionlib库用于实现简单行为。

   7 import actionlib_tutorials.msg

指定的行为生成几个消息用于目标、接收反馈等等。这一行加载生成的消息

  17         self._as = actionlib.SimpleActionServer(self._action_name, actionlib_tutorials.msg.FibonacciAction, execute_cb=self.execute_cb, auto_start = False)
  18         self._as.start()

在这里,创建SimpleActionServer,我们传递一个名字(用于作为一个命名空间namespace)、一个行为类型和可选项运行回调。由于我们在这个示例中指定一个运行回调,因此会为我们循环一个线程,该线程允许我们当一个新目标进来时,会以一个回调(callback)形式接收来运行行为。

注意你应当总是显示的设置auto_startFalse,除非你知道你在做什么(参考)。

  20     def execute_cb(self, goal):

这是一个运行回调函数,不管什么时候,只有一个新目标接收到的时候会运行。

  22         r = rospy.Rate(1)
  23         success = True
  24         
  25         # 附加种子用于fibonacci序列
  26         self._feedback.sequence = []
  27         self._feedback.sequence.append(0)
  28         self._feedback.sequence.append(1)
  29         
  30         # 发布信息到控制台,用于用户查看
  31         rospy.loginfo('%s: Executing, creating fibonacci sequence of order %i with seeds %i, %i' % (self._action_name, goal.order, self._feedback.sequence[0], self._feedback.sequence[1]))

在这里,创建内置行为。在本示例中发布的rospy.loginfo来让用户知道行为处于运行状态。

  33         # 开始运行行为
  34         for i in range(1, goal.order):
  35             # check that preempt has not been requested by the client
  36             if self._as.is_preempt_requested():
  37                 rospy.loginfo('%s: Preempted' % self._action_name)
  38                 self._as.set_preempted()
  39                 success = False

一个行为服务器的重要组件是有能力允许一个行为客户端的请求,该请求是目标可以被取消。当一个客户端请求当前目标被抢占时,行为服务器应该取消目标,运行任何必要的清理工作,随后调用set_preempted函数,该函数触发一个行为被用户请求抢占的信号。在这里,我们将每一秒进行检查是否被抢占。另外,当接收到一个抢占请求时,我们应该接收一个回调。

  41             self._feedback.sequence.append(self._feedback.sequence[i] + self._feedback.sequence[i-1])
  42             # 发布反馈(feedback)
  43             self._as.publish_feedback(self._feedback)

在这里,Fibonacci序列指定反馈变量,随后在提供的反馈通道中通过行为服务器发布。之后,行为继续循环和发布反馈。

  47         if success:
  48             self._result.sequence = self._feedback.sequence
  49             rospy.loginfo('%s: Succeeded' % self._action_name)
  50             self._as.set_succeeded(self._result)

一旦行为结束Fibonacci序列处理,行为服务器通过调用set_succeeded来通知行为客户端行为目标完成。

  52 if __name__ == '__main__':
  53     rospy.init_node('fibonacci')
  54     server = FibonacciAction(rospy.get_name())
  55     rospy.spin()

最后,main函数,创建行为服务器并且循环节点。

编译

只有初始化的时候,即你创建教程包的时候,你需要编译生成shell配置文件。

cd %TOPDIR_YOUR_CATKIN_WORKSPACE%
catkin_make
source devel/setup.bash

运行行为服务器

运行:

roscore

然后在一个新终端上,用以下命令来运行行为服务器。

rosrun actionlib_tutorials fibonacci_server.py

Wiki: cn/actionlib_tutorials/Tutorials/Writing a Simple Action Server using the Execute Callback (Python) (last edited 2018-07-05 00:22:05 by Playfish)