ros源码分析(3)—rosmaster 包分析
来源:互联网 发布:淘宝子账号登录密码 编辑:程序博客网 时间:2024/05/22 14:02
rosmaster包下的setup.py,
from distutils.core import setupfrom catkin_pkg.python_setup import generate_distutils_setupd = generate_distutils_setup( packages=['rosmaster'], package_dir={'': 'src'}, scripts=['scripts/rosmaster'], requires=['roslib', 'rospkg'])setup(**d)
其中,命令行脚本为scripts/rosmaster(roslaunch会利用popen启动rosmaster进程,调用的就是该脚本,后续会分析)。
rosmaster仅执行了rosmaster_main()函数,
import rosmasterrosmaster.rosmaster_main()
rosmaster_main()函数如下,
#ros_comm\tools\rosmaster\src\rosmaster\main.pydef rosmaster_main(argv=sys.argv, stdout=sys.stdout, env=os.environ): #①前面都是解析命令行参数 parser = optparse.OptionParser(usage="usage: zenmaster [options]") parser.add_option("--core", dest="core", action="store_true", default=False, help="run as core") parser.add_option("-p", "--port", dest="port", default=0, help="override port", metavar="PORT") parser.add_option("-w", "--numworkers", dest="num_workers", default=NUM_WORKERS, type=int, help="override number of worker threads", metavar="NUM_WORKERS") parser.add_option("-t", "--timeout", dest="timeout", help="override the socket connection timeout (in seconds).", metavar="TIMEOUT") options, args = parser.parse_args(argv[1:]) # only arg that zenmaster supports is __log remapping of logfilename for arg in args: if not arg.startswith('__log:='): parser.error("unrecognized arg: %s"%arg) configure_logging()# ②rosmaster进程默认监听端口 #DEFAULT_MASTER_PORT=11311 #default port for master's to bind to port = rosmaster.master.DEFAULT_MASTER_PORT if options.port: port = int(options.port)....... try: logger.info("Starting ROS Master Node") #③ 创建Master对象,启动XmlRpcNode #NUM_WORKERS = 3 #number of threads we use to send publisher_update notifications #三个工作线程 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()
上段代码最重要的是第③部分:
创建了个Master类对象,默认端口为11311 ,三个工作线程;
调用start()。
关于python xmlrpc,可以参考http://blog.csdn.net/lewif/article/details/75150722。
class Master(object): def start(self): """ Start the ROS Master. """ self.handler = None self.master_node = None self.uri = None #① 创建一个class ROSMasterHandler(object)对象 handler = rosmaster.master_api.ROSMasterHandler(self.num_workers) #② 创建一个XmlRpcNode对象 master_node = rosgraph.xmlrpc.XmlRpcNode(self.port, handler) #③ 调用XmlRpcNode的start(),其实是新启动一个线程,线程函数为XmlRpcNode中的run() 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 logging.getLogger('rosmaster.master').info("Master initialized: port[%s], uri[%s]", self.port, self.uri)
# Master Implementationclass 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 .......
#ros_comm\tools\rosgraph\src\rosgraph\xmlrpc.pyclass XmlRpcNode(object): """ Generic XML-RPC node. Handles the additional complexity of binding an XML-RPC server to an arbitrary port. XmlRpcNode is initialized when the uri field has a value. """ def __init__(self, port=0, rpc_handler=None, on_run_error=None): """ XML RPC Node constructor :param port: port to use for starting XML-RPC API. Set to 0 or omit to bind to any available port, ``int`` :param rpc_handler: XML-RPC API handler for node, `XmlRpcHandler` :param on_run_error: function to invoke if server.run() throws Exception. Server always terminates if run() throws, but this enables cleanup routines to be invoked if server goes down, as well as include additional debugging. ``fn(Exception)`` """ #调用父类构造函数 super(XmlRpcNode, self).__init__() #①构造函数传进来的rpc_handler self.handler = rpc_handler ... def start(self): """ Initiate a thread to run the XML RPC server. Uses thread.start_new_thread. """ #② 启动新线程,线程函数为run() _thread.start_new_thread(self.run, ()) def run(self): try: self._run() def _run_init(self): logger = logging.getLogger('xmlrpc') try: log_requests = 0 port = self.port or 0 #0 = any bind_address = rosgraph.network.get_bind_address() logger.info("XML-RPC server binding to %s:%d" % (bind_address, port)) self.server = ThreadingXMLRPCServer((bind_address, port), log_requests) self.port = self.server.server_address[1] #set the port to whatever server bound to if not self.port: self.port = self.server.socket.getsockname()[1] #Python 2.4 assert self.port, "Unable to retrieve local address binding" # #528: semi-complicated logic for determining XML-RPC URI # - if ROS_IP/ROS_HOSTNAME is set, use that address # - if the hostname returns a non-localhost value, use that # - use whatever rosgraph.network.get_local_address() returns uri = None override = rosgraph.network.get_address_override() if override: uri = 'http://%s:%s/'%(override, self.port) else: try: hostname = socket.gethostname() if hostname and not hostname == 'localhost' and not hostname.startswith('127.') and hostname != '::': uri = 'http://%s:%s/'%(hostname, self.port) except: pass if not uri: uri = 'http://%s:%s/'%(rosgraph.network.get_local_address(), self.port) self.set_uri(uri) # log打印Started XML-RPC server [http://lyf:11311/] logger.info("Started XML-RPC server [%s]", self.uri) # ③这里最主要的是下面两个函数,将handler注册到xml-rpc, # handler是个rosmaster.master_api.ROSMasterHandler对象 self.server.register_multicall_functions() self.server.register_instance(self.handler) ....... def _run(self): """ Main processing thread body. :raises: :exc:`socket.error` If server cannot bind """ self._run_init() while not self.is_shutdown: try: #④ 服务端开始监听运行 self.server.serve_forever()
通过上面的代码分析可以看到rosmaster的整个执行流程:
rosmaster命令行脚本执行rosmaster_main();
启动了一个新的线程来启动xml-rpc server(rosmaster);
xml-rpc server注册了一个类为ROSMasterHandler,定义了rpc的方法。
接下来会继续分析roslaunch是如何调用这个rosmaster脚本,将roscore,roslaunch,rosmaster联系起来。
阅读全文
0 0
- ros源码分析(3)—rosmaster 包分析
- ros源码分析(5)—rosmaster xmlrpc api
- ROS create_master_process 创建rosmaster 线程参数分析
- ros源码分析(2)—roslaunch 包分析
- ROS源码分析
- ros源码分析(1)—roscore概况
- ROS 源码分析中一
- 简单的ros源码分析
- ros源码分析(4)—roslaunch之process monitoring(pmon)
- ros源码分析(6)—roslaunch Commandline Tools
- ros源码分析(7)—roslaunch .launch 文件
- ros源码分析(8)—roslaunch .launch文件中的tag
- Hibernate源码包分析
- ROS源码分析--子话题-catkin
- ros::init源码分析(未完待续。)
- gRPC-transport包源码分析
- ROS 机器人源码分析之 self._launch_core_nodes() rosout/rosout
- ros nodehandle源码级深度分析(未完待续)
- mysql存储过程语法及实例
- java 基础
- jbpm7学习笔记
- codeforces 831D Office Keys
- 10表格元素上
- ros源码分析(3)—rosmaster 包分析
- @JoinColumn
- Intellij Idea 15 下新建 Hibernate 项目以及如何添加配置
- Android避免进入一页面后EditText自动弹出软键盘
- 【android学习】Fragment
- select 语句查询
- 安卓——WIFI连接
- Android 把bitmap图片的某一部分的颜色改成其他颜色
- 算法总览