1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 """
34 Implements rosmsg/rossrv command-line tools.
35
36 The code API of the rosmsg module is unstable. Much of the
37 functionality of rosmsg/rossrv is implemented using the roslib.msgs
38 and roslib.srvs libraries and can be found there instead.
39 """
40
41 import os
42 import platform
43 import sys
44 import socket
45 import threading
46 import time
47 import subprocess
48
49 import roslib
50 import roslib.genpy
51 import roslib.gentools
52 import roslib.message
53 import roslib.msgs
54 import roslib.names
55 import roslib.packages
56 import roslib.srvs
57 import rosbag
58
59 from optparse import OptionParser
62
63 import warnings
65 """This is a decorator which can be used to mark functions
66 as deprecated. It will result in a warning being emmitted
67 when the function is used."""
68 def newFunc(*args, **kwargs):
69 warnings.warn("Call to deprecated function %s." % func.__name__,
70 category=DeprecationWarning, stacklevel=2)
71 return func(*args, **kwargs)
72 newFunc.__name__ = func.__name__
73 newFunc.__doc__ = func.__doc__
74 newFunc.__dict__.update(func.__dict__)
75 return newFunc
76
78 code, msg, val = args
79 if code != 1:
80 raise ROSMsgException("remote call failed: %s"%msg)
81 return val
82
84 if os.uname()[0] in ['Darwin', 'FreeBSD']:
85 return ["find", "-E", path]
86 else:
87 return ["find", path, "-regextype", "posix-egrep"]
88
91 result = set()
92 mode_str = "srv"
93 if mode == roslib.msgs.EXT:
94 mode_str = "msg"
95
96 msg_pkg, msg_name = type_.split('/')
97
98
99 p = roslib.packages.get_pkg_dir(package)
100
101
102
103
104 if mode == roslib.msgs.EXT:
105 command = []
106 if msg_pkg == package:
107 command = make_find_command(p)
108 command += ["-regex", ".*\.(msg|srv)", "!", "-regex", ".*build.*", "!", "-regex", ".*\.svn.*", "!", "-regex", ".*~", "-exec", "grep", "-lE", "(" + type_ + "|" + msg_name + ")", "{}", ";"]
109 else:
110 command = make_find_command(p)
111 command += ["-regex", ".*\.(msg|srv)", "!", "-regex", ".*build.*", "!", "-regex", ".*\.svn.*", "!", "-regex", ".*~", "-exec", "grep", "-lE", type_, "{}", ";"]
112
113
114
115 msgfiles = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip().split()
116
117
118 for f in msgfiles:
119 if len(f.strip()) != 0:
120 result.add( f )
121
122
123
124
125 command = make_find_command(p)
126 command += ["-regex", ".*\.(cpp|h|hh|cc|hpp|c)", "!", "-regex", ".*build.*", "!", "-regex", ".*svn.*", "!", "-regex", ".*~", "-exec", "grep", "-lE", " *#include *(\"|<)" + type_ + ".h", "{}", ";"]
127
128 cppfiles = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip().split()
129
130
131 for f in cppfiles:
132 if len(f.strip()) != 0:
133 result.add( f )
134
135
136
137
138 command = make_find_command(p)
139
140
141
142 command += ["!", "-regex", ".*build.*", "!", "-regex", ".*\.svn.*", "-exec", "grep", "-IlE", "import " +msg_pkg+"\."+mode_str+"\."+ msg_name, "{}", ";"]
143
144 pyfiles = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip().split('\n')
145 for f in pyfiles:
146 if len(f.strip()) != 0:
147 result.add(f)
148
149
150 command = make_find_command(p)
151
152
153
154 command += ["!", "-regex", ".*build.*", "!", "-regex", ".*\.svn.*", "!", "-regex", ".*~", "-exec", "grep", "-IlE", " *from.*" + msg_pkg + "\."+mode_str+".*import (\*|" + msg_name +")", "{}",";"]
155
156 pyfiles = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip().split('\n')
157
158
159 for f in pyfiles:
160 if len(f.strip()) != 0:
161
162
163 command = ["grep", "-l", msg_name, f]
164
165 present = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0].strip().split('\n')
166 if len(present[0]) > 0:
167
168 result.add(f)
169
170 return list(result)
171
174 msg_pkg, msg_name = roslib.names.package_resource_name(type_)
175
176
177 if not msg_pkg:
178 print >> sys.stderr, "Please specify the package and type for [%s]"%type_
179 sys.exit(os.EX_USAGE)
180
181 print 'Files using %s:' % (type_)
182
183 deps = subprocess.Popen(["rospack", "depends-on1", msg_pkg], stdout=subprocess.PIPE).communicate()[0].strip().split()
184
185 deps.append(msg_pkg)
186
187 correct_dependencies = []
188 for d in deps:
189 files = rosmsg_users_package_search(mode, type_, d)
190 correct_dependencies.extend(files)
191
192 print "Usages directly depended upon:" + type_
193 for f in correct_dependencies:
194 print f
195
196 deps = subprocess.Popen(["rospack", "depends-on", msg_pkg], stdout=subprocess.PIPE).communicate()[0].strip().split()
197 incorrect_dependencies = []
198 for d in deps:
199 files = rosmsg_users_package_search(mode, type_, d)
200 incorrect_dependencies.extend(files)
201 print "Usages indirectly depended upon:"
202 for f in incorrect_dependencies:
203 if f not in correct_dependencies:
204 print f
205
206 -def get_srv_text(type_, raw=False):
207 """
208 Get .srv file for type_ as text
209 @param type_: service type
210 @type type_: str
211 @param raw: if True, include comments and whitespace (default False)
212 @type raw: bool
213 @return: text of .srv file
214 @rtype: str
215 @raise ROSMsgException: if type_ is unknown
216 """
217 package, base_type = roslib.names.package_resource_name(type_)
218 roslib.msgs.load_package_dependencies(package, load_recursive=True)
219 roslib.msgs.load_package(package)
220 f = roslib.srvs.srv_file(package, base_type)
221 if not os.path.isfile(f):
222 raise ROSMsgException("Unknown srv type: %s"%type_)
223 name, spec = roslib.srvs.load_from_file(f, package)
224 if raw:
225 return spec.text
226 else:
227 return str(spec.request)+'---\n'+str(spec.response)
228
229 -def get_msg_text(type_, raw=False, full_text=None):
230 """
231 Get .msg file for type_ as text
232 @param type_: message type
233 @type type_: str
234 @param raw: if True, include comments and whitespace (default False)
235 @type raw: bool
236 @param full_text: if not None, contains full text of message definition
237 @type full_text: str
238 @return: text of .msg file
239 @rtype: str
240 @raise ROSMsgException: if type_ is unknown
241 """
242 package, base_type = roslib.names.package_resource_name(type_)
243
244 if not full_text:
245 roslib.msgs.load_package_dependencies(package, load_recursive=True)
246 roslib.msgs.load_package(package)
247 try:
248 spec = roslib.msgs.get_registered(type_)
249 except KeyError:
250 raise ROSMsgException("Unknown msg type: %s"%type_)
251
252 if raw:
253 text = spec.text
254 else:
255 text = str(spec)
256 else:
257 splits = full_text.split('\n'+'='*80+'\n')
258 core_msg = splits[0]
259 deps_msgs = splits[1:]
260
261 specs = { type_: roslib.msgs.load_from_string(core_msg, package) }
262 for dep_msg in deps_msgs:
263 dep_type, dep_spec = roslib.genpy._generate_dynamic_specs(specs, dep_msg)
264 specs[dep_type] = dep_spec
265
266 for t, spec in specs.iteritems():
267 roslib.msgs.register(t, spec)
268 spec = specs[type_]
269 if raw:
270 text = spec.text
271 else:
272 text = str(spec)
273
274 return text
275
277 """
278 Prints contents of msg/srv file
279 @param mode: roslib.srvs.EXT or roslib.msgs.EXT
280 @type mode: str
281 """
282 if mode == roslib.srvs.EXT:
283 print get_srv_text(type_, raw=raw)
284 elif mode == roslib.msgs.EXT:
285 print get_msg_text(type_, raw=raw)
286 else:
287 raise ROSMsgException("invalid mode: %s"%mode)
288
290 """
291 List srvs contained in package
292 @param package: package name
293 @type package: str
294 @return: list of srvs in package
295 @rtype: [str]
296 """
297 return list_types(package, mode=roslib.srvs.EXT)
298
300 """
301 List msgs contained in package
302 @param package: package name
303 @type package: str
304 @return: list of msgs in package
305 @rtype: [str]
306 """
307 return list_types(package)
308
313
315 """
316 Lists msg/srvs contained in package
317 @param package: package name
318 @type package: str
319 @param mode: roslib.srvs.EXT or roslib.msgs.EXT. Defaults to msgs.
320 @type mode: str
321 @return: list of msgs/srv in package
322 @rtype: [str]
323 """
324 if mode == roslib.msgs.EXT:
325 return [roslib.names.resource_name(package, t) for t in roslib.msgs.list_msg_types(package, False)]
326 elif mode == roslib.srvs.EXT:
327 return [roslib.names.resource_name(package, t) for t in roslib.srvs.list_srv_types(package, False)]
328 else:
329 raise ValueError('mode')
330
332 """
333 Iterator for packages that contain messages/services
334 @param mode: roslib.msgs.EXT or roslib.srvs.EXT
335 @type mode: str
336 """
337 if mode == roslib.msgs.EXT:
338 subdir = roslib.packages.MSG_DIR
339 elif mode == roslib.srvs.EXT:
340 subdir = roslib.packages.SRV_DIR
341 else:
342 raise ValueError('mode')
343
344 pkgs = roslib.packages.list_pkgs()
345 for p in pkgs:
346 dir = roslib.packages.get_pkg_subdir(p, subdir, False)
347 if dir and os.path.isdir(dir):
348 yield p
349
352 """
353 Use list_packages
354 """
355 return list_packages(mode=mode)
356
358 """
359 List all packages that contain messages/services. This is a convenience
360 function of iterate_packages
361 @param mode: roslib.msgs.EXT or roslib.srvs.EXT. Defaults to msgs
362 @type mode: str
363 @return: list of packages that contain messages/services (depending on mode)
364 @rtype: [str]
365 """
366 return [p for p in iterate_packages(mode)]
367
371 if mode == roslib.msgs.EXT:
372 res_file = roslib.msgs.msg_file
373 else:
374 res_file = roslib.srvs.srv_file
375 for p in iterate_packages(mode):
376 if os.path.isfile(res_file(p, base_type)):
377 yield roslib.names.resource_name(p, base_type)
378
380 options, args = parser.parse_args(sys.argv[2:])
381
382 if not args:
383 arg = None
384 while not arg:
385 arg = sys.stdin.readline().strip()
386 return options, arg
387 else:
388 if len(args) > 1:
389 parser.error("you may only specify one %s"%full)
390 return options, args[0]
391
393 cmd = "ros%s"%(mode[1:])
394 parser = OptionParser(usage="usage: %s show [options] <%s>"%(cmd, full))
395 parser.add_option("-r", "--raw",
396 dest="raw", default=False,action="store_true",
397 help="show raw message text, including comments")
398 parser.add_option("-b", "--bag",
399 dest="bag", default=None,
400 help="show message from .bag file", metavar="BAGFILE")
401 options, arg = _stdin_arg(parser, full)
402 if arg.endswith(mode):
403 arg = arg[:-(len(mode))]
404
405
406 if '::' in arg:
407 parser.error(cmd+" does not understand C++-style namespaces (i.e. '::').\nPlease refer to msg/srv types as 'package_name/Type'.")
408 elif '.' in arg:
409 parser.error("invalid message type '%s'.\nPlease refer to msg/srv types as 'package_name/Type'." % arg)
410 if options.bag:
411 bag_file = options.bag
412 if not os.path.exists(bag_file):
413 raise ROSMsgException("ERROR: bag file [%s] does not exist"%bag_file)
414 for topic, msg, t in rosbag.Bag(bag_file).read_messages(raw=True):
415 datatype, _, _, _, pytype = msg
416 if datatype == arg:
417 print get_msg_text(datatype, options.raw, pytype._full_text)
418 break
419 else:
420 if '/' in arg:
421 rosmsg_debug(mode, arg, options.raw)
422 else:
423 for found in rosmsg_search(mode, arg):
424 print "[%s]:"%found
425 rosmsg_debug(mode, found, options.raw)
426
428 package, base_type = roslib.names.package_resource_name(type_)
429 roslib.msgs.load_package_dependencies(package, load_recursive=True)
430 roslib.msgs.load_package(package)
431 if mode == roslib.msgs.EXT:
432 f = roslib.msgs.msg_file(package, base_type)
433 name, spec = roslib.msgs.load_from_file(f, package)
434 else:
435 f = roslib.srvs.srv_file(package, base_type)
436 name, spec = roslib.srvs.load_from_file(f, package)
437 gendeps_dict = roslib.gentools.get_dependencies(spec, package, compute_files=False)
438 return roslib.gentools.compute_md5(gendeps_dict)
439
442 try:
443 msg_class = roslib.message.get_message_class(type_)
444 if msg_class is not None and msg_class._md5sum != gendeps_md5:
445 print >> sys.stderr, "WARN: md5sum for compiled [%s] appears to differ from %s:\n\t%s vs %s"%(type_, mode, msg_class._md5sum, gendeps_md5)
446 except ImportError: pass
447
449 parser = OptionParser(usage="usage: ros%s md5 <%s>"%(mode[1:], full))
450 options, arg = _stdin_arg(parser, full)
451
452 if '/' in arg:
453 try:
454 md5 = rosmsg_md5(mode, arg)
455 print md5
456 _rosmsg_md5_check(mode, arg, md5)
457 except IOError:
458 print >> sys.stderr, "Cannot locate [%s]"%arg
459 else:
460 matches = [m for m in rosmsg_search(mode, arg)]
461 for found in matches:
462 try:
463 md5 = rosmsg_md5(mode, found)
464 print "[%s]: %s"%(found, md5)
465 _rosmsg_md5_check(mode, found, md5)
466 except IOError:
467 print >> sys.stderr, "Cannot locate [%s]"%found
468 if not matches:
469 print >> sys.stderr, "No messages matching the name [%s]"%arg
470
472 parser = OptionParser(usage="usage: ros%s users <%s>"%(mode[1:], full))
473 options, arg = _stdin_arg(parser, full)
474 rosmsg_users(mode, arg)
475
477 parser = OptionParser(usage="usage: ros%s package <package>"%mode[1:])
478 parser.add_option("-s",
479 dest="single_line", default=False,action="store_true",
480 help="list all msgs on a single line")
481 options, arg = _stdin_arg(parser, full)
482 if options.single_line:
483 print ' '.join(list_types(arg,mode=mode))
484 else:
485 print '\n'.join(list_types(arg, mode=mode))
486
488 parser = OptionParser(usage="usage: ros%s packages"%mode[1:])
489 parser.add_option("-s",
490 dest="single_line", default=False,action="store_true",
491 help="list all packages on a single line")
492 options, args = parser.parse_args(sys.argv[2:])
493 if options.single_line:
494 print ' '.join([p for p in iterate_packages(mode)])
495 else:
496 print '\n'.join([p for p in iterate_packages(mode)])
497
499 """
500 @param cmd: command name
501 @type cmd: str
502 @return: usage text for cmd
503 @rtype: str
504 """
505 return """Commands:
506 \t%(cmd)s show\tShow message description
507 \t%(cmd)s users\tFind files that use message
508 \t%(cmd)s md5\tDisplay message md5sum
509 \t%(cmd)s package\tList messages in a package
510 \t%(cmd)s packages\tList packages that contain messages
511
512 Type %(cmd)s <command> -h for more detailed usage
513 """%locals()
514
515 -def rosmsgmain(mode=roslib.msgs.EXT):
516 """
517 Main entry point for command-line tools (rosmsg/rossrv).
518
519 rosmsg can interact with either ros messages or ros services. The mode
520 param indicates which
521 @param mode: roslib.msgs.EXT or roslib.srvs.EXT
522 @type mode: str
523 """
524 if len(sys.argv) == 1:
525 print fullusage('ros'+mode[1:])
526 sys.exit(0)
527 if mode == roslib.msgs.EXT:
528 ext, full = mode, "message type"
529 else:
530 ext, full = mode, "service type"
531
532 try:
533 command = sys.argv[1]
534 if command == 'users':
535 rosmsg_cmd_users(ext, full)
536 elif command == 'show':
537 rosmsg_cmd_show(ext, full)
538 elif command == 'package':
539 rosmsg_cmd_package(ext, full)
540 elif command == 'packages':
541 rosmsg_cmd_packages(ext, full)
542 elif command == 'md5':
543 rosmsg_cmd_md5(ext, full)
544 else:
545 print fullusage('ros'+mode[1:])
546 sys.exit(0)
547 except KeyError, e:
548 print >> sys.stderr, "Unknown message type: %s"%e
549 sys.exit(os.EX_USAGE)
550 except roslib.packages.InvalidROSPkgException, e:
551 print >> sys.stderr, "Invalid package: '%s'"%e
552 sys.exit(os.EX_USAGE)
553 except ValueError, e:
554 print >> sys.stderr, "Invalid type: '%s'"%e
555 sys.exit(os.EX_USAGE)
556 except ROSMsgException, e:
557 print >> sys.stderr, str(e)
558 sys.exit(1)
559 except KeyboardInterrupt:
560 pass
561