测试代码,使用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. ArcGIS地图文档MXD效率慢的一点建议(二)

    经常有用户询问,我的MXD图层比较多,而且配置好了相关的符号,但是我的服务器更换了一下,而且两个服务器的要素类名称都是一样的,我想配置一下新的数据源,而且我的这个MXD已经连接不到原来的数据源了,打开 ...

  2. 【阿里云产品公测】OTS使用之简单线上产品实践基于PythonSDK

    阿里云用户:morenocjm 实践是检验真理的唯一标准,学习技术需要通过实践过程中的不断尝试,才能够快速掌握要领.OTS是构建在阿里云飞天分布式系统之上的NoSQL数据库服务,提供海量结构化数据的存 ...

  3. OC之property和自动释放池

    property实例 property参数 自动释放池 一.property实例 1.前边的例子我们看到,我们在一个类中如果用到另外一个类的实例作为自己的成员变量时,通常需要在setter方法中,先r ...

  4. Frameset使用教程 小结

    frame,是网页开发必须掌握的知识.例如后台架构.局部刷新,页面分割,都是frame的用途表现,尤其是后台页面制作,使用frame会给用户带来非常舒适的使用感受. frame知识点包括(frames ...

  5. React Native(ios)项目中logo,启动屏设置

    由于logo和启动屏尺寸多,react native(ios)中没有命令可以自动生成各种的尺寸,所以可以使用以下办法:在ionic项目中生成(使用命令:ionic resources)后,再粘贴到re ...

  6. Spring操作mongo排序,限制查询记录数

    Query query = new Query(); Criteria criteria = Criteria.where("timestamp").gt(from).lt(to) ...

  7. 有一种风格,叫做 Low Poly 3D

    原作:Simon阿文    杂交编辑者:RhinoC       个人更推崇使用第二款神器 ImageTriangulator :http://www.conceptfarm.ca/2013/port ...

  8. MVC datetime? & datetime 设置格式

    设置datetime的格式,直接有方法重载进行,即使数据为datetime?格式 设置起始时间在配置的时候添加设置 $('#closeTime').datetimepicker({ language: ...

  9. springMVC第一课--配置文件

    刚学springMVC,记录下学习过程,供以后查阅(githup源码). 1,新建一个web工程.(其他按常规来) 如下:添加applicationContext.xml,webmvc-servlet ...

  10. js中关于原型的几个方法

    一.isPrototypeOf()方法,判断一个对象是否是另一个对象的原型 function Student(name,age){ this.name=name; this.age=age; } va ...