用户数据UserData类和重映射Remapper类包含在smach中的user_data.py文件中实现,该博文主要介绍其原理和例子

  • UserData主要用于状态之间的数据传递,包括数据的输入input_keys和输出output_keys。用户数据做为状态的execute函数的参数来使用。而输入和输出的初始化在状态的__init__中进行初始化。数据结构可以表示为树状:

    UserData

    -- input_keys

    --output_keys

  • Rempaper主要用于用户数据中的输入input_keys和输出键output_keys的名字重映射。和消息的重映射的思路相同。

  进一步关于UserData如何在状态之间传递和指定输入输出键的,请参考如下的资料:

    原理:The principle of Passing User Data between States

    例子:The example of Passing User Data between States

1、源码注释

具体的中文翻译解释和一些额外的注释,请看如下的实现代码:

import threading
import copy import smach __all__ = ['UserData','Remapper']#用"__all__"导出UserData,Remapper两个类 #用户数据,用于状态之间的传递,输入或输出
class UserData(object):
"""SMACH user data structure."""
'''SMACH 用户数据结构'''
def __init__(self):
self._data = {}
self._locks = {}
self.__initialized = True def update(self, other_userdata):
"""Combine this userdata struct with another.
This overwrites duplicate keys with values from C{other_userdata}.
"""
'''将外加的用户数据和原有的用户数据合并,重复关键字的会更新相应的值'''
# Merge data
# 合并数据
self._data.update(other_userdata._data) def extract(self, keys, remapping):
ud = UserData()
reverse_remapping = {remapping[k]: k for k in remapping}
if len(reverse_remapping) != len(remapping):
smach.logerr("SMACH userdata remapping is not one-to-one: " + str(remapping))
for k in keys:
rmk = k
if k in reverse_remapping:
rmk = reverse_remapping[k]
ud[rmk] = copy.copy(self[k])
return ud def merge(self, ud, keys, remapping):
for k in keys:
rmk = k
if k in remapping:
rmk = remapping[k]
self[rmk] = copy.copy(ud[k]) def __getitem__(self, key):
return self.__getattr__(key) def __setitem__(self, key, item):
self._data[key] = item def keys(self):
return list(self._data.keys()) def __contains__(self,key):
return key in self._data def __getattr__(self, name):
"""Override getattr to be thread safe."""
'''重写getattr是线程安全的'''
if name[0] == '_':
return object.__getattr__(self, name)
if not name in self._locks.keys():
self._locks[name] = threading.Lock() try:
with self._locks[name]:
temp = self._data[name]
except:
smach.logerr("Userdata key '%s' not available. Available keys are: %s" % (name, str(list(self._data.keys()))))
raise KeyError() return temp def __setattr__(self, name, value):
"""Override setattr to be thread safe."""
'''重写setattr是线程安全的'''
# If we're still in __init__ don't do anything special
if name[0] == '_' or '_UserData__initialized' not in self.__dict__:
return object.__setattr__(self, name, value) if not name in self._locks.keys():
self._locks[name] = threading.Lock() self._locks[name].acquire()
self._data[name] = value
self._locks[name].release() # Const wrapper
def get_const(obj):
"""Get a const reference to an object if it has "user-defined" attributes."""
'''如果obj有“user-defined”属性,那么返回obj的一个常引用'''
if hasattr(obj,'__dict__'):
smach.logdebug("Making const '%s'" % str(obj))
return Const(obj)
else:
return obj #object对象常量化
class Const(object):
"""Wrapper that treats "user-defined" fields as immutable. This wrapper class is used when user data keys are specified as input keys,
but not as output keys.
""" '''一个对object的封装器,将object中的“user-defined”的域设置为不可改变,即只读 当用户数据的keys中被指定了input keys,但没有 output keys时,会用到这个封装器。
'''
def __init__(self, obj):
smach.logdebug("Making const '%s'" % str(obj))
self._obj = obj
self.__initialized = True def __getattr__(self, name):
smach.logdebug("Getting '%s' from const wrapper." % name)
attr = getattr(self._obj,name)
return get_const(attr) def __getitem__(self, name):
smach.logdebug("Getting '%s' from const wrapper." % name)
attr = self._obj[name]
return get_const(attr) def __setattr__(self, name, value):
if '_const__initialized' not in self.__dict__:
return object.__setattr__(self, name, value)
smach.logerr("Attempting to set '%s' but this member is read-only." % name)
raise TypeError() def __delattr__(self, name):
smach.logerr("Attempting to delete '%s' but this member is read-only." % name)
raise TypeError() #用户数据结构的键值重映射
class Remapper(object):
"""Key-remapping proxy to a SMACH userdata structure."""
'''对Smach 用户数据结构的一个键值重映射代理'''
def __init__(self, ud, input_keys=[], output_keys=[], remapping={}):
self._ud = ud
self._input = input_keys
self._output = output_keys
self._map = remapping
self.__initialized = True def _remap(self, key):
"""Return either the key or it's remapped value."""
'''返回key‘s value或者remapped’s value'''
if key in self._map:
return self._map[key]
return key def update(self, other_userdata):
self._ud.update(other_userdata) def __getitem__(self, key):#“__“两个下划线表示内置函数,类似inline?;“_“一个下划线表示私有函数
if key not in self._input:
raise smach.InvalidUserCodeError("Reading from SMACH userdata key '%s' but the only keys that were declared as input to this state were: %s. This key needs to be declaread as input to this state. " % (key, self._input))
if key not in self._output:
return get_const(self._ud.__getitem__(self._remap(key)))
return self._ud.__getitem__(self._remap(key)) def __setitem__(self, key, item):
if key not in self._output:
smach.logerr("Writing to SMACH userdata key '%s' but the only keys that were declared as output from this state were: %s." % (key, self._output))
return
self._ud.__setitem__(self._remap(key),item) def keys(self):
return [self._remap(key) for key in self._ud.keys() if key in self._input] def __contains__(self,key):
if key in self._input:
return self._remap(key) in self._ud
else:
return False def __getattr__(self, name):
if name[0] == '_':
return object.__getattr__(self, name)
if name not in self._input:
raise smach.InvalidUserCodeError("Reading from SMACH userdata key '%s' but the only keys that were declared as input to this state were: %s. This key needs to be declaread as input to this state. " % (name, self._input))
if name not in self._output:
return get_const(getattr(self._ud, self._remap(name)))
return getattr(self._ud, self._remap(name)) def __setattr__(self, name, value):
if name[0] == '_' or '_Remapper__initialized' not in self.__dict__:
return object.__setattr__(self, name, value)
if name not in self._output:
smach.logerr("Writing to SMACH userdata key '%s' but the only keys that were declared as output from this state were: %s." % (name, self._output))
return None
setattr(self._ud, self._remap(name), value)

