测试代码,使用xmlrpc与roscore通信

ros的框架是使用rpc与server端通信,server维护topic的publisher,subscriber,param server,serviceServer

import xmlrpclib

server = xmlrpclib.ServerProxy("http://localhost:11311/",verbose=False)

print server.getSystemState('/rosout')

##返回的是 [topic node ] [topic node ] [topic node ] [topic node ]

server

rosmaster/main.py

try:
logger.info("Starting ROS Master Node")
#定义master的端口,工作线程,启动
master = rosmaster.master.Master(port, options.num_workers)
master.start() import time
while master.ok():
time.sleep(.1)
except KeyboardInterrupt:
logger.info("keyboard interrupt, will exit")
finally:
logger.info("stopping master...")
master.stop()

rosmaster/master.py

class Master(object):

    def __init__(self, port=DEFAULT_MASTER_PORT, num_workers=rosmaster.master_api.NUM_WORKERS):
self.port = port
self.num_workers = num_workers def start(self):
"""
Start the ROS Master.
"""
self.handler = None
self.master_node = None
self.uri = None # self.server.register_instance(self.handler)
# 注册handler到xmlrpc,以后每次远程调用的时候,寻找ROSMasterHandler类同名称的函数进行处理返回
handler = rosmaster.master_api.ROSMasterHandler(self.num_workers)
master_node = rosgraph.xmlrpc.XmlRpcNode(self.port, handler)
master_node.start() # poll for initialization
while not master_node.uri:
time.sleep(0.0001) # save fields
self.handler = handler
self.master_node = master_node
self.uri = master_node.uri

rosmaster/master_api.py

class ROSMasterHandler(object):
"""
XML-RPC handler for ROS master APIs.
API routines for the ROS Master Node. The Master Node is a
superset of the Slave Node and contains additional API methods for
creating and monitoring a graph of slave nodes. By convention, ROS nodes take in caller_id as the first parameter
of any API call. The setting of this parameter is rarely done by
client code as ros::msproxy::MasterProxy automatically inserts
this parameter (see ros::client::getMaster()).
""" def __init__(self, num_workers=NUM_WORKERS):
"""ctor.""" self.uri = None
self.done = False self.thread_pool = rosmaster.threadpool.MarkedThreadPool(num_workers)
# pub/sub/providers: dict { topicName : [publishers/subscribers names] }
self.ps_lock = threading.Condition(threading.Lock()) self.reg_manager = RegistrationManager(self.thread_pool) # maintain refs to reg_manager fields
self.publishers = self.reg_manager.publishers
self.subscribers = self.reg_manager.subscribers
self.services = self.reg_manager.services
self.param_subscribers = self.reg_manager.param_subscribers self.topics_types = {} #dict { topicName : type } # parameter server dictionary
self.param_server = rosmaster.paramserver.ParamDictionary(self.reg_manager)

ROSMasterHandler定义的所有函数,也就是xmlrpc服务器处理的函数

rosmaster/registrations.py

class RegistrationManager(object):
"""
Stores registrations for Master. RegistrationManager is not threadsafe, so access must be externally locked as appropriate
""" def __init__(self, thread_pool):
"""
ctor.
@param thread_pool: thread pool for queueing tasks
@type thread_pool: ThreadPool
"""
self.nodes = {}
self.thread_pool = thread_pool self.publishers = Registrations(Registrations.TOPIC_PUBLICATIONS)
self.subscribers = Registrations(Registrations.TOPIC_SUBSCRIPTIONS)
self.services = Registrations(Registrations.SERVICE)
self.param_subscribers = Registrations(Registrations.PARAM_SUBSCRIPTIONS) def _register(self, r, key, caller_id, caller_api, service_api=None):
# update node information
node_ref, changed = self._register_node_api(caller_id, caller_api)
node_ref.add(r.type, key)
# update pub/sub/service indicies
if changed:
self.publishers.unregister_all(caller_id)
self.subscribers.unregister_all(caller_id)
self.services.unregister_all(caller_id)
self.param_subscribers.unregister_all(caller_id)
r.register(key, caller_id, caller_api, service_api) def _unregister(self, r, key, caller_id, caller_api, service_api=None):
node_ref = self.nodes.get(caller_id, None)
if node_ref != None:
retval = r.unregister(key, caller_id, caller_api, service_api)
# check num removed field, if 1, unregister is valid
if retval[2] == 1:
node_ref.remove(r.type, key)
if node_ref.is_empty():
del self.nodes[caller_id]
else:
retval = 1, "[%s] is not a registered node"%caller_id, 0
return retval

上面的publishers,subscribers,services都是由 Registrations这个类进行管理

def registerPublisher(self, caller_id, topic, topic_type, caller_api):
"""
Register the caller as a publisher the topic.
@param caller_id: ROS caller id
@type caller_id: str
@param topic: Fully-qualified name of topic to register.
@type topic: str
@param topic_type: Datatype for topic. Must be a
package-resource name, i.e. the .msg name.
@type topic_type: str
@param caller_api str: ROS caller XML-RPC API URI
@type caller_api: str
@return: (code, statusMessage, subscriberApis).
List of current subscribers of topic in the form of XMLRPC URIs.
@rtype: (int, str, [str])
"""
#NOTE: we need topic_type for getPublishedTopics.
try:
self.ps_lock.acquire()
self.reg_manager.register_publisher(topic, caller_id, caller_api)
# don't let '*' type squash valid typing
if topic_type != rosgraph.names.ANYTYPE or not topic in self.topics_types:
self.topics_types[topic] = topic_type
pub_uris = self.publishers.get_apis(topic)
sub_uris = self.subscribers.get_apis(topic)
#通知订阅topic的所有subscriber,回调函数
self._notify_topic_subscribers(topic, pub_uris, sub_uris)
mloginfo("+PUB [%s] %s %s",topic, caller_id, caller_api)
sub_uris = self.subscribers.get_apis(topic)
finally:
self.ps_lock.release()
return 1, "Registered [%s] as publisher of [%s]"%(caller_id, topic), sub_uris

