最近使用ROS进行任务(Task)执行,深切体会用传统的方法实现是极其繁杂的。比如人脸录入工作,包含人脸检测,识别,语音提示,运动控制,这些子部分基本都是通过订阅话题的回调函数中处理,之间的切换,如人脸识别,语音提示之间的切换,需要用信号量进行控制切换,当多数据融合的时候,逻辑是极其的混乱的,也容易导致冗余代码,后期的维护也是不易于维护的。深切体会到一个好的实现框架有多么的重要。正如自己的体会,PR2开发中,发现如果不用一套完整的框架去执行任务,会导致代码的维护特别的繁杂,所以大佬们才开发这套smach状态机功能包。而状态机的思想也正符合机器人的这种多数据融合,多子任务执行的问题。状态机的优点是:实现简单,易于维护,重构任务顺序容易。最近的实现证明,smach正是为任务执行量身定做的。经检索也发现,国内介绍关于smach状态机的介绍和比较少,从这篇开始,我们将连续的介绍在ROS-Indigo版本下的smach使用。

1、安装

  学习smach之前需要安装这个软件,安装smach有两种方式:

  a、使用apt-get直接安装(推荐),只需要执行如下代码:

$ sudo apt-get install ros-indigo-executive-smach

  b、使用源码安装,只需要在相应的工作空间的src下,通过git clone拉取下来,比如在catkin_ws/src的目录下执行如下代码:

$ git clone http://wiki.ros.org/smach/Tutorials

2、smach介绍

 smach[1]是ros中的一个实现有限状态机的开发包,在ROS任务执行中使用得比较多。一提到状态机,大家可能会想起图灵而望而生畏,别紧张,其实没那么的难。smach使用了python实现,所以要使用smach只能在python环境中使用,python使用起来很简单,如果有编程基础,看几个小时就可以上手,没编程基础的看几天也可以很容易上手。

  smach提供了actionlib整合和smach viewer两大组件。smach viewer可以实时地查看任务执行当前的状态节点位置,是调试开发的必备工具。smach还整合了动作状态,例如定点导航。可以把话题topic,服务service转化为状态,也可以把一个类转化为状态节点。smach可以实现状态的并发执行,任务的重复执行,层次嵌套复杂的状态机(状态机也可以作为一个状态)。

  学习smach需要有两个基础:状态机和python知识。

  a、状态机

  状态机就是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。参考资料[3],最简单的例子就是灯的开灯和关灯的例子。用开灯状态和关灯状态描述灯的状态,状态之间的转换,通过开灯动作和关灯的动作来完成,基于smach打实现如下:

#!/usr/bin/env python

import roslib; roslib.load_manifest('smach_sample_node')
import rospy
import smach
import smach_ros
import time
# define state Foo # define state Bar
class Open(smach.State):
def __init__(self):
smach.State.__init__(self, outcomes=['closed']) def execute(self, userdata):
rospy.loginfo('Opened')
time.sleep(2)
rospy.loginfo('Closeing')
return 'closed' #define state close light
class Close(smach.State):
def __init__(self):
smach.State.__init__(self, outcomes=['opened']) def execute(self, userdata):
rospy.loginfo('Closed')
time.sleep(2)
rospy.loginfo('Closing')
return 'opened' # main
def main():
rospy.init_node('smach_example_state_machine') # Create a SMACH state machine
sm_light = smach.StateMachine(outcomes=['stop', 'succee']) # Open the container
with sm_light:
# Add states to the container
smach.StateMachine.add('OPEN', Open(),
transitions={'closed':'CLOSE'})
smach.StateMachine.add('CLOSE', Close(),
transitions={'opened':'OPEN'}) # Execute SMACH plan
sis = smach_ros.IntrospectionServer('sm_light', sm_light, '/SM_ROOT')
sis.start()
# Execute SMACH plan
outcome = sm_light.execute() # Wait for ctrl-c to stop the application
rospy.spin()
sis.stop() if __name__ == '__main__':
main()

    输出结果:

[INFO] [WallTime: 1453689512.106141] Closed
[INFO] [WallTime: 1453689514.108995] Closing
[INFO] [WallTime: 1453689514.109447] State machine transitioning 'CLOSE':'opened'-->'OPEN'
[INFO] [WallTime: 1453689514.109942] Opened
[INFO] [WallTime: 1453689514.420038] Closeing
[INFO] [WallTime: 1453689514.420271] State machine transitioning 'OPEN':'closed'-->'CLOSE'

    相应的状态机实时状态,如下图所示:

    大家发现,基于smach实现状态机器是如此打简单,所以大胆打去弄熟它吧。

    下面贴出两张ros smach viewer生成的图,直观感受下状态机的魅力。

    简单有限状态机:

(来自:ros wiki)

    较为复杂的有限状态机:    

(来自ros wiki)

  b、python知识

   网上资源特别多,这里不展开介绍了。请参考[2]

参考资料:

[1]. http://wiki.ros.org/smach/Tutorials

[2]. Python菜鸟教程

[3]. 有限状态机

