前面我们实现了动作的定义,接下来实现动作的功能

实现一个基本的动作服务器

准备好所需的动作定义后就可以开始编写代码了。动作和话题一样,都是使用回调机制,即回调函数会在收到消息时被唤醒和调用。

例:simple_action_server.py

 #!/usr/bin/env python
import rospy import time #导入时间time标准库
import actionlib            #导入actionlib包来提供将要使用的SimpleActionServer
from basic.msg import TimerAction,TimerGoal,TimerResult #导入一些从Timer.action中自动生成的消息类 def do_timer(goal):             #定义一个函数,对收到的目标进行了处理,传入函数do_timer()的参数goal是TimerGoal类型
start_time=time.time()
time.sleep(goal.time_to_wait.to_sec())    
result=TimerResult()            #构造结果消息,对应的类型为TimerResult
result.time_elapsed=rospy.Duration.from_sec(time.time()-start_time)
result.updates_sent=
server.set_succeeded(result) #以结果作为参数调用set_succeeded() rospy.init_node('time_action_server')
17 server=actionlib.SimpleActionServer('timer',TimerAction,do_timer,False)#构造函数(第一个参数为动作服务器的名称,第二个参数为动作服务器的类型,第三个参数目标的回调函数,最后通过传递False参数来关闭动作服务器的自动启动
18 server.start()
19 rospy.spin()

完成动作服务器的编写,需要检查其工作是否正常,启动roscore ,然后运行动作服务器

qqtsj@qqtsj-Nitro-AN515-:~/catkin_ws$ rosrun basic simple_action_server.py 

查看相应的话题

qqtsj@qqtsj-Nitro-AN515-:~/catkin_ws/src/basic/actionnode$ rostopic list/rosout
/rosout_agg
/timer/cancel
/timer/feedback
/timer/goal
/timer/result
/timer/status

动作的使用

为了便利起见,我们直接使用actionlib包中的SimpleActionClient作为客服端

例:simple_action_client.py

  #!/usr/bin/env python 

  import rospy
import actionlib
from basic.msg import TimerAction ,TimerGoal,TimerResult rospy.init_node('timer_action_client')
client=actionlib.SimpleActionClient('timer',TimerAction) #创建一个SimpleActionClient,构造函数的第一个参数为动作客户端的名称,名称必须与我们之前创建的服务器相匹配,第二个参数为动作的类型,也要与服务器相匹配。
client.wait_for_server()    #等待服务器启动
goal=TimerGoal()         #创建目标,构建一个TimerGoal对象,并填入我们希望定时器等待的时间(5.0)
goal.time_to_wait=rospy.Duration.from_sec(5.0)   
client.send_goal(goal)
client.wait_for_result()
print('Time elspsed:%f'% (client.get_result().time_elapsed.to_sec()))
#最后就是等待服务器的结果,如果一切正常的话,我们应该会在此处阻塞5s,结果到来后,就可以用来get_result来获得它并打印服务器汇报的time_elapsed信息。

同样,也需要对客服端进行检查,确保roscore和动作服务器均启动,然后运行客户端:

qqtsj@qqtsj-Nitro-AN515-:~/catkin_ws/src/basic/actionnode$ rosrun basic simple_action_client.py
Time elspsed:5.006946

在启动客户端和打印结果信息之间,应该出现约5s的延迟。而结果中的time_elapsed则会比5秒稍微长一些,因为time_sleep()的阻塞时间往往比请求时间长。

实现一个更复杂的的动作服务器

动作和服务看起来非常的相似,只是在配置上多了一些步骤,动作和服务的主要区别在于动作的异步特性,复杂的动作可以实现终止目标,处理打断请求和实时反馈功能。

例:fany_action_Server.py

  #!/usr/bin/env python
import time
import rospy
import actionlib
from basic.msg import TimerAction ,TimerGoal,TimerResult,TimerFeedback #增加量对TimerFeedback消息类型的导入 def do_timer(goal):
start_time=time.time()
update_count=0       #增加一个变量,用于统计总共发布了多少反馈消息 if goal.time_to_wait.to_sec()>60.0:
result=TimerResult()
result.time_elapsed=rospy.Duration.from_sec(time.time()-start_t ime)
result.updates_sent=update_count
server.set_aborted(result,"Timer aborted due to too-long wait")
return
while (time.time()-start_time)<goal.time_to_wait.to_sec(): if server.is_preempt_requested(): #检查是否发生终端,如果发生中断(即客户端在前一个动作还在执行时,发送了新的目标),函数会返回Ture,此时就需要补充一个result,同时提供一个表示状态的字符串,然后调用set_preempted
reslut=TimerResult()
result.time_elapsed=\
rospy.Duration.from_sec(time.time()-start.time)
result.updates_sent=update_count
server.set_preempted(result,"Timer preempted")
return feedback=TimerFeedback()
feedback.time_elapsed=rospy.Duration.from_sec(time.time()-start _time)
feedback.time_remaining=goal.time_to_wait-feedback.time_elapsed
server.publish_feedback(feedback)     #把反馈发送给客户端
update_count+=1           #增加1表示进行了一次反馈 time.sleep(1.0)
result=TimerResult()
result.time_elapsed=rospy.Duration.from_sec(time.time()-start_time)
result.updates_sent=update_count
server.set_succeeded(result,"timer completed successfully")
rospy.init_node('time_action_server')
server=actionlib.SimpleActionServer('timer' ,TimerAction ,do_timer ,Fal se)
server.start()
rospy.spin()