caller_id 是节点,caller_api http://localhost:53749/

  def _notify(self, registrations, task, key, value, node_apis):
"""
Generic implementation of callback notification
@param registrations: Registrations
@type registrations: L{Registrations}
@param task: task to queue
@type task: fn
@param key: registration key
@type key: str
@param value: value to pass to task
@type value: Any
"""
# cache thread_pool for thread safety
thread_pool = self.thread_pool
if not thread_pool:
return try:
for node_api in node_apis:
# use the api as a marker so that we limit one thread per subscriber
thread_pool.queue_task(node_api, task, (node_api, key, value))
except KeyError:
_logger.warn('subscriber data stale (key [%s], listener [%s]): node API unknown'%(key, s)) def _notify_param_subscribers(self, updates):
"""
Notify parameter subscribers of new parameter value
@param updates [([str], str, any)*]: [(subscribers, param_key, param_value)*]
@param param_value str: parameter value
"""
# cache thread_pool for thread safety
thread_pool = self.thread_pool
if not thread_pool:
return for subscribers, key, value in updates:
# use the api as a marker so that we limit one thread per subscriber
for caller_id, caller_api in subscribers:
self.thread_pool.queue_task(caller_api, self.param_update_task, (caller_id, caller_api, key, value))

client

def init_node(name, argv=None, anonymous=False, log_level=None, disable_rostime=False, disable_rosout=False, disable_signals=False, xmlrpc_port=0, tcpros_port=0):

class MasterProxy(object):
"""
Convenience wrapper for ROS master API and XML-RPC
implementation. The Master API methods can be invoked on this
object and will be forwarded appropriately. Names in arguments
will be remapped according to current node settings. Provides
dictionary-like access to parameter server, e.g.:: master[key] = value All methods are thread-safe.
"""

rospy 是python的客户端的实现

roscpp 是c++的客户端的实现

ros::NodeHandler构造函数执行会调用ros::start(),接下来ros的框架就起来了。

//init.cpp
namespace ros{
void start()
{ PollManager::instance()->addPollThreadListener(checkForShutdown);
XMLRPCManager::instance()->bind("shutdown", shutdownCallback); initInternalTimerManager(); TopicManager::instance()->start();
ServiceManager::instance()->start();
ConnectionManager::instance()->start();
PollManager::instance()->start();
XMLRPCManager::instance()->start();
}
};

gdb调试一个listener, talker,service ,client,可以看到每个node都起了好多线程,有专门的log thread, xmlrpc select线程,poll线程

rosgraph 是对底层的master的一个封装,用户一般不直接对他操作

ros的源码阅读的更多相关文章

  1. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  2. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  3. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  4. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  5. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  6. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  7. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  8. 【原】AFNetworking源码阅读(二)

    [原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...

  9. 【原】AFNetworking源码阅读(一)

    [原]AFNetworking源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 AFNetworking版本:3.0.4 由于我平常并没有经常使用AFNetw ...

随机推荐

  1. hdu 1228 A+B 字符串处理 超级大水题

    中文意思不解释. 很水,我本来想用switch处理字符串,然后编译不通过...原来switch只能处理整数型的啊,我都忘了. 然后就有了很挫的一大串if代码了... 代码: #include < ...

  2. jquery移除、绑定、触发元素事件使用示例详解

    这篇文章主要介绍了jquery移除.绑定.触发元素事件使用示例详解,需要的朋友可以参考下. unbind(type [,data]) //data是要移除的函数 $('#btn').unbind(&q ...

  3. WingIde的快捷键

     tab:自动补全    Alt+1:打开所有折叠    Alt+2:折叠所有classes    Alt+3:折叠所有函数和类    Alt+Backspace:删除光标所在单词的光标前的部分    ...

  4. Convolution and Deconvolution

    1.Introduction 2.Convolution 3.Deconvolution 4.Summary

  5. Html5新标签及用法

    HTML 5 是一个新的网络标准,目标在于取代现有的 HTML 4.01, XHTML 1.0 and DOM Level 2  HTML 标准.它希望能够减少浏览器对于需要插件的丰富性网络应用服务( ...

  6. centos 6.5 安装lnmp(linux+nginx+mysql+php)

    参考:http://www.cnblogs.com/AloneSword/archive/2013/03/18/2966750.html (总结并简要) 一安装cmake wget -c http:/ ...

  7. Ajax 传统的异步登陆

    这是一个传统的异步登陆,利用Ajax实现的,主要代码如下: 客户端代码: var http; function Button1_onclick() { if (window.ActiveXObject ...

  8. 配置JDK和TOMCAT

    配置JDK 1.先从官网下载最新的JDK安装包,然后安装.安装过程中会询问是否再装JRE,因为JDK中已经包含JRE,所以不必重复安装. 2.注意安装的路径名最好不要有中文或者空格出现. 3.在系统环 ...

  9. Markdown 学习资源

    语法 Mastering Markdown Markdown Cheatsheet pandoc 在线预览工具

  10. chcon可实现对文件的SEAndroid安全标签的修改

    chcon可实现对文件的SEAndroid安全标签的修改 参考使用如下: chcon -u u system/app/ chcon -r object_r system/app/ chcon -t s ...