测试代码,使用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. 新手不了解Xcode和mac系统可能犯得错误和我的建议

    我是学iOS刚入门的新手,本人装的时黑苹果,我是喜欢完美的人,但黑苹果又是不完美的系统,比如关不了机啊,和显卡驱动不了啊,当自己的电脑出现白屏和卡顿的时候气的没脾气.我是一个新手.开始学的时java但 ...

  2. 《Cortex-M0权威指南》之体系结构---异常和中断

    转载请注明来源:cuixiaolei的技术博客 异常会引起程序控制的变化.在异常发生时,处理器停止当前的任务,转而执行异常处理程序,异常处理完成后,会继续执行刚才的任务.异常分为很多种,中断是其中之一 ...

  3. Linux_netstat 详解

    简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...

  4. cordova在app内部指定浏览器打开链接插件:cordova-plugin-inappbrowser

    原文网址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-plugin-inappbrowser/ 要想App里边的 ...

  5. hdu-5683 zxa and xor (位运算)

    题目链接: zxa and xor Time Limit: 16000/8000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Othe ...

  6. MVC 菜鸟学习记录2

    自定义Html.Helper扩展方法 在Models文件夹下新建一个静态类,取名为:MyHtmlHelper.cs 将MyHtmlHelper设置为static,并写入以下的一个静态方法 public ...

  7. (转)优化js脚本设计,防止浏览器假死

    在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们先来看一下浏览器的内 ...

  8. iOS 通过tag查找控件

    //比如创建一个UIImageView到view上 UIImageView *imageView = [[UIImageView allc] init]; imageView.tag = 10001; ...

  9. 使用wordpress自带ajax方法

    css3 提示只适用于高级浏览器: ChromeFirefoxSafariIE9+ valid.invalid.required的定义 代码如下 复制代码 input:required, input: ...

  10. 对Json字符串进行格式化显示

    很多时候,我们拿Json字符串作为返回结果,但是当数据量多的时候,一堆的Json字符串看起来很不直观,这时候我们可以使用以下办法将Json字符串格式化一下再输出 var JsonUti = { //定 ...