Package rosmsg
[frames] | no frames]

Source Code for Package rosmsg

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, 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  """ 
 34  Implements rosmsg/rossrv command-line tools. 
 35   
 36  The code API of the rosmsg module is unstable.  
 37  """ 
 38   
 39  from __future__ import print_function 
 40   
 41  import collections 
 42  import inspect 
 43  import os 
 44  import sys 
 45  import yaml 
 46   
 47  import rospkg 
 48  import genmsg 
 49   
 50  import roslib.message 
 51  import rosbag 
 52   
 53  from optparse import OptionParser 
 54   
 55  MODE_MSG = '.msg' 
 56  MODE_SRV = '.srv' 
 57   
58 -class ROSMsgException(Exception): pass
59 -class RosMsgProtoException(Exception): pass
60 -class RosMsgProtoArgsException(Exception): pass
61 62 # If flowtype chosen is default, instead use flow-style 63 # False except if meeting objects or arrays with more than 64 # this size of sub-elements 65 MAX_DEFAULT_NON_FLOW_ITEMS = 4 66 67 ## copied from the web, recipe for ordered yaml output ######
68 -def construct_ordered_mapping(self, node, deep=False):
69 if not isinstance(node, yaml.MappingNode): 70 raise yaml.constructor.ConstructorError(None, None, 71 "expected a mapping node, but found %s" % node.id, 72 node.start_mark) 73 mapping = collections.OrderedDict() 74 for key_node, value_node in node.value: 75 key = self.construct_object(key_node, deep=deep) 76 if not isinstance(key, collections.Hashable): 77 raise yaml.constructor.ConstructorError("while constructing a mapping", node.start_mark, 78 "found unhashable key", key_node.start_mark) 79 value = self.construct_object(value_node, deep=deep) 80 mapping[key] = value 81 return mapping
82
83 -def construct_yaml_map_with_ordered_dict(self, node):
84 data = collections.OrderedDict() 85 yield data 86 value = self.construct_mapping(node) 87 data.update(value)
88
89 -def represent_ordered_mapping(self, tag, mapping, flow_style=None):
90 value = [] 91 node = yaml.MappingNode(tag, value, flow_style=flow_style) 92 if self.alias_key is not None: 93 self.represented_objects[self.alias_key] = node 94 best_style = True 95 if hasattr(mapping, 'items'): 96 mapping = list(mapping.items()) 97 for item_key, item_value in mapping: 98 node_key = self.represent_data(item_key) 99 node_value = self.represent_data(item_value) 100 if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style): 101 best_style = False 102 if not (isinstance(node_value, yaml.ScalarNode) and not node_value.style): 103 best_style = False 104 value.append((node_key, node_value)) 105 if flow_style is None: 106 if self.default_flow_style is not None: 107 node.flow_style = self.default_flow_style 108 else: 109 node.flow_style = best_style 110 return node
111 112 ## end recipe for ordered yaml output ###### 113 114
115 -def get_array_type_instance(field_type, default_package = None):
116 """ 117 returns a single instance of field_type, where field_type can be a 118 message or ros primitive or an flexible size array. 119 """ 120 field_type = field_type.strip().rstrip("[]") 121 if field_type == "empty": 122 return None 123 if not "/" in field_type: 124 # is either built-in, Header, or in same package 125 # it seems built-in types get a priority 126 if field_type in ['byte', 'int8', 'int16', 'int32', 'int64',\ 127 'char', 'uint8', 'uint16', 'uint32', 'uint64']: 128 return 0 129 elif field_type in ['float32', 'float64']: 130 return 0 131 elif field_type in ['string']: 132 return "" 133 elif field_type == 'bool': 134 return False 135 elif field_type == 'time': 136 field_type = "std_msgs/Time" 137 elif field_type == 'duration': 138 field_type = "std_msgs/Duration" 139 elif field_type == 'Header': 140 field_type = "std_msgs/Header" 141 else: 142 if default_package is None: 143 return None 144 field_type = default_package + "/" + field_type 145 msg_class = roslib.message.get_message_class(field_type) 146 if (msg_class == None): 147 # not important enough to raise exception? 148 return None 149 instance = msg_class() 150 return instance
151
152 -def get_yaml_for_msg(msg, prefix='', time_offset=None, current_time=None, field_filter=None, flow_style_ = None, fill_arrays_ = False):
153 """ 154 Builds a YAML string of message. 155 @param msg: A object, dict or array 156 @param flow_style_: if True, produces one line with brackets, if false uses multiple lines with indentation, if None uses both using heuristics 157 @param prefix: prefixes all lines with this string 158 @param fill_arrays_: if True, for all flexible size arrays an element will be generated 159 @param current_time: currently not used. Only provided for API compatibility. current_time passes in the current time with respect to the message. 160 @type current_time: Time 161 @param field_filter: filter the fields that are strified for Messages. 162 @type field_filter: fn(Message)->iter(str) 163 @type flow_style_: bool 164 @return: a string 165 """ 166 def object_representer(dumper, obj): 167 ndict = collections.OrderedDict() 168 index = 0 169 # allow caller to select which fields of message are strified 170 if field_filter != None: 171 fields = list(field_filter(obj)) 172 else: 173 fields = obj.__slots__ 174 for key in fields: 175 if not key.startswith('_'): 176 val = getattr(obj, key) 177 if type(val) == list and len(val) > MAX_DEFAULT_NON_FLOW_ITEMS: 178 dumper.default_flow_style = flow_style_ 179 if time_offset is not None and isinstance(val, Time): 180 ndict[key] = val-time_offset 181 # create initial array element (e.g. for code completion) 182 elif fill_arrays_ == True and val == []: 183 message_type = obj._slot_types[index] 184 if (obj._type != None) and "/" in obj._type: 185 def_pack = obj._type.split("/")[0] 186 instance = get_array_type_instance(message_type, default_package = def_pack) 187 if instance == None: 188 # not important enough to raise exception? 189 ndict[key] = val 190 else: 191 ndict[key] = [instance] 192 elif not inspect.ismethod(val) and not inspect.isfunction(val): 193 ndict[key] = val 194 index += 1 195 # as a hack, we improve the heuristics of pyyaml and say with less than 5 objects, no need for brackets 196 if len(ndict) > MAX_DEFAULT_NON_FLOW_ITEMS: 197 dumper.default_flow_style = flow_style_ 198 return dumper.represent_dict(ndict)
199 yaml.representer.SafeRepresenter.add_representer(None, object_representer) 200 201 # we force False over None here and set the style in dumper, to 202 # avoid unecessary outer brackets pyyaml chooses e.g. to 203 # represent msg Int32 as "{data: 0}" 204 initial_flow_style = False 205 if flow_style_ == True: 206 initial_flow_style = True 207 208 # need to set default flow style True for bash prototype 209 # means will generate one line with [] and {} brackets 210 # bash needs bracket notation for rostopic pub 211 txt = yaml.safe_dump(msg, 212 # None, True, False (None chooses a compromise) 213 default_flow_style = initial_flow_style, 214 # Can be None, '', '\'', '"', '|', '>'. 215 default_style = '', 216 #indent=2, #>=2, indentation depth 217 #line_break=?, 218 #allow_unicode=?, 219 #if true writes plenty of tags 220 #canonical = False, 221 #version={}?, 222 #width=40, 223 #encoding=?, 224 #tags={}?, 225 # when True, produces --- at start 226 #explicit_start=False, 227 # when True, produces ... at end 228 #explicit_end=False 229 ) 230 if prefix != None and prefix != '': 231 result = prefix + ("\n"+prefix).join(txt.splitlines()) 232 else: 233 result = txt.rstrip('\n') 234 return result 235 236
237 -def create_names_filter(names):
238 """ 239 returns a function to use as filter that returns all objects slots except those with names in list. 240 """ 241 return lambda obj : filter(lambda slotname : not slotname in names, obj.__slots__)
242 243
244 -def init_rosmsg_proto():
245 if "OrderedDict" in collections.__dict__: 246 yaml.constructor.BaseConstructor.construct_mapping = construct_ordered_mapping 247 yaml.constructor.Constructor.add_constructor( 248 'tag:yaml.org,2002:map', 249 construct_yaml_map_with_ordered_dict) 250 251 yaml.representer.BaseRepresenter.represent_mapping = represent_ordered_mapping 252 yaml.representer.Representer.add_representer(collections.OrderedDict, 253 yaml.representer.SafeRepresenter.represent_dict)
254
255 -def rosmsg_cmd_prototype(args):
256 init_rosmsg_proto() 257 parser = OptionParser(usage="usage: rosmsgproto msg/srv [options]", 258 description="Produces output or a msg or service request, intended for tab completion support.") 259 parser.add_option("-f","--flow_style", 260 dest="flow_style", type="int", default=None, action="store", 261 help="if 1 always use brackets, if 0 never use brackets. Default is a heuristic mix.") 262 parser.add_option("-e","--empty-arrays", 263 dest="empty_arrays", default=False, action="store_true", 264 help="if true flexible size arrays are not filled with default instance") 265 parser.add_option("-s","--silent", 266 dest="silent", default=False, action="store_true", 267 help="if true supresses all error messages") 268 parser.add_option("-p", "--prefix", metavar="prefix", default="", 269 help="prefix to print before each line, can be used for indent") 270 parser.add_option("-H","--no-hyphens", 271 dest="no_hyphens", default="", action="store_true", 272 help="if true output has no outer hyphens") 273 parser.add_option("-x", "--exclude-slots", metavar="exclude_slots", default="", 274 help="comma separated list of slot names not to print") 275 276 options, args = parser.parse_args(args) 277 278 try: 279 if len(args) < 2: 280 raise RosMsgProtoArgsException("Insufficient arguments") 281 mode = ".%s"%args[0] 282 message_type=args[1] 283 field_filter = None 284 if options.exclude_slots != None and options.exclude_slots.strip() != "": 285 field_filter = create_names_filter(options.exclude_slots.split(',')) 286 287 # possible extentions: options for 288 # - target language 289 # - initial values for standard types 290 # - get partial message (subtree) 291 292 # try to catch the user specifying code-style types and error 293 if '::' in message_type: 294 if not options.silent: 295 parser.error("rosmsgproto does not understand C++-style namespaces (i.e. '::').\nPlease refer to msg/srv types as 'package_name/Type'.") 296 elif '.' in message_type: 297 if not options.silent: 298 parser.error("invalid message type '%s'.\nPlease refer to msg/srv types as 'package_name/Type'." % message_type) 299 if not '/' in message_type: 300 # if only one such msg or srv exists, use it 301 results = [] 302 for found in rosmsg_search(rospkg.RosPack(), mode, message_type): 303 results.append(found) 304 if len(results) > 1: 305 raise RosMsgProtoException("Ambiguous message name %s"%message_type) 306 elif len(results) < 1: 307 raise RosMsgProtoException("Unknown message name %s"%message_type) 308 else: 309 message_type=results[0] 310 311 if mode == MODE_SRV: 312 msg_class = roslib.message.get_service_class(message_type) 313 if (msg_class == None): 314 raise RosMsgProtoException("Unknown service class: %s"%message_type) 315 instance = msg_class()._request_class() 316 elif mode == MODE_MSG: 317 msg_class = roslib.message.get_message_class(message_type) 318 if (msg_class == None): 319 raise RosMsgProtoException("Unknown message class: %s"%message_type) 320 instance = msg_class() 321 else: 322 raise RosMsgProtoException("Invalid mode: %s"%mode) 323 txt = get_yaml_for_msg(instance, 324 prefix = options.prefix, 325 flow_style_ = options.flow_style, 326 fill_arrays_ = not options.empty_arrays, 327 field_filter = field_filter) 328 329 if options.no_hyphens == True: 330 return txt 331 else: 332 return '"' + txt + '"' 333 334 except KeyError as e: 335 if not options.silent: 336 sys.stderr.write("Unknown message type: %s"%e, file=sys.stderr) 337 sys.exit(getattr(os, 'EX_USAGE', 1)) 338 # except rospkg.InvalidROSPkgException as e: 339 # if not options.silent: 340 # print(file=sys.stderr, "Invalid package: '%s'"%e) 341 # sys.exit(getattr(os, 'EX_USAGE', 1)) 342 except ValueError, e: 343 if not options.silent: 344 sys.stderr.write("Invalid type: '%s'"%e) 345 sys.exit(getattr(os, 'EX_USAGE', 1)) 346 except RosMsgProtoException as e: 347 if not options.silent: 348 sys.stderr.write(str(e)) 349 sys.exit(1) 350 except RosMsgProtoArgsException as e: 351 if not options.silent: 352 sys.stderr.write("%s"%e) 353 sys.exit(getattr(os, 'EX_USAGE', 1)) 354 except KeyboardInterrupt: 355 pass
356 357 #### Start of rosmsg #### 358 359 try: 360 from cStringIO import StringIO # Python 2.x 361 except ImportError: 362 from io import StringIO # Python 3.x
363 -def spec_to_str(msg_context, spec, buff=None, indent=''):
364 """ 365 Convert spec into a string representation. Helper routine for MsgSpec. 366 :param indent: internal use only, ``str`` 367 :param buff: internal use only, ``StringIO`` 368 :returns: string representation of spec, ``str`` 369 """ 370 if buff is None: 371 buff = StringIO() 372 for c in spec.constants: 373 buff.write("%s%s %s=%s\n"%(indent, c.type, c.name, c.val_text)) 374 for type_, name in zip(spec.types, spec.names): 375 buff.write("%s%s %s\n"%(indent, type_, name)) 376 base_type = genmsg.msgs.bare_msg_type(type_) 377 if not base_type in genmsg.msgs.BUILTIN_TYPES: 378 subspec = msg_context.get_registered(base_type) 379 spec_to_str(msg_context, subspec, buff, indent + ' ') 380 return buff.getvalue()
381
382 -def get_srv_text(type_, raw=False, rospack=None):
383 """ 384 Get .srv file for type_ as text 385 :param type_: service type, ``str`` 386 :param raw: if True, include comments and whitespace (default False), ``bool`` 387 :returns: text of .srv file, ``str`` 388 @raise ROSMsgException: if type_ is unknown 389 """ 390 if rospack is None: 391 rospack = rospkg.RosPack() 392 srv_search_path = {} 393 msg_search_path = {} 394 for p in rospack.list(): 395 path = rospack.get_path(p) 396 msg_search_path[p] = [os.path.join(path, 'msg')] 397 srv_search_path[p] = [os.path.join(path, 'srv')] 398 399 #TODO: cache context somewhere 400 context = genmsg.MsgContext.create_default() 401 try: 402 spec = genmsg.load_srv_by_type(context, type_, srv_search_path) 403 genmsg.load_depends(context, spec, msg_search_path) 404 except Exception as e: 405 raise ROSMsgException("Unknown srv type [%s]: %s"%(type_, e)) 406 407 if raw: 408 return spec.text 409 else: 410 return spec_to_str(context, spec.request)+'---\n'+spec_to_str(context, spec.response)
411
412 -def get_msg_text(type_, raw=False, rospack=None):
413 """ 414 Get .msg file for type_ as text 415 :param type_: message type, ``str`` 416 :param raw: if True, include comments and whitespace (default False), ``bool`` 417 :returns: text of .msg file, ``str`` 418 :raises :exc:`ROSMsgException` If type_ is unknown 419 """ 420 if rospack is None: 421 rospack = rospkg.RosPack() 422 search_path = {} 423 for p in rospack.list(): 424 search_path[p] = [os.path.join(rospack.get_path(p), 'msg')] 425 426 context = genmsg.MsgContext.create_default() 427 try: 428 spec = genmsg.load_msg_by_type(context, type_, search_path) 429 genmsg.load_depends(context, spec, search_path) 430 except Exception as e: 431 raise ROSMsgException("Unable to load msg [%s]: %s"%(type_, e)) 432 433 if raw: 434 return spec.text 435 else: 436 return spec_to_str(context, spec)
437
438 -def rosmsg_debug(rospack, mode, type_, raw=False):
439 """ 440 Prints contents of msg/srv file 441 :param mode: MODE_MSG or MODE_SRV, ``str`` 442 """ 443 if mode == MODE_SRV: 444 print(get_srv_text(type_, raw=raw, rospack=rospack)) 445 elif mode == MODE_MSG: 446 print(get_msg_text(type_, raw=raw, rospack=rospack)) 447 else: 448 raise ROSMsgException("Invalid mode for debug: %s"%mode)
449
450 -def list_srvs(package):
451 """ 452 List srvs contained in package 453 :param package: package name, ``str`` 454 :returns: list of srvs in package, ``[str]`` 455 """ 456 return list_types(package, mode=MODE_SRV)
457
458 -def list_msgs(package):
459 """ 460 List msgs contained in package 461 :param package: package name, ``str`` 462 :returns: list of msgs in package, ``[str]`` 463 """ 464 return list_types(package)
465
466 -def list_types(package, mode=MODE_MSG):
467 """ 468 Lists msg/srvs contained in package 469 :param package: package name, ``str`` 470 :param mode: MODE_MSG or MODE_SRV. Defaults to msgs, ``str`` 471 :returns: list of msgs/srv in package, ``[str]`` 472 """ 473 rospack = rospkg.RosPack() 474 if mode == MODE_MSG: 475 subdir = 'msg' 476 elif mode == MODE_SRV: 477 subdir = 'srv' 478 else: 479 raise ValueError('Unknown mode for list_types: %s'%mode) 480 481 path = os.path.join(rospack.get_path(package), subdir) 482 483 return [genmsg.resource_name(package, t) for t in _list_types(path, subdir, mode)]
484
485 -def _msg_filter(ext):
486 def mfilter(f): 487 """ 488 Predicate for filtering directory list. matches message files 489 :param f: filename, ``str`` 490 """ 491 return os.path.isfile(f) and f.endswith(ext)
492 return mfilter 493
494 -def _list_types(path, subdir, ext):
495 """ 496 List all messages in the specified package 497 :param package str: name of package to search 498 :param include_depends bool: if True, will also list messages in package dependencies 499 :returns [str]: message type names 500 """ 501 types = _list_resources(path, _msg_filter(ext)) 502 result = [x[:-len(ext)] for x in types] 503 result.sort() 504 return result
505
506 -def _list_resources(path, rfilter=os.path.isfile):
507 """ 508 List resources in a package directory within a particular 509 subdirectory. This is useful for listing messages, services, etc... 510 :param rfilter: resource filter function that returns true if filename is the desired resource type, ``fn(filename)->bool`` 511 """ 512 resources = [] 513 if os.path.isdir(path): 514 resources = [f for f in os.listdir(path) if rfilter(os.path.join(path, f))] 515 else: 516 resources = [] 517 return resources
518
519 -def iterate_packages(rospack, mode):
520 """ 521 Iterator for packages that contain messages/services 522 :param mode: .msg or .srv, ``str`` 523 """ 524 if mode == MODE_MSG: 525 subdir = 'msg' 526 elif mode == MODE_SRV: 527 subdir = 'srv' 528 else: 529 raise ValueError('Unknown mode for iterate_packages: %s'%mode) 530 531 pkgs = rospack.list() 532 for p in pkgs: 533 d = os.path.join(rospack.get_path(p), subdir) 534 if os.path.isdir(d): 535 yield p, d
536
537 -def rosmsg_search(rospack, mode, base_type):
538 """ 539 Iterator for all packages that contain a message matching base_type 540 541 :param base_type: message base type to match, e.g. 'String' would match std_msgs/String, ``str`` 542 """ 543 for p, path in iterate_packages(rospack, mode): 544 if os.path.isfile(os.path.join(path, "%s%s"%(base_type, mode))): 545 yield genmsg.resource_name(p, base_type)
546
547 -def _stdin_arg(parser, full):
548 options, args = parser.parse_args(sys.argv[2:]) 549 # read in args from stdin pipe if not present 550 if not args: 551 arg = None 552 while not arg: 553 arg = sys.stdin.readline().strip() 554 return options, arg 555 else: 556 if len(args) > 1: 557 parser.error("you may only specify one %s"%full) 558 return options, args[0]
559
560 -def rosmsg_cmd_show(mode, full):
561 cmd = "ros%s"%(mode[1:]) 562 parser = OptionParser(usage="usage: %s show [options] <%s>"%(cmd, full)) 563 parser.add_option("-r", "--raw", 564 dest="raw", default=False,action="store_true", 565 help="show raw message text, including comments") 566 parser.add_option("-b", "--bag", 567 dest="bag", default=None, 568 help="show message from .bag file", metavar="BAGFILE") 569 options, arg = _stdin_arg(parser, full) 570 if arg.endswith(mode): 571 arg = arg[:-(len(mode))] 572 573 # try to catch the user specifying code-style types and error 574 if '::' in arg: 575 parser.error(cmd+" does not understand C++-style namespaces (i.e. '::').\nPlease refer to msg/srv types as 'package_name/Type'.") 576 elif '.' in arg: 577 parser.error("invalid message type '%s'.\nPlease refer to msg/srv types as 'package_name/Type'." % arg) 578 if options.bag: 579 bag_file = options.bag 580 if not os.path.exists(bag_file): 581 raise ROSMsgException("ERROR: bag file [%s] does not exist"%bag_file) 582 for topic, msg, t in rosbag.Bag(bag_file).read_messages(raw=True): 583 datatype, _, _, _, pytype = msg 584 if datatype == arg: 585 print(get_msg_text(datatype, options.raw, pytype._full_text)) 586 break 587 else: 588 rospack = rospkg.RosPack() 589 if '/' in arg: #package specified 590 rosmsg_debug(rospack, mode, arg, options.raw) 591 else: 592 for found in rosmsg_search(rospack, mode, arg): 593 print("[%s]:"%found) 594 rosmsg_debug(rospack, mode, found, options.raw)
595
596 -def rosmsg_md5(mode, type_):
597 try: 598 if mode == MODE_MSG: 599 msg_class = roslib.message.get_message_class(type_) 600 else: 601 msg_class = roslib.message.get_service_class(type_) 602 except ImportError: 603 raise IOError("cannot load [%s]"%(type_)) 604 if msg_class is not None: 605 return msg_class._md5sum 606 else: 607 raise IOError("cannot load [%s]"%(type_))
608
609 -def rosmsg_cmd_md5(mode, full):
610 parser = OptionParser(usage="usage: ros%s md5 <%s>"%(mode[1:], full)) 611 options, arg = _stdin_arg(parser, full) 612 613 if '/' in arg: #package specified 614 try: 615 md5 = rosmsg_md5(mode, arg) 616 print(md5) 617 except IOError: 618 print("Cannot locate [%s]"%arg, file=sys.stderr) 619 else: 620 rospack = rospkg.RosPack() 621 matches = [m for m in rosmsg_search(rospack, mode, arg)] 622 for found in matches: 623 try: 624 md5 = rosmsg_md5(mode, found) 625 print("[%s]: %s"%(found, md5)) 626 except IOError: 627 print("Cannot locate [%s]"%found, file=sys.stderr) 628 if not matches: 629 print("No messages matching the name [%s]"%arg, file=sys.stderr)
630
631 -def rosmsg_cmd_package(mode, full):
632 parser = OptionParser(usage="usage: ros%s package <package>"%mode[1:]) 633 parser.add_option("-s", 634 dest="single_line", default=False,action="store_true", 635 help="list all msgs on a single line") 636 options, arg = _stdin_arg(parser, full) 637 joinstring='\n' 638 if options.single_line: 639 joinstring=' ' 640 print(joinstring.join(list_types(arg, mode=mode)))
641
642 -def rosmsg_cmd_packages(mode, full, argv=None):
643 if argv is None: 644 argv = sys.argv[1:] 645 parser = OptionParser(usage="usage: ros%s packages"%mode[1:]) 646 parser.add_option("-s", 647 dest="single_line", default=False,action="store_true", 648 help="list all packages on a single line") 649 options, args = parser.parse_args(argv[1:]) 650 rospack = rospkg.RosPack() 651 joinstring='\n' 652 if options.single_line: 653 joinstring=' ' 654 p1 = [p for p, _ in iterate_packages(rospack, mode)] 655 p1.sort() 656 print(joinstring.join(p1))
657
658 -def rosmsg_cmd_list(mode, full, argv=None):
659 if argv is None: 660 argv = sys.argv[1:] 661 parser = OptionParser(usage="usage: ros%s list"%mode[1:]) 662 options, args = parser.parse_args(argv[1:]) 663 if mode == MODE_MSG: 664 subdir = 'msg' 665 elif mode == MODE_SRV: 666 subdir = 'srv' 667 else: 668 raise ValueError('Unknown mode for iterate_packages: %s'%mode) 669 rospack = rospkg.RosPack() 670 packs = sorted([x for x in iterate_packages(rospack, mode)]) 671 for (p, direc) in packs: 672 for file in _list_types(direc, subdir, mode): 673 print( "%s/%s"%(p, file))
674 675
676 -def fullusage(cmd):
677 """ 678 :param cmd: command name, ``str`` 679 :returns: usage text for cmd, ``str`` 680 """ 681 return """rosmsg is a command-line tool for displaying information about ROS Message types. 682 683 Commands: 684 \t%(cmd)s show\tShow message description 685 \t%(cmd)s list\tList all messages 686 \t%(cmd)s md5\tDisplay message md5sum 687 \t%(cmd)s package\tList messages in a package 688 \t%(cmd)s packages\tList packages that contain messages 689 690 Type %(cmd)s <command> -h for more detailed usage 691 """%locals()
692
693 -def rosmsgmain(mode=MODE_MSG):
694 """ 695 Main entry point for command-line tools (rosmsg/rossrv). 696 697 rosmsg can interact with either ros messages or ros services. The mode 698 param indicates which 699 :param mode: MODE_MSG or MODE_SRV, ``str`` 700 """ 701 try: 702 if mode == MODE_MSG: 703 ext, full = mode, "message type" 704 elif mode == MODE_SRV: 705 ext, full = mode, "service type" 706 else: 707 raise ROSMsgException("Invalid mode: %s"%mode) 708 if len(sys.argv) == 1: 709 print(fullusage('ros'+mode[1:])) 710 sys.exit(0) 711 712 command = sys.argv[1] 713 if command == 'show': 714 rosmsg_cmd_show(ext, full) 715 elif command == 'package': 716 rosmsg_cmd_package(ext, full) 717 elif command == 'packages': 718 rosmsg_cmd_packages(ext, full) 719 elif command == 'list': 720 rosmsg_cmd_list(ext, full) 721 elif command == 'md5': 722 rosmsg_cmd_md5(ext, full) 723 elif command == '--help': 724 print(fullusage('ros'+mode[1:])) 725 sys.exit(0) 726 else: 727 print(fullusage('ros'+mode[1:])) 728 sys.exit(getattr(os, 'EX_USAGE', 1)) 729 except KeyError as e: 730 print("Unknown message type: %s"%e, file=sys.stderr) 731 sys.exit(getattr(os, 'EX_USAGE', 1)) 732 except rospkg.ResourceNotFound as e: 733 print("Invalid package: %s"%e, file=sys.stderr) 734 sys.exit(getattr(os, 'EX_USAGE', 1)) 735 except ValueError as e: 736 print("Invalid type: '%s'"%e, file=sys.stderr) 737 sys.exit(getattr(os, 'EX_USAGE', 1)) 738 except ROSMsgException as e: 739 print(str(e), file=sys.stderr) 740 sys.exit(1) 741 except KeyboardInterrupt: 742 pass
743