ros机器人之动作(二)
前面我们实现了动作的定义,接下来实现动作的功能
实现一个基本的动作服务器
准备好所需的动作定义后就可以开始编写代码了。动作和话题一样,都是使用回调机制,即回调函数会在收到消息时被唤醒和调用。
例: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机器人之动作(二)的更多相关文章
- ROS机器人之动作(一)
前面我们探讨了ros的两种通信方式,话题和服务,服务机制常用于同步的请求/响应交互方式. 话题则是单工通信,尤其是接收方有多时(比如传感器数据流),然而,当需要完成的任务比较复杂时, 服务和话题都不是 ...
- ROS机器人程序设计(原书第2版)补充资料 教学大纲
ROS机器人程序设计(原书第2版) 补充资料 教学大纲 针对该书稍后会补充教学大纲.教案.多媒体课件以及练习题等. <ROS机器人程序设计>课程简介 课程编号:XXXXXX 课程名称:RO ...
- ROSCon 2016视频和幻灯片发布 ROS机器人操作系统重要参考资料
ROSCon 2016视频和幻灯片发布 By Tully Foote on 十月19,2016 7:28 AM 全部PPT下载地址:http://pan.baidu.com/s/1gf2sn2F RO ...
- ROS机器人星火计划公开课总结
非常荣幸参加了两次星火计划公开课(上海站), 感谢NXROBO.EXBOT以及所有支持ROS机器人星火计划的小伙伴们. ----废话开始,与课程总结无关,可跳过---- 在国内20多年的求学生涯以及2 ...
- ROS入门笔记(二):ROS安装与环境配置及卸载(重点)
ROS入门笔记(二):ROS安装与环境配置及卸载(重点) [TOC] 1 ROS安装步骤 1.1 ROS版本 ROS目前只支持在Linux系统上安装部署, 它的首选开发平台是Ubuntu. 发布时间 ...
- ROS 机器人技术 - 广播与接收 TF 坐标
上次我们学习了 TF 的基本概念和如何发布静态的 TF 坐标: ROS 机器人技术 - TF 坐标系统基本概念 ROS 机器人技术 - 静态 TF 坐标帧 这次来总结下如何发布一个自定义的 TF 坐标 ...
- ros机器人开发概述
1. ROS项目开发流程? 参照古月大神写的ROS探索总结系列:http://blog.exbot.net/archives/619 具体项目设计可看看<程序员>杂志的最新一篇 ...
- Learning ROS for Robotics Programming - Second Edition(《学习ROS机器人编程-第二版》)
Learning ROS for Robotics Programming - Second Edition <学习ROS机器人编程-第二版> ----Your one-stop guid ...
- ROS机器人程序设计-学习小结-
ROS官网 |易科 |虞坤林 |古月居 |ROSClub 学习ROS相关书籍推荐:http://blog.csdn.net/zhangrelay/article/details/52244746 RO ...
随机推荐
- .NET 半天搭建Jenkins持续集成与自动化部署系统
前言 相信每一位程序员都经历过深夜加班上线的痛苦!而作为一个加班上线如家常便饭的码农,更是深感其痛.由于我们所做的系统业务复杂,系统庞大,设计到多个系统之间的合作,而核心系统更是采用分布式系统架构,由 ...
- $HDOJ5542\ The\ Battle\ of\ Chibi$ 数据结构优化$DP$
$AcWing$ $Description$ $Sol$ 首先显然是是以严格递增子序列的长度为阶段,由于要单调递增,所以还要记录最后一位的数值 $F[i][j]$表示前$i$个数中以$A_i$结尾的长 ...
- Python 中 unittest 单元测试框架中需要知识点
现在正在使用 unittest 框架,我们来记录下这个框架的知识点: unittest 框架:我们在写接口用例的时候,会继承 unittest 当中的 TestCase 的类和方法,私有方法除外,来识 ...
- 从0开发3D引擎(二):准备预备知识
大家好,本文介绍了开发3D引擎需要的预备知识,给出了相关的资源. 上一篇博文 从0开发3D引擎(一):开篇 了解Web 3D Web 3D的历史 目前Web 3D是基于WebGL这个Web端3D AP ...
- 组件与props简解
一.创建组件 1.函数式创建 特点: 组件不能访问this对象 组件无法访问生命周期的方法 无状态组件只能访问输入的props,无副作用 function Title() { return <h ...
- JWT实现授权认证
目录 一. JWT是什么 二. JWT标准规范 三. 核心代码简析 四. 登录授权示例 五. JWT 使用方式 六. JWT注意事项 一. JWT是什么 JSON Web Token(JWT)是目前最 ...
- IOS系统唤醒微信内置地图
针对前一篇文章 唤醒微信内置地图 后来发现在IOS系统中运行 唤醒地图会无效的问题.因为在IOS上无法解析这俩个字符串的问题! 需要对经纬度 使用 “parseFloat()”进行转换 返回一个浮点数 ...
- Oracle数据库设计省市区小区数据库建表
省CREATE TABLE "SF_JECF_BASE"."SF_PROVINCE" ( "id" VARCHAR2(64 BYTE) NO ...
- 编写SQL查询范围分区类型,MAX分区范围
需求 对于分区表,对于范围分区类型来说,查询MAX分区及对应的分区范围. ==查询分区表对应的最大分区信息 ==排除了自扩展分区(如果是自扩展分区,但是最大的分区不是自扩展的并未排除在外) ==排除了 ...
- python继承简介
继承 是面向对象的三大特性之一 作用: 通过继承可以使一个类获取其它类中的属性和方法 使用方法: 在定义类时,可以在类名后的括号中指定当前类的父类(超类.基类.super) 这样子类(衍生类)就可以直 ...