The setup.py under the Rosmaster bag,
From Distutils.core Import Setup from
catkin_pkg.python_setup import generate_distutils_setup
d = generate_ Distutils_setup (
packages=[' Rosmaster ',
package_dir={': ' src '},
scripts=[' Scripts/rosmaster '),
requires=[' roslib ', ' rospkg ']
)
Setup (**D)
Where the command line script is Scripts/rosmaster (Roslaunch will use Popen to start the rosmaster process, the script is called, subsequent analysis ).
Rosmaster only performed the Rosmaster_main () function,
Import Rosmaster
Rosmaster.rosmaster_main ()
The Rosmaster_main () function is as follows,
#ros_comm \tools\rosmaster\src\rosmaster\main.py def rosmaster_main (argv=sys.argv, Stdout=sys.stdout, env= Os.environ): #① is preceded by parsing command-line arguments 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= "over Ride number of worker threads ", metavar=" Num_workers ") parser.add_option ("-T ","--timeout ", dest = "Timeout", help= "override the socket connection timeout (in seconds).", metavar= "timeout") Opti ONS, args = Parser.parse_args (argv[1:]) # only Arg. 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 process default listener port #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") #③ create Master object, start Xmlrpcnode #NUM_WORKERS = 3 #number of Threads we use to send publisher_update notifications #三个工作线程 master = rosmaster.master.Master (port, Optio ns.num_workers) Master.start () Import time while Master.ok (): Time.sleep (. 1) exce PT KeyboardInterrupt:logger.info ("Keyboard interrupt, would exit") Finally:logger.info ("Stopping mast Er ... ") master.stop ()
The most important part of the previous code is section ③:
A master class object was created with a default port of 11311 and three worker threads;
Call Start ().
for Python xmlrpc, you can refer to 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 #① Create a class Rosmasterhand Ler (object) Object handler = Rosmaster.master_api. Rosmasterhandler (self.num_workers) #② creates a Xmlrpcnode object Master_node = Rosgraph.xmlrpc.XmlRpcNode (Self.port, Handler) #③ call Xmlrpcnode's start (), is actually a new startup thread, the thread function is xmlrpcnode in the Run () Master_node.start () # poll fo R initialization While not Master_node.uri:time.sleep (0.0001) # Save Fields Self.ha Ndler = Handler Self.master_node = Master_node Self.uri = Master_node.uri Logging.getlogger (' Rosm Aster.master '). Info ("Master initialized:port[%s], uri[%s]", Self.port, Self.uri)
# Master Implementation Class Rosmasterhandler (object): "" "Xml-rpc handler for ROS mast
Er 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 are rarely done by client code as Ros::msproxy::masterproxy automatically inserts thi
s 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.py class Xmlrpcnode (object): "" "Generic xml-rpc node.
Handles the additional complexity of the binding an XML-RPC server to an arbitrary port.
Xmlrpcnode is initialized if the URI field has a value.
"" "Def __init__ (self, port=0, Rpc_handler=none, On_run_error=none):" "" XML RPC Node constructor :p Aram Port:port to use for starting Xml-rpc API. Set to 0 or omit to bind to any available port, "int":p Aram Rpc_handler:xml-rpc API handler for node, ' xmlrpch Andler ':p Aram On_run_error:function to invoke if Server.run () throws Exception. Server always terminates if run () throws, but the enables cleanup routines to is invoked if server goes down, a s well as include additional debugging.
' fn (Exception) ' "" "#调用父类构造函数 super (Xmlrpcnode, self). __init__ () #① the constructor passed in Rpc_handler
Self.handler = Rpc_handler ... def start (self): "" "Initiate a thread to run the XML RPC server.
Uses Thread.start_new_thread. "" "#② start a new thread, the thread function is run () _thread.start_new_thread (Self.run, ()) def run (self): try:s Elf._run () def _run_init (self): logger = Logging.getlogger (' xmlrpc ') try:log_re
Quests = 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 = THREADINGXMLRPCSE RVer ((bind_address, Port), log_requests) Self.port = self.server.server_address[1] #set The port to whatever s
Erver 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 D Etermining XML-RPCURI #-If Ros_ip/ros_hostname is set, use that address #-if the HOSTNAME returns a Non-localhos
T 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/'% (ov
Erride, 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 no T Uri:uri = ' http://%s:%s/'% (rosgraph.network.get_local_address (), self.port) Self.set_uri (Ur i) # log print Started XML-RPC server [http://lyf:11311/] Logger.info ("Started XML-RPC server [%s]", SE Lf.uri) #③ ThisThe most important is the following two functions, the handler register to XML-RPC, # handler is a rosmaster.master_api. Rosmasterhandler Object Self.server.register_multicall_functions () self.server.register_instance (self.h
Andler) ... def _run (self): "" "Main processing thread body. : Raises:: Exc: ' socket.error ' If server cannot bind "" "Self._run_init () while not Self.is_shutdow N:try: #④ server Start monitoring run Self.server.serve_forever ()
The entire execution flow of rosmaster can be seen through the above Code analysis:
rosmaster command line script execution Rosmaster_main ();
started a new thread to start XML-RPC server (rosmaster);
XML-RPC Server Registers a method that defines RPC for a class of Rosmasterhandler.
The next step is to analyze how Roslaunch calls this Rosmaster script to connect roscore,roslaunch,rosmaster .