Package roslaunch
[frames] | no frames]

Source Code for Package roslaunch

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2008, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: __init__.py 12732 2011-01-04 01:21:14Z kwc $ 
 34   
 35  from __future__ import with_statement 
 36   
 37  import os 
 38  import logging 
 39  import sys 
 40   
 41  import roslib.packages 
 42  import roslaunch.core 
 43  import roslaunch.param_dump 
 44   
 45  # symbol exports 
 46  from roslaunch.core import Node, Test, Master, RLException 
 47  from roslaunch.config import ROSLaunchConfig 
 48  from roslaunch.launch import ROSLaunchRunner 
 49  from roslaunch.xmlloader import XmlLoader, XmlParseException 
 50   
 51   
 52  # script api 
 53  from roslaunch.scriptapi import ROSLaunch 
 54  from roslaunch.pmon import Process 
 55   
 56  try: 
 57      from rosmaster import DEFAULT_MASTER_PORT 
 58  except: 
 59      DEFAULT_MASTER_PORT = 11311 
 60       
 61  NAME = 'roslaunch' 
 62   
63 -def configure_logging(uuid):
64 """ 65 scripts using roslaunch MUST call configure_logging 66 """ 67 try: 68 import socket 69 import roslib.roslogging 70 logfile_basename = os.path.join(uuid, '%s-%s-%s.log'%(NAME, socket.gethostname(), os.getpid())) 71 # additional: names of python packages we depend on that may also be logging 72 logfile_name = roslib.roslogging.configure_logging(NAME, filename=logfile_basename) 73 if logfile_name: 74 print "... logging to %s"%logfile_name 75 76 # add logger to internal roslaunch logging infrastructure 77 logger = logging.getLogger('roslaunch') 78 roslaunch.core.add_printlog_handler(logger.info) 79 roslaunch.core.add_printerrlog_handler(logger.error) 80 except: 81 print >> sys.stderr, "WARNING: unable to configure logging. No log files will be generated"
82
83 -def write_pid_file(options_pid_fn, options_core, port):
84 from roslib.rosenv import get_ros_home 85 if options_pid_fn or options_core: 86 if options_pid_fn: 87 pid_fn = options_pid_fn 88 else: 89 # NOTE: this assumption is not 100% valid until work on #3097 is complete 90 if port is None: 91 port = DEFAULT_MASTER_PORT 92 #2987 93 pid_fn = os.path.join(get_ros_home(), 'roscore-%s.pid'%(port)) 94 with open(pid_fn, "w") as f: 95 f.write(str(os.getpid()))
96
97 -def _get_optparse():
98 from optparse import OptionParser 99 100 parser = OptionParser(usage="usage: %prog [options] [package] <filename> [arg_name:=value...]", prog=NAME) 101 parser.add_option("--args", 102 dest="node_args", default=None, 103 help="Print command-line arguments for node", metavar="NODE_NAME") 104 parser.add_option("--nodes", 105 dest="node_list", default=False, action="store_true", 106 help="Print list of node names in launch file") 107 parser.add_option("--find-node", 108 dest="find_node", default=None, 109 help="Find launch file that node is defined in", metavar="NODE_NAME") 110 parser.add_option("-c", "--child", 111 dest="child_name", default=None, 112 help="Run as child service 'NAME'. Required with -u", metavar="NAME") 113 parser.add_option("--local", 114 dest="local_only", default=False, action="store_true", 115 help="Do not launch remote nodes") 116 # #2370 117 parser.add_option("--screen", 118 dest="force_screen", default=False, action="store_true", 119 help="Force output of all local nodes to screen") 120 parser.add_option("-u", "--server_uri", 121 dest="server_uri", default=None, 122 help="URI of server. Required with -c", metavar="URI") 123 parser.add_option("--run_id", 124 dest="run_id", default=None, 125 help="run_id of session. Required with -c", metavar="RUN_ID") 126 # #1254: wait until master comes online before starting 127 parser.add_option("--wait", action="store_true", 128 dest="wait_for_master", default=False, 129 help="wait for master to start before launching") 130 parser.add_option("-p", "--port", 131 dest="port", default=None, 132 help="master port. Only valid if master is launched", metavar="PORT") 133 parser.add_option("--core", action="store_true", 134 dest="core", default=False, 135 help="Launch core services only") 136 parser.add_option("--pid", 137 dest="pid_fn", default="", 138 help="write the roslaunch pid to filename") 139 parser.add_option("-v", action="store_true", 140 dest="verbose", default=False, 141 help="verbose printing") 142 # 2685 - Dump parameters of launch files 143 parser.add_option("--dump-params", default=False, action="store_true", 144 dest="dump_params", 145 help="Dump parameters of all roslaunch files to stdout") 146 return parser
147
148 -def _validate_args(parser, options, args):
149 # validate args first so we don't spin up any resources 150 if options.child_name: 151 if not options.server_uri: 152 parser.error("--child option requires --server_uri to be set as well") 153 if not options.run_id: 154 parser.error("--child option requires --run_id to be set as well") 155 if options.port: 156 parser.error("port option cannot be used with roslaunch child mode") 157 if args: 158 parser.error("Input files are not allowed when run in child mode") 159 elif options.core: 160 if args: 161 parser.error("Input files are not allowed when launching core") 162 if options.run_id: 163 parser.error("--run_id should only be set for child roslaunches (-c)") 164 165 # we don't actually do anything special for core as the roscore.xml file 166 # is an implicit include for any roslaunch 167 168 elif len(args) == 0: 169 parser.error("you must specify at least one input file") 170 elif [f for f in args if not os.path.exists(f)]: 171 parser.error("The following input files do not exist: %s"%f) 172 173 if len([x for x in [options.node_list, options.find_node, options.node_args] if x]) > 1: 174 parser.error("only one of [--nodes, --find-node, --args] may be specified")
175
176 -def main(argv=sys.argv):
177 options = None 178 try: 179 import roslaunch.rlutil 180 parser = _get_optparse() 181 182 (options, args) = parser.parse_args(argv[1:]) 183 args = roslaunch.rlutil.resolve_launch_arguments(args) 184 _validate_args(parser, options, args) 185 186 # node args doesn't require any roslaunch infrastructure, so process it first 187 if options.node_args or options.node_list or options.find_node or options.dump_params: 188 if options.node_args and not args: 189 parser.error("please specify a launch file") 190 import roslaunch.node_args 191 if options.node_args: 192 roslaunch.node_args.print_node_args(options.node_args, args) 193 elif options.find_node: 194 roslaunch.node_args.print_node_filename(options.find_node, args) 195 # Dump parameters, #2685 196 elif options.dump_params: 197 roslaunch.param_dump.dump_params(args) 198 else: 199 roslaunch.node_args.print_node_list(args) 200 return 201 202 # we have to wait for the master here because we don't have the run_id yet 203 if options.wait_for_master: 204 if options.core: 205 parser.error("--wait cannot be used with roscore") 206 roslaunch.rlutil._wait_for_master() 207 208 # write the pid to a file 209 write_pid_file(options.pid_fn, options.core, options.port) 210 211 # spin up the logging infrastructure. have to wait until we can read options.run_id 212 uuid = roslaunch.rlutil.get_or_generate_uuid(options.run_id, options.wait_for_master) 213 configure_logging(uuid) 214 215 # #3088: don't check disk usage on remote machines 216 if not options.child_name: 217 # #2761 218 roslaunch.rlutil.check_log_disk_usage() 219 220 logger = logging.getLogger('roslaunch') 221 logger.info("roslaunch starting with args %s"%str(argv)) 222 logger.info("roslaunch env is %s"%os.environ) 223 224 if options.child_name: 225 logger.info('starting in child mode') 226 227 # This is a roslaunch child, spin up client server. 228 # client spins up an XML-RPC server that waits for 229 # commands and configuration from the server. 230 import roslaunch.child 231 c = roslaunch.child.ROSLaunchChild(uuid, options.child_name, options.server_uri) 232 c.run() 233 else: 234 logger.info('starting in server mode') 235 236 # #1491 change terminal name 237 roslaunch.rlutil.change_terminal_name(args, options.core) 238 239 # This is a roslaunch parent, spin up parent server and launch processes. 240 # args are the roslaunch files to load 241 import roslaunch.parent 242 try: 243 # force a port binding spec if we are running a core 244 if options.core: 245 options.port = options.port or DEFAULT_MASTER_PORT 246 p = roslaunch.parent.ROSLaunchParent(uuid, args, is_core=options.core, port=options.port, local_only=options.local_only, verbose=options.verbose, force_screen=options.force_screen) 247 p.start() 248 p.spin() 249 finally: 250 # remove the pid file 251 if options.pid_fn: 252 try: os.unlink(options.pid_fn) 253 except os.error, reason: pass 254 255 except RLException, e: 256 roslaunch.core.printerrlog(str(e)) 257 sys.exit(1) 258 except ValueError, e: 259 # TODO: need to trap better than this high-level trap 260 roslaunch.core.printerrlog(str(e)) 261 sys.exit(1) 262 except roslib.packages.InvalidROSPkgException, e: 263 roslaunch.core.printerrlog(str(e)) 264 sys.exit(1) 265 except Exception, e: 266 import traceback 267 traceback.print_exc() 268 sys.exit(1)
269 270 if __name__ == '__main__': 271 main() 272