roscore調用了roslaunch.main,我們繼續追蹤,進到ros_comm-noetic-develtoolsroslaunchsrcroslaunch文件夾中,發現有個__init__.py文件,說明這個文件夾是一個python包,打開__init__.py文件找到def main(argv=sys.argv),這就是roscore調用的函數roslaunch.main的實現,如下(這里只保留主要的代碼,不太重要的刪掉了)。
def main(argv=sys.argv):
options = None
logger = None
try:
from . import rlutil
parser = _get_optparse()
(options, args) = parser.parse_args(argv[1:])
args = rlutil.resolve_launch_arguments(args)
write_pid_file(options.pid_fn, options.core, options.port)
uuid = rlutil.get_or_generate_uuid(options.run_id, options.wait_for_master)
configure_logging(uuid)
# #3088: don't check disk usage on remote machines
if not options.child_name and not options.skip_log_check:
rlutil.check_log_disk_usage()
logger = logging.getLogger('roslaunch')
logger.info("roslaunch starting with args %s"%str(argv))
logger.info("roslaunch env is %s"%os.environ)
if options.child_name:
# 這里沒執行到,就不列出來了
else:
logger.info('starting in server mode')
# #1491 change terminal name
if not options.disable_title:
rlutil.change_terminal_name(args, options.core)
# Read roslaunch string from stdin when - is passed as launch filename.
roslaunch_strs = []
# This is a roslaunch parent, spin up parent server and launch processes.
# args are the roslaunch files to load
from . import parent as roslaunch_parent
# force a port binding spec if we are running a core
if options.core:
options.port = options.port or DEFAULT_MASTER_PORT
p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs, is_core=options.core, port=options.port, local_only=options.local_only, verbose=options.verbose, force_screen=options.force_screen, force_log=options.force_log, num_workers=options.num_workers, timeout=options.timeout, master_logger_level=options.master_logger_level, show_summary=not options.no_summary, force_required=options.force_required, sigint_timeout=options.sigint_timeout, sigterm_timeout=options.sigterm_timeout)
p.start()
p.spin()
roslaunch.main開啟了日志,日志記錄的信息可以幫我們了解main函數執行的順序。
我們去Ubuntu的.ros/log/路徑下,打開roslaunch-ubuntu-52246.log日志文件,內容如下。
通過閱讀日志我們發現,main函數首先檢查日志文件夾磁盤占用情況,如果有剩余空間就繼續往下運行。
然后把運行roscore的終端的標題給改了。
再調用ROSLaunchParent類中的函數,這大概就是main函數中最重要的地方了。
ROSLaunchParent類的定義是在同一路徑下的parent.py文件中。為什么叫LaunchParent筆者也不清楚。
先不管它,我們再看日志,發現運行到了下面這個函數,它打算啟動XMLRPC服務器端。
所以調用的順序是:roslaunch_ init _.py文件中的main()函數調用parent.pystart()函數,start()函數調用自己類中的_start_infrastructure()函數,_start_infrastructure()函數調用自己類中的_start_server()函數,_start_server()函數再調用server.py中的start函數。
def _start_server(self):
self.logger.info("starting parent XML-RPC server")
self.server = roslaunch.server.ROSLaunchParentNode(self.config, self.pm)
self.server.start()
我們再進到server.py文件中,找到ROSLaunchNode類,里面的start函數又調用了父類XmlRpcNode中的start函數。
class ROSLaunchNode(xmlrpc.XmlRpcNode):
"""
Base XML-RPC server for roslaunch parent/child processes
"""
def start(self):
logger.info("starting roslaunch XML-RPC server")
super(ROSLaunchNode, self).start()
我們來到ros_comm-noetic-develtoolsrosgraphsrcrosgraph路徑,找到xmlrpc.py文件。找到class XmlRpcNode(object)類,再進入start(self)函數,發現它調用了自己類的run函數,run函數又調用了自己類中的_run函數,_run函數又調用了自己類中的_run_init()函數,在這里才調用了真正起作用的ThreadingXMLRPCServer類。
因為master節點是用python實現的,所以,需要有python版的XMLRPC庫。
幸運的是,python有現成的XMLRPC庫,叫SimpleXMLRPCServer。SimpleXMLRPCServer已經內置到python中了,無需安裝。
所以,ThreadingXMLRPCServer類直接繼承了SimpleXMLRPCServer,如下。
class ThreadingXMLRPCServer(socketserver.ThreadingMixIn, SimpleXMLRPCServer)
-
函數
+關注
關注
3文章
4306瀏覽量
62431 -
MASTER
+關注
關注
0文章
103瀏覽量
11262 -
ROS
+關注
關注
1文章
276瀏覽量
16967
發布評論請先 登錄
相關推薦
評論