2、例子-用户数据和键值重映射

参考ROS的smach例程,例子:The example of Passing User Data between States

#!/usr/bin/env python

import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros # define state Foo
class Foo(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1','outcome2'],
input_keys=['foo_counter_in'],#键初始化
output_keys=['foo_counter_out']) def execute(self, userdata):#用户数据做为参数使用
rospy.loginfo('Executing state FOO')
if userdata.foo_counter_in < 3:
userdata.foo_counter_out = userdata.foo_counter_in + 1
return 'outcome1'
else:
return 'outcome2' # define state Bar
class Bar(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1'],
input_keys=['bar_counter_in'])#键对初始化 def execute(self, userdata):#用户数据做为参数使用
rospy.loginfo('Executing state BAR')
rospy.loginfo('Counter = %f'%userdata.bar_counter_in)
return 'outcome1' def main():
rospy.init_node('smach_example_state_machine') # Create a SMACH state machine
sm = smach.StateMachine(outcomes=['outcome4'])
sm.userdata.sm_counter = 0 # Open the container
with sm:
# Add states to the container
smach.StateMachine.add('FOO', Foo(),
transitions={'outcome1':'BAR',
'outcome2':'outcome4'},
remapping={'foo_counter_in':'sm_counter',
'foo_counter_out':'sm_counter'})
                    
smach.StateMachine.add('BAR', Bar(),
transitions={'outcome1':'FOO'},
remapping={'bar_counter_in':'sm_counter'})#键值重映射,重映射的名字可以根据具体的业务指定,这样更易于理解 # Execute SMACH plan
outcome = sm.execute() if __name__ == '__main__':
main()