使用更复杂的动作

这个客户端以测试服务端功能,对反馈进行处理,打断正在执行的目标,以及引发一个终止。

例:fancy_action_client.py

  #!/usr/bin/env python
import rospy
import time
import actionlib
from basic.msg import TimerAction,TimerGoal,TimerResult,TimerFeedback def feedback_cb(feedback): #定义一个回调函数feedback_cb(),当收到反馈消息时会被执行。
print('[Feedback] Time elapsed:%f' %(feedback.time_elapsed.to_sec() ))
print('[Feedback] Time remaining: %f'%(feedback.time_remaining.to_s ec())) rospy.init_node('timer_action_client')
client=actionlib.SimpleActionClient('timer',TimerAction)
client.wait_for_server()
goal=TimerGoal()
goal.time_to_wait=rospy.Duration.from_sec(5.0)
#Uncomment this line to test server-side abort:
#goal.time_to_wait=rospy.Duration.from_sec(500.0)
client.send_goal(goal, feedback_cb=feedback_cb)    #将回调函数作为feedback_cb关键词的参数 #Uncomment these lines to test goal preemption:
#time.sleep(3.0)
#client.cancel_goal() client.wait_for_result()
print('[Result] State: %d' %(client.get_state()))
print('[Result] State: %s' %(client.get_goal_status_text()))
print('[Result] Time elapse: %f'%(client.get_result().time_elapsed.to_s ec()))
print('[Result] Updates sent: %d'%(client.get_result().updates_sent))
~

跟以前一样,先启动roscore,然后运行server,在运行客服端client,结果如下

qqtsj@qqtsj-Nitro-AN515-:~/catkin_ws/src/basic/actionnode$ rosrun basic fancy_action_client.py
[Feedback] Time elapsed:0.000043
[Feedback] Time remaining: 4.999957
[Feedback] Time elapsed:1.001889
[Feedback] Time remaining: 3.998111
[Feedback] Time elapsed:2.003785
[Feedback] Time remaining: 2.996215
[Feedback] Time elapsed:3.005333
[Feedback] Time remaining: 1.994667
[Feedback] Time elapsed:4.007131
[Feedback] Time remaining: 0.992869
[Result] State:
[Result] State: timer completed successfully
[Result] Time elapse: 5.007945
[Result] Updates sent:

所有节点都如期运行起来了

现在来引发一个服务端的主动终止,将等待时间从5s改为500s

再次运行客户端

qqtsj@qqtsj-Nitro-AN515-:~/catkin_ws/src/basic/actionnode$ rosrun basic fancy_action_client.py
[Result] State:
[Result] State: Timer aborted due to too-long wait
[Result] Time elapse: 0.000139
[Result] Updates sent:

服务端立即主动终止了目标的执行

小结

本章探讨了ros的动作机制,它是ros中一个功能强大,使用广泛的通信工具,与服务类似,动作允许你发起一个请求(即目标),同时接受一个响应(即结果),不过,动作提供了更多的控制形式,

服务端可以在执行过程中提供反馈,客户端也可以取消之前发出的目标。

话题,服务,动作机制的对比

类型          最佳使用场景

话题       单工通信,尤其是接收方多个时(如传感器数据流)

服务       简单的请/响应式交互场景,如询问节点的当前状态

动作       大部分请求/响应式交互场景,尤其是执行过程不能立即完成时(如导航前往一个目标点)

