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