SMACH(五)----用户数据UserData类和重映射Remapper类的原理和例子的更多相关文章

  1. ITTC数据挖掘平台介绍(五) 数据导入导出向导和报告生成

    一. 前言 经过了一个多月的努力,软件系统又添加了不少新功能.这些功能包括非常实用的数据导入导出,对触摸进行优化的画布和画笔工具,以及对一些智能分析的报告生成模块等.进一步加强了平台系统级的功能. 马 ...

  2. 【Java EE 学习 69 下】【数据采集系统第一天】【实体类分析和Base类书写】

    之前SSH框架已经搭建完毕,现在进行实体类的分析和Base类的书写.Base类是抽象类,专门用于继承. 一.实体类关系分析 既然是数据采集系统,首先调查实体(Survey)是一定要有的,一个调查有多个 ...

  3. Android系统的五种数据存储形式(一)

    Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...

  4. VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)

    上一节中鸡啄米讲了定时器Timer的用法,本节介绍下文件操作类CFile类的使用. CFile类概述 如果你学过C语言,应该知道文件操作使用的是文件指针,通过文件指针实现对它指向的文件的各种操作.这些 ...

  5. .NET混合开发解决方案16 管理WebView2的用户数据

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  6. 使用python抓取婚恋网用户数据并用决策树生成自己择偶观

    最近在看<机器学习实战>的时候萌生了一个想法,自己去网上爬一些数据按照书上的方法处理一下,不仅可以加深自己对书本的理解,顺便还可以在github拉拉人气.刚好在看决策树这一章,书里面的理论 ...

  7. C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据

    我曾经在系列文章中的<C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍>中介绍了微信菜单里面的重定向操作,通过这个重定向操作,我们可以获取一个code值,然后获取用户的open ...

  8. SQL Server 2016五大优势挖掘企业用户数据价值

    SQL Server 2016五大优势挖掘企业用户数据价值 转载自:http://soft.zdnet.com.cn/software_zone/2016/0318/3074442.shtml 3月1 ...

  9. 【php爬虫】百万级别知乎用户数据爬取与分析

    代码托管地址:https://github.com/hoohack/zhihuSpider 这次抓取了110万的用户数据,数据分析结果如下: 开发前的准备 安装Linux系统(Ubuntu14.04) ...

随机推荐

  1. Deploy Openstack all-in-one Shell Script

    Deploy Openstack all-in-one Shell Script At present(2015/10), the RDO deploment method can only inst ...

  2. 创建自己的maven模板

    概述 使用maven创建项目时,提供的基础的工程太简单不是想要的,并且创建过程很慢,使用起来体验不好.如果可以根据自己的需要,直接创建模板,然后进行类似项目拷贝的工作,那就完美.幸运的是,maven提 ...

  3. centos下安装zabbix

    1. 安装mysql CREATE DATABASE zabbix;GRANT ALL ON zabbix.* TO 'zabbix'@'192.168.19.%' IDENTIFIED BY '12 ...

  4. pip-django-cms

    pip install django-el_pagination pip install django-ckeditor

  5. python import 与 from ... import ...

    import test test = 'test.py all code' from test import m1 m1 ='code'

  6. python 创建项目

    项目骨架 nose 测试框架 Windows 10 配置 创建骨架项目目录 Windows 10 的 PowerShell mkdir projects cd projects/ mkdir skel ...

  7. TCP可靠传输及流量控制实现原理

    一.为什么TCP是可靠传输? 1. 停止等待协议 通过确认与超时重传机制实现可靠传输 在发送完一个分组后,必须暂时保留已发送的分组的副本. 分组和确认分组都必须进行编号. 超时计时器的重传时间应当比数 ...

  8. 【原创】MySQL5.7.18(ptmalloc VS tcmalloc VS jemalloc)性能测试

    ptmalloc(glibc的malloc)是Linux提供的内存分配管理模块,目前我们MySQL默认使用的内存分配模块. tcmalloc是Google提供的内存分配管理模块. jemalloc是F ...

  9. OpenGL笔记<第一章> 构建 GLSL class

    恭喜,我们终于很扎实地完成了第一章——glsl 入门 不幸的是,it's not the basic of GLSL shader ,我们下一节开篇,basic of GLSL shader 在下一章 ...

  10. 1013 Battle Over Cities (25)(25 point(s))

    problem It is vitally important to have all the cities connected by highways in a war. If a city is ...