ros机器人之动作(二)的更多相关文章

  1. ROS机器人之动作(一)

    前面我们探讨了ros的两种通信方式,话题和服务,服务机制常用于同步的请求/响应交互方式. 话题则是单工通信,尤其是接收方有多时(比如传感器数据流),然而,当需要完成的任务比较复杂时, 服务和话题都不是 ...

  2. ROS机器人程序设计(原书第2版)补充资料 教学大纲

    ROS机器人程序设计(原书第2版) 补充资料 教学大纲 针对该书稍后会补充教学大纲.教案.多媒体课件以及练习题等. <ROS机器人程序设计>课程简介 课程编号:XXXXXX 课程名称:RO ...

  3. ROSCon 2016视频和幻灯片发布 ROS机器人操作系统重要参考资料

    ROSCon 2016视频和幻灯片发布 By Tully Foote on 十月19,2016 7:28 AM 全部PPT下载地址:http://pan.baidu.com/s/1gf2sn2F RO ...

  4. ROS机器人星火计划公开课总结

    非常荣幸参加了两次星火计划公开课(上海站), 感谢NXROBO.EXBOT以及所有支持ROS机器人星火计划的小伙伴们. ----废话开始,与课程总结无关,可跳过---- 在国内20多年的求学生涯以及2 ...

  5. ROS入门笔记(二):ROS安装与环境配置及卸载(重点)

    ROS入门笔记(二):ROS安装与环境配置及卸载(重点) [TOC] 1 ROS安装步骤 1.1 ROS版本 ROS目前只支持在Linux系统上安装部署, 它的首选开发平台是Ubuntu. 发布时间 ...

  6. ROS 机器人技术 - 广播与接收 TF 坐标

    上次我们学习了 TF 的基本概念和如何发布静态的 TF 坐标: ROS 机器人技术 - TF 坐标系统基本概念 ROS 机器人技术 - 静态 TF 坐标帧 这次来总结下如何发布一个自定义的 TF 坐标 ...

  7. ros机器人开发概述

    1.       ROS项目开发流程? 参照古月大神写的ROS探索总结系列:http://blog.exbot.net/archives/619 具体项目设计可看看<程序员>杂志的最新一篇 ...

  8. Learning ROS for Robotics Programming - Second Edition(《学习ROS机器人编程-第二版》)

    Learning ROS for Robotics Programming - Second Edition <学习ROS机器人编程-第二版> ----Your one-stop guid ...

  9. ROS机器人程序设计-学习小结-

    ROS官网 |易科 |虞坤林 |古月居 |ROSClub 学习ROS相关书籍推荐:http://blog.csdn.net/zhangrelay/article/details/52244746 RO ...

随机推荐

  1. .NET 半天搭建Jenkins持续集成与自动化部署系统

    前言 相信每一位程序员都经历过深夜加班上线的痛苦!而作为一个加班上线如家常便饭的码农,更是深感其痛.由于我们所做的系统业务复杂,系统庞大,设计到多个系统之间的合作,而核心系统更是采用分布式系统架构,由 ...

  2. $HDOJ5542\ The\ Battle\ of\ Chibi$ 数据结构优化$DP$

    $AcWing$ $Description$ $Sol$ 首先显然是是以严格递增子序列的长度为阶段,由于要单调递增,所以还要记录最后一位的数值 $F[i][j]$表示前$i$个数中以$A_i$结尾的长 ...

  3. Python 中 unittest 单元测试框架中需要知识点

    现在正在使用 unittest 框架,我们来记录下这个框架的知识点: unittest 框架:我们在写接口用例的时候,会继承 unittest 当中的 TestCase 的类和方法,私有方法除外,来识 ...

  4. 从0开发3D引擎(二):准备预备知识

    大家好,本文介绍了开发3D引擎需要的预备知识,给出了相关的资源. 上一篇博文 从0开发3D引擎(一):开篇 了解Web 3D Web 3D的历史 目前Web 3D是基于WebGL这个Web端3D AP ...

  5. 组件与props简解

    一.创建组件 1.函数式创建 特点: 组件不能访问this对象 组件无法访问生命周期的方法 无状态组件只能访问输入的props,无副作用 function Title() { return <h ...

  6. JWT实现授权认证

    目录 一. JWT是什么 二. JWT标准规范 三. 核心代码简析 四. 登录授权示例 五. JWT 使用方式 六. JWT注意事项 一. JWT是什么 JSON Web Token(JWT)是目前最 ...

  7. IOS系统唤醒微信内置地图

    针对前一篇文章 唤醒微信内置地图 后来发现在IOS系统中运行 唤醒地图会无效的问题.因为在IOS上无法解析这俩个字符串的问题! 需要对经纬度 使用 “parseFloat()”进行转换 返回一个浮点数 ...

  8. Oracle数据库设计省市区小区数据库建表

    省CREATE TABLE "SF_JECF_BASE"."SF_PROVINCE" ( "id" VARCHAR2(64 BYTE) NO ...

  9. 编写SQL查询范围分区类型,MAX分区范围

    需求 对于分区表,对于范围分区类型来说,查询MAX分区及对应的分区范围. ==查询分区表对应的最大分区信息 ==排除了自扩展分区(如果是自扩展分区,但是最大的分区不是自扩展的并未排除在外) ==排除了 ...

  10. python继承简介

    继承 是面向对象的三大特性之一 作用: 通过继承可以使一个类获取其它类中的属性和方法 使用方法: 在定义类时,可以在类名后的括号中指定当前类的父类(超类.基类.super) 这样子类(衍生类)就可以直 ...