SMACH专题(一)----安装与初探的更多相关文章

  1. freeswitch编译安装,初探, 以及联合sipgateway, webrtc server的使用场景。

    本文主要记录freeswitch学习过程. 一 安装freeswitch NOTE 以下两种安装方式,再安装的过程中遇到了不少问题,印象比较深刻的就是lua库找到不到这个问题.这个问题发生在make ...

  2. bbed的使用--安装及初探

    bbed是oracle内部一款用来直接查看和修改数据文件数据的工具,可以直接修改Oracle数据文件块的内容,在一些特殊恢复场景下比较有用. 1.bbed 的安装 在9i/10g中连接生成bbed: ...

  3. SMACH专题(三)----几种State类型

    状态机提供了若干种状态,包括了Generic State,CBState,SimpleActionState (ROS),ServiceState (ROS),MonitorState (ROS).下 ...

  4. SMACH专题(四)----状态State类的实现和中文注释

    SMACH中,状态(State)是状态机器组成的重要部分,理解State的原理和实现,对使用SMACH很有帮助,特别是理解 __init__(),execute(),preempt是尤为关键. __i ...

  5. SMACH专题(二)----Concurrent状态机

    Concurrent状态机是一种同时执行多个状态的状态机.如下图所示.状态FOO和BAR同时执行,当两个状态输出的结果同时满足一个组合条件时(FOO输出outcome2,BAR输出outcome1)才 ...

  6. 虚拟机安装&Linux初探

    学习基于VirtualBox虚拟机安装Ubuntu图文教程在自己笔记本上安装Linux操作系统 安装虚拟机的过程还算顺利.除了在安装增强设备功能时需要将之前的硬盘弹出之外,没有遇到其他的问题. 通过实 ...

  7. Python模块安装路径初探

    在调用MySQL第三方工具mysqlrplsync是报错 mysqlrplsync --master=checksum:checksum@master_ip:3306 --slave=checksum ...

  8. 安装archlinux的另辟蹊径的命令及心得

    先说说我为什么开始入坑archlinux的吧,我最喜欢这个系统的一点就是简洁,DIY程度高,可以定制真正属于自己的专用系统.(像gentoo的话,就为了日常使用也没必要那么折腾,除非你是想在折腾的过程 ...

  9. [知识库分享系列] 四、ASP.NET MVC and Winform

    知识库分享系列: [知识库分享系列] 三.Web(高性能Web站点建设) [知识库分享系列] 二..NET(ASP.NET) [知识库分享系列] 一.开篇 分享介绍本篇分享两个知识库节点,分别为“AS ...

随机推荐

  1. MySQL 四种链接

    1.内联接 INNER JOIN(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接.     内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行. ...

  2. 栈应用之 括号匹配问题(Python 版)

    栈应用之 括号匹配问题(Python 版) 检查括号是否闭合 循序扫描被检查正文(一个字符)里的一个个字符 检查中跳过无关字符(所有非括号字符都与当前处理无关) 遇到开括号将其压入栈 遇到闭括号时弹出 ...

  3. Java基础82 jsp中的EL表达式(网页知识)

    1.EL表达式的作用 EL表达式的作用:向浏览器输出域对象中的变量值或者表达式计算结果.语法:${变量或者表达式} 注: Jsp的核心语法:jsp的表达式<%= %>和jsp的脚本< ...

  4. java基础43 IO流技术(输入字节流/缓冲输入字节流)

    通过File对象可以读取文件或者文件夹的属性数据,如果要读取文件的内容数据,那么我们就要使用IO技术. 一.输入字节流 输入字节流的体系:  -------| InputStream:所有输入字节流的 ...

  5. 你竟然在公钥中下毒!——如何在RSA公钥中添加后门

    原文:http://www.hackdig.com/?01/hack-17893.htm 分享到: 当我知道它是如何运行时,我惊得下巴都掉了.这是一个非常简单的手法,但这篇文章会颠覆你之前对RSA的看 ...

  6. C++ 必须使用初始化列表

    继承关系中,父类无默认构造函数 类类型类成员变量无默认构造函数 const类型成员变量 引用类型成员变量 不使用初始化列表,在创建对象调用构造函数之前会对所有的成员变量进行默认初始化,然后再执行构造函 ...

  7. es6之yield

    yield 关键字用来暂停和继续一个生成器函数.我们可以在需要的时候控制函数的运行. yield 关键字使生成器函数暂停执行,并返回跟在它后面的表达式的当前值.与return类似,但是可以使用next ...

  8. Python学习笔记:lambda表达式

    lambda表达式:通常是在需要一个函数,但又不想去命名一个函数的时候使用,即匿名函数. 示例如下: add = lambda x,y : x+ y add(1,2) # 结果为3 1.应用在函数式编 ...

  9. 打印数据的字节(十六进制)表示-c语言代码

    先取数据地址,转换成单字节长度的类型(unsigned char)的指针,然后按照十六进制逐字节打印即可,格式为“%.2x”. sizeof()函数获取数据的字节数. /* $begin show-b ...

  10. PHP XML操作的各种方法解析

    PHP提供了一整套的读取 XML文件的方法,很容易的就可以编写基于 XML的脚本程序.本章将要介绍 PHP与 XML的操作方法,并对几个常用的 XML类库做一些简要介绍. XML是一种流行的半结构化文 ...