genmsg_lisp.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2009, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Willow Garage, Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 #
34 
35 ## ROS message source code generation for Lisp
36 ##
37 ## Converts ROS .msg and .srv files in a package into Lisp source code
38 
39 ## t0: needed for script to work
40 ## t1: for reference; remove once running
41 ## t2: can be changed once we remove strict diff-compatibility requirement with old version of genmsg_lisp
42 
43 import sys
44 import os
45 import traceback
46 import re
47 
48 import roslib.msgs
49 import roslib.srvs
50 import roslib.packages
51 import roslib.gentools
52 from roslib.msgs import MsgSpec
53 from roslib.srvs import SrvSpec
54 
55 try:
56  from cStringIO import StringIO #Python 2.x
57 except ImportError:
58  from io import StringIO #Python 3.x
59 
60 ############################################################
61 # Built in types
62 ############################################################
63 
64 def is_fixnum(t):
65  return t in ['int8', 'uint8', 'int16', 'uint16']
66 
67 def is_integer(t):
68  return is_fixnum(t) or t in ['byte', 'char', 'int32', 'uint32', 'int64', 'uint64'] #t2 byte, char can be fixnum
69 
71  return t in ['int8', 'int16', 'int32', 'int64']
72 
74  return t in ['uint8', 'uint16', 'uint32', 'uint64']
75 
76 def is_bool(t):
77  return t == 'bool'
78 
79 def is_string(t):
80  return t == 'string'
81 
82 def is_float(t):
83  return t in ['float16', 'float32', 'float64']
84 
85 def is_time(t):
86  return t in ['time', 'duration']
87 
88 def field_type(f):
89  if f.is_builtin:
90  elt_type = lisp_type(f.base_type)
91  else:
92  elt_type = msg_type(f)
93  if f.is_array:
94  return '(cl:vector %s)'%elt_type
95  else:
96  return elt_type
97 
99  if f.base_type == 'Header':
100  return ('std_msgs', 'Header')
101  else:
102  return f.base_type.split('/')
103 
104 # t2 no need for is_array
105 def msg_type(f):
106  (pkg, msg) = parse_msg_type(f)
107  return '%s-msg:%s'%(pkg, msg)
108 
109 def lisp_type(t):
110  if is_fixnum(t):
111  return 'cl:fixnum'
112  elif is_integer(t):
113  return 'cl:integer'
114  elif is_bool(t):
115  return 'cl:boolean'
116  elif is_float(t):
117  return 'cl:float'
118  elif is_time(t):
119  return 'cl:real'
120  elif is_string(t):
121  return 'cl:string'
122  else:
123  raise ValueError('%s is not a recognized primitive type'%t)
124 
126  if f.is_builtin:
127  initform = lisp_initform(f.base_type)
128  elt_type = lisp_type(f.base_type)
129  else:
130  initform = '(cl:make-instance \'%s)'%msg_type(f)
131  elt_type = msg_type(f)
132  if f.is_array:
133  len = f.array_len or 0
134  return '(cl:make-array %s :element-type \'%s :initial-element %s)'%(len, elt_type, initform)
135  else:
136  return initform
137 
139  if is_integer(t):
140  return '0'
141  elif is_bool(t):
142  return 'cl:nil'
143  elif is_float(t):
144  return '0.0'
145  elif is_time(t):
146  return 0
147  elif is_string(t):
148  return '\"\"'
149  else:
150  raise ValueError('%s is not a recognized primitive type'%t)
151 
152 NUM_BYTES = {'int8': 1, 'int16': 2, 'int32': 4, 'int64': 8,
153  'uint8': 1, 'uint16': 2, 'uint32': 4, 'uint64': 8}
154 
155 
156 
157 ############################################################
158 # Indented writer
159 ############################################################
160 
162 
163  def __init__(self, s):
164  self.str = s
165  self.indentation = 0
166  self.block_indent = False
167 
168  def write(self, s, indent=True, newline=True):
169  if not indent:
170  newline = False
171  if self.block_indent:
172  self.block_indent = False
173  else:
174  if newline:
175  self.str.write('\n')
176  if indent:
177  for i in range(self.indentation):
178  self.str.write(' ')
179  self.str.write(s)
180 
181  def newline(self):
182  self.str.write('\n')
183 
184  def inc_indent(self, inc=2):
185  self.indentation += inc
186 
187  def dec_indent(self, dec=2):
188  self.indentation -= dec
189 
190  def reset_indent(self):
191  self.indentation = 0
192 
193  def block_next_indent(self):
194  self.block_indent = True
195 
196 class Indent():
197 
198  def __init__(self, w, inc=2, indent_first=True):
199  self.writer = w
200  self.inc = inc
201  self.indent_first = indent_first
202 
203  def __enter__(self):
204  self.writer.inc_indent(self.inc)
205  if not self.indent_first:
206  self.writer.block_next_indent()
207 
208  def __exit__(self, type, val, traceback):
209  self.writer.dec_indent(self.inc)
210 
211 
212 
213 def write_begin(s, spec, path, is_service=False):
214  "Writes the beginning of the file: a comment saying it's auto-generated and the in-package form"
215 
216  s.write('; Auto-generated. Do not edit!\n\n\n', newline=False)
217  suffix = 'srv' if is_service else 'msg'
218  s.write('(cl:in-package %s-%s)\n\n\n'%(spec.package, suffix), newline=False)
219 
220 def write_html_include(s, spec, is_srv=False):
221 
222  s.write(';//! \\htmlinclude %s.msg.html\n'%spec.actual_name, newline=False) # t2
223 
224 def write_slot_definition(s, field):
225  "Write the definition of a slot corresponding to a single message field"
226 
227  s.write('(%s'%field.name)
228  with Indent(s, 1):
229  s.write(':reader %s'%field.name)
230  s.write(':initarg :%s'%field.name)
231  s.write(':type %s'%field_type(field))
232  i = 0 if field.is_array else 1 # t2
233  with Indent(s, i):
234  s.write(':initform %s)'%field_initform(field))
235 
237  suffix = 'srv' if spec.component_type == 'service' else 'msg'
238  for field in spec.parsed_fields():
239  s.newline()
240  s.write('(cl:ensure-generic-function \'%s-val :lambda-list \'(m))' % field.name)
241  s.write('(cl:defmethod %s-val ((m %s))'%(field.name, message_class(spec)))
242  with Indent(s):
243  s.write('(roslisp-msg-protocol:msg-deprecation-warning "Using old-style slot reader %s-%s:%s-val is deprecated. Use %s-%s:%s instead.")'%(spec.package, suffix, field.name, spec.package, suffix, field.name))
244  s.write('(%s m))'%field.name)
245 
246 
247 
248 def write_defclass(s, spec):
249  "Writes the defclass that defines the message type"
250  cl = message_class(spec)
251  new_cl = new_message_class(spec)
252  suffix = 'srv' if spec.component_type == 'service' else 'msg'
253  s.write('(cl:defclass %s (roslisp-msg-protocol:ros-message)'%cl)
254  with Indent(s):
255  s.write('(')
256  with Indent(s, inc=1, indent_first=False):
257  for field in spec.parsed_fields():
258  write_slot_definition(s, field)
259  s.write(')', indent=False)
260  s.write(')')
261  s.newline()
262  s.write('(cl:defclass %s (%s)'%(new_cl, cl))
263  with Indent(s):
264  s.write('())')
265  s.newline()
266  s.write('(cl:defmethod cl:initialize-instance :after ((m %s) cl:&rest args)'%cl)
267  with Indent(s):
268  s.write('(cl:declare (cl:ignorable args))')
269  s.write('(cl:unless (cl:typep m \'%s)'%new_cl)
270  with Indent(s):
271  s.write('(roslisp-msg-protocol:msg-deprecation-warning "using old message class name %s-%s:%s is deprecated: use %s-%s:%s instead.")))'%(spec.package, suffix, cl, spec.package, suffix, new_cl))
272 
273 
274 
275 def message_class(spec):
276  """
277  Return the CLOS class name for this message type
278  """
279  return '<%s>'%spec.actual_name
280 
282  return spec.actual_name
283 
284 
285 def write_serialize_length(s, v, is_array=False):
286  #t2
287  var = '__ros_arr_len' if is_array else '__ros_str_len'
288 
289  s.write('(cl:let ((%s (cl:length %s)))'%(var, v))
290  with Indent(s):
291  for x in range(0, 32, 8):
292  s.write('(cl:write-byte (cl:ldb (cl:byte 8 %s) %s) ostream)'%(x, var))
293  s.write(')', indent=False)
294 
295 
296 def write_serialize_bits(s, v, num_bytes):
297  for x in range(0, num_bytes*8, 8):
298  s.write('(cl:write-byte (cl:ldb (cl:byte 8 %s) %s) ostream)'%(x, v))
299 
300 def write_serialize_bits_signed(s, v, num_bytes):
301  num_bits = num_bytes*8
302  s.write('(cl:let* ((signed %s) (unsigned (cl:if (cl:< signed 0) (cl:+ signed %s) signed)))'%(v, 2**num_bits))
303  with Indent(s):
304  write_serialize_bits(s, 'unsigned', num_bytes)
305  s.write(')')
306 
307 
308 
309 # t2: can get rid of this lookup_slot stuff
310 def write_serialize_builtin(s, f, var='msg', lookup_slot=True):
311  v = '(cl:slot-value %s \'%s)'%(var, f.name) if lookup_slot else var
312  if f.base_type == 'string':
314  s.write('(cl:map cl:nil #\'(cl:lambda (c) (cl:write-byte (cl:char-code c) ostream)) %s)'%v)
315  elif f.base_type == 'float32':
316  s.write('(cl:let ((bits %s))'%'(roslisp-utils:encode-single-float-bits %s)'%v)
317  with Indent(s):
318  write_serialize_bits(s, 'bits', 4)
319  s.write(')', False)
320  elif f.base_type == 'float64':
321  s.write('(cl:let ((bits %s))'%'(roslisp-utils:encode-double-float-bits %s)'%v)
322  with Indent(s):
323  write_serialize_bits(s, 'bits', 8)
324  s.write(')', False)
325  elif f.base_type == 'bool':
326  s.write('(cl:write-byte (cl:ldb (cl:byte 8 0) (cl:if %s 1 0)) ostream)'%v)
327  elif f.base_type in ['byte', 'char']:
328  s.write('(cl:write-byte (cl:ldb (cl:byte 8 0) %s) ostream)'%v)
329  elif f.base_type in ['duration', 'time']:
330  s.write('(cl:let ((__sec (cl:floor %s))'%v)
331  s.write(' (__nsec (cl:round (cl:* 1e9 (cl:- %s (cl:floor %s))))))'%(v,v))
332  with Indent(s):
333  write_serialize_bits(s, '__sec', 4)
334  write_serialize_bits(s, '__nsec', 4)
335  s.write(')', False)
336  elif is_signed_int(f.base_type):
337  write_serialize_bits_signed(s, v, NUM_BYTES[f.base_type])
338  elif is_unsigned_int(f.base_type):
339  write_serialize_bits(s, v, NUM_BYTES[f.base_type])
340  else:
341  raise ValueError('Unknown type: %s', f.base_type)
342 
344  slot = '(cl:slot-value msg \'%s)'%f.name
345  if f.is_array:
346  if not f.array_len:
347  write_serialize_length(s, slot, True)
348  s.write('(cl:map cl:nil #\'(cl:lambda (ele) ')
349  var = 'ele'
350  s.block_next_indent()
351  lookup_slot = False
352  else:
353  var='msg'
354  lookup_slot = True
355 
356  if f.is_builtin:
357  write_serialize_builtin(s, f, var, lookup_slot=lookup_slot)
358  else:
359  to_write = slot if lookup_slot else var #t2
360  s.write('(roslisp-msg-protocol:serialize %s ostream)'%to_write)
361 
362  if f.is_array:
363  s.write(')', False)
364  s.write(' %s)'%slot)
365 
366 def write_serialize(s, spec):
367  """
368  Write the serialize method
369  """
370  s.write('(cl:defmethod roslisp-msg-protocol:serialize ((msg %s) ostream)'%message_class(spec))
371  with Indent(s):
372  s.write('"Serializes a message object of type \'%s"'%message_class(spec))
373  for f in spec.parsed_fields():
375  s.write(')')
376 
377 
378 # t2 can get rid of is_array
379 def write_deserialize_length(s, is_array=False):
380  var = '__ros_arr_len' if is_array else '__ros_str_len'
381  s.write('(cl:let ((%s 0))'%var)
382  with Indent(s):
383  for x in range(0, 32, 8):
384  s.write('(cl:setf (cl:ldb (cl:byte 8 %s) %s) (cl:read-byte istream))'%(x, var))
385 
386 def write_deserialize_bits(s, v, num_bytes):
387  for x in range(0, num_bytes*8, 8):
388  s.write('(cl:setf (cl:ldb (cl:byte 8 %s) %s) (cl:read-byte istream))'%(x, v))
389 
390 def write_deserialize_bits_signed(s, v, num_bytes):
391  s.write('(cl:let ((unsigned 0))')
392  num_bits = 8*num_bytes
393  with Indent(s):
394  write_deserialize_bits(s, 'unsigned', num_bytes)
395  s.write('(cl:setf %s (cl:if (cl:< unsigned %s) unsigned (cl:- unsigned %s))))'%(v, 2**(num_bits-1), 2**num_bits))
396 
397 
398 
400  if f.base_type == 'string':
402  with Indent(s):
403  s.write('(cl:setf %s (cl:make-string __ros_str_len))'%v)
404  s.write('(cl:dotimes (__ros_str_idx __ros_str_len msg)')
405  with Indent(s):
406  s.write('(cl:setf (cl:char %s __ros_str_idx) (cl:code-char (cl:read-byte istream)))))'%v)
407  elif f.base_type == 'float32':
408  s.write('(cl:let ((bits 0))')
409  with Indent(s):
410  write_deserialize_bits(s, 'bits', 4)
411  s.write('(cl:setf %s (roslisp-utils:decode-single-float-bits bits)))'%v)
412  elif f.base_type == 'float64':
413  s.write('(cl:let ((bits 0))')
414  with Indent(s):
415  write_deserialize_bits(s, 'bits', 8)
416  s.write('(cl:setf %s (roslisp-utils:decode-double-float-bits bits)))'%v)
417  elif f.base_type == 'bool':
418  s.write('(cl:setf %s (cl:not (cl:zerop (cl:read-byte istream))))'%v)
419  elif f.base_type in ['byte', 'char']:
420  s.write('(cl:setf (cl:ldb (cl:byte 8 0) %s) (cl:read-byte istream))'%v)
421  elif f.base_type in ['duration', 'time']:
422  s.write('(cl:let ((__sec 0) (__nsec 0))')
423  with Indent(s):
424  write_deserialize_bits(s, '__sec', 4)
425  write_deserialize_bits(s, '__nsec', 4)
426  s.write('(cl:setf %s (cl:+ (cl:coerce __sec \'cl:double-float) (cl:/ __nsec 1e9))))'%v)
427  elif is_signed_int(f.base_type):
428  write_deserialize_bits_signed(s, v, NUM_BYTES[f.base_type])
429  elif is_unsigned_int(f.base_type):
430  write_deserialize_bits(s, v, NUM_BYTES[f.base_type])
431  else:
432  raise ValueError('%s unknown'%f.base_type)
433 
434 
435 def write_deserialize_field(s, f, pkg):
436  slot = '(cl:slot-value msg \'%s)'%f.name
437  var = slot
438  if f.is_array:
439  if not f.array_len:
440  write_deserialize_length(s, True)
441  length = '__ros_arr_len'
442  else:
443  length = '%s'%f.array_len
444 
445  s.write('(cl:setf %s (cl:make-array %s))'%(slot, length))
446  s.write('(cl:let ((vals %s))'%slot) # t2
447  var = '(cl:aref vals i)'
448  with Indent(s):
449  s.write('(cl:dotimes (i %s)'%length)
450 
451  if f.is_builtin:
452  with Indent(s):
453  write_deserialize_builtin(s, f, var)
454  else:
455  if f.is_array:
456  with Indent(s):
457  s.write('(cl:setf %s (cl:make-instance \'%s))'%(var, msg_type(f)))
458  s.write('(roslisp-msg-protocol:deserialize %s istream)'%var)
459 
460  if f.is_array:
461  s.write('))', False)
462  if not f.array_len:
463  s.write(')', False)
464 
465 
466 def write_deserialize(s, spec):
467  """
468  Write the deserialize method
469  """
470  s.write('(cl:defmethod roslisp-msg-protocol:deserialize ((msg %s) istream)'%message_class(spec))
471  with Indent(s):
472  s.write('"Deserializes a message object of type \'%s"'%message_class(spec))
473  for f in spec.parsed_fields():
474  write_deserialize_field(s, f, spec.package)
475  s.write('msg')
476  s.write(')')
477 
479  "Write the _package.lisp file"
480  s.write('(cl:defpackage %s-msg'%pkg, False)
481  with Indent(s):
482  s.write('(:use )')
483  s.write('(:export')
484  with Indent(s, inc=1):
485  for spec in roslib.msgs.get_pkg_msg_specs(pkg)[0]:
486  (p, msg_type) = spec[0].split('/')
487  msg_class = '<%s>'%msg_type
488  s.write('"%s"'%msg_class.upper())
489  s.write('"%s"'%msg_type.upper())
490  s.write('))\n\n')
491 
492 def write_srv_exports(s, pkg):
493  "Write the _package.lisp file for a service directory"
494  s.write('(cl:defpackage %s-srv'%pkg, False)
495  with Indent(s):
496  s.write('(:use )')
497  s.write('(:export')
498  with Indent(s, inc=1):
499  for spec in roslib.srvs.get_pkg_srv_specs(pkg)[0]:
500  (_, srv_type) = spec[0].split('/')
501  s.write('"%s"'%srv_type.upper())
502  s.write('"<%s-REQUEST>"'%srv_type.upper())
503  s.write('"%s-REQUEST"'%srv_type.upper())
504  s.write('"<%s-RESPONSE>"'%srv_type.upper())
505  s.write('"%s-RESPONSE"'%srv_type.upper())
506  s.write('))\n\n')
507 
508 
509 def write_asd_deps(s, deps, msgs):
510  with Indent(s):
511  s.write(':depends-on (:roslisp-msg-protocol :roslisp-utils ')
512  with Indent(s, inc=13, indent_first=False):
513  for d in sorted(deps):
514  s.write(':%s-msg'%d)
515  s.write(')') #t2 indentation
516  with Indent(s):
517  s.write(':components ((:file "_package")')
518  with Indent(s):
519  for (full_name, _) in msgs:
520  (_, name) = full_name.split('/')
521  s.write('(:file "%s" :depends-on ("_package_%s"))'%(name, name))
522  s.write('(:file "_package_%s" :depends-on ("_package"))'%name)
523  s.write('))')
524 
525 
526 
527 def write_srv_asd(s, pkg):
528  s.write('(cl:in-package :asdf)')
529  s.newline()
530  s.write('(defsystem "%s-srv"'%pkg)
531  services = roslib.srvs.get_pkg_srv_specs(pkg)[0]
532 
533  # Figure out set of depended-upon ros packages
534  deps = set()
535  for (_, spec) in services:
536  for f in spec.request.parsed_fields():
537  if not f.is_builtin:
538  (p, _) = parse_msg_type(f)
539  deps.add(p)
540  for f in spec.response.parsed_fields():
541  if not f.is_builtin:
542  (p, _) = parse_msg_type(f)
543  deps.add(p)
544 
545  write_asd_deps(s, deps, services)
546 
547 
548 def write_asd(s, pkg):
549  s.write('(cl:in-package :asdf)')
550  s.newline()
551  s.write('(defsystem "%s-msg"'%pkg)
552  msgs = roslib.msgs.get_pkg_msg_specs(pkg)[0]
553 
554  # Figure out set of depended-upon ros packages
555  deps = set()
556  for (_, spec) in msgs:
557  for f in spec.parsed_fields():
558  if not f.is_builtin:
559  (p, _) = parse_msg_type(f)
560  deps.add(p)
561  if pkg in deps:
562  deps.remove(pkg)
563  write_asd_deps(s, deps, msgs)
564 
566  "Write the package exports for this message/service"
567  is_srv = isinstance(spec, SrvSpec)
568  suffix = 'srv' if is_srv else 'msg'
569  s.write('(cl:in-package %s-%s)'%(spec.package, suffix), indent=False)
570  s.write('(cl:export \'(')
571  if is_srv:
572  fields = spec.request.parsed_fields()[:]
573  fields.extend(spec.response.parsed_fields())
574  else:
575  fields = spec.parsed_fields()
576 
577  with Indent(s, inc=10, indent_first=False):
578  for f in fields:
579  accessor = '%s-val'%f.name
580  s.write('%s'%accessor.upper())
581  s.write('%s'%f.name.upper())
582  s.write('))')
583 
584 
585 def write_ros_datatype(s, spec):
586  for c in (message_class(spec), new_message_class(spec)):
587  s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%c)
588  with Indent(s):
589  s.write('"Returns string type for a %s object of type \'%s"'%(spec.component_type, c))
590  s.write('"%s")'%spec.full_name)
591 
592 def write_md5sum(s, spec, parent=None):
593  if parent is None:
594  parent = spec
595  gendeps_dict = roslib.gentools.get_dependencies(parent, spec.package,
596  compute_files=False)
597  md5sum = roslib.gentools.compute_md5(gendeps_dict)
598  for c in (message_class(spec), new_message_class(spec)):
599  s.write('(cl:defmethod roslisp-msg-protocol:md5sum ((type (cl:eql \'%s)))'%c)
600  with Indent(s):
601  # t2 this should print 'service' instead of 'message' if it's a service request or response
602  s.write('"Returns md5sum for a message object of type \'%s"'%c)
603  s.write('"%s")'%md5sum)
604 
606  for c in (message_class(spec), new_message_class(spec)):
607  s.write('(cl:defmethod roslisp-msg-protocol:message-definition ((type (cl:eql \'%s)))'%c)
608  with Indent(s):
609  s.write('"Returns full string definition for message of type \'%s"'%c)
610  s.write('(cl:format cl:nil "')
611  gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package, compute_files=False)
612  definition = roslib.gentools.compute_full_text(gendeps_dict)
613  lines = definition.split('\n')
614  for line in lines:
615  l = line.replace('\\', '\\\\')
616  l = l.replace('"', '\\"')
617  s.write('%s~%%'%l, indent=False)
618  s.write('~%', indent=False)
619  s.write('"))', indent=False)
620 
621 def write_builtin_length(s, f, var='msg'):
622  if f.base_type in ['int8', 'uint8']:
623  s.write('1')
624  elif f.base_type in ['int16', 'uint16']:
625  s.write('2')
626  elif f.base_type in ['int32', 'uint32', 'float32']:
627  s.write('4')
628  elif f.base_type in ['int64', 'uint64', 'float64', 'duration', 'time']:
629  s.write('8')
630  elif f.base_type == 'string':
631  s.write('4 (cl:length %s)'%var)
632  elif f.base_type in ['bool', 'byte', 'char']:
633  s.write('1')
634  else:
635  raise ValueError('Unknown: %s', f.base_type)
636 
638  c = message_class(spec)
639  s.write('(cl:defmethod roslisp-msg-protocol:serialization-length ((msg %s))'%c)
640  with Indent(s):
641  s.write('(cl:+ 0')
642  with Indent(s, 3):
643  for field in spec.parsed_fields():
644  slot = '(cl:slot-value msg \'%s)'%field.name
645  if field.is_array:
646  l = '0' if field.array_len else '4'
647  s.write('%s (cl:reduce #\'cl:+ %s :key #\'(cl:lambda (ele) (cl:declare (cl:ignorable ele)) (cl:+ '%(l, slot))
648  var = 'ele'
649  s.block_next_indent()
650  else:
651  var = slot
652 
653  if field.is_builtin:
654  write_builtin_length(s, field, var)
655  else:
656  s.write('(roslisp-msg-protocol:serialization-length %s)'%var)
657 
658  if field.is_array:
659  s.write(')))', False)
660  s.write('))')
661 
662 
663 def write_list_converter(s, spec):
664  c = message_class(spec)
665  s.write('(cl:defmethod roslisp-msg-protocol:ros-message-to-list ((msg %s))'%c)
666  with Indent(s):
667  s.write('"Converts a ROS message object to a list"')
668  s.write('(cl:list \'%s'%new_message_class(spec))
669  with Indent(s):
670  for f in spec.parsed_fields():
671  s.write('(cl:cons \':%s (%s msg))'%(f.name, f.name))
672  s.write('))')
673 
674 def write_constants(s, spec):
675  if spec.constants:
676  for cls in (message_class(spec), new_message_class(spec)):
677  s.write('(cl:defmethod roslisp-msg-protocol:symbol-codes ((msg-type (cl:eql \'%s)))'%cls)
678  with Indent(s):
679  s.write(' "Constants for message type \'%s"'%cls)
680  s.write('\'(')
681  with Indent(s, indent_first=False):
682  for c in spec.constants:
683  s.write('(:%s . %s)'%(c.name.upper(), c.val))
684  s.write(')', False)
685  s.write(')')
686 
687 
688 def write_srv_component(s, spec, parent):
689  spec.component_type='service'
690  write_html_include(s, spec)
691  write_defclass(s, spec)
692  write_deprecated_readers(s, spec)
693  write_constants(s, spec)
694  write_serialize(s, spec)
695  write_deserialize(s, spec)
696  write_ros_datatype(s, spec)
697  write_md5sum(s, spec, parent)
698  write_message_definition(s, spec)
700  write_list_converter(s, spec)
701 
702 
704  spec.actual_name=spec.short_name
705  s.write('(cl:defmethod roslisp-msg-protocol:service-request-type ((msg (cl:eql \'%s)))'%spec.short_name)
706  with Indent(s):
707  s.write('\'%s)'%new_message_class(spec.request))
708  s.write('(cl:defmethod roslisp-msg-protocol:service-response-type ((msg (cl:eql \'%s)))'%spec.short_name)
709  with Indent(s):
710  s.write('\'%s)'%new_message_class(spec.response))
711  s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%spec.short_name)
712  with Indent(s):
713  s.write('"Returns string type for a service object of type \'%s"'%message_class(spec))
714  s.write('"%s")'%spec.full_name)
715 
716 
717 def generate_msg(msg_path):
718  """
719  Generate a message
720 
721  @param msg_path: The path to the .msg file
722  @type msg_path: str
723  """
724  (package_dir, package) = roslib.packages.get_dir_pkg(msg_path)
725  (_, spec) = roslib.msgs.load_from_file(msg_path, package)
726  spec.actual_name=spec.short_name
727  spec.component_type='message'
728 
729  ########################################
730  # 1. Write the .lisp file
731  ########################################
732 
733  io = StringIO()
734  s = IndentedWriter(io)
735  write_begin(s, spec, msg_path)
736  write_html_include(s, spec)
737  write_defclass(s, spec)
738  write_deprecated_readers(s, spec)
739  write_constants(s, spec)
740  write_serialize(s, spec)
741  write_deserialize(s, spec)
742  write_ros_datatype(s, spec)
743  write_md5sum(s, spec)
744  write_message_definition(s, spec)
746  write_list_converter(s, spec)
747 
748  output_dir = '%s/msg_gen/lisp'%package_dir
749  if (not os.path.exists(output_dir)):
750  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
751  # another copy just created the directory
752  try:
753  os.makedirs(output_dir)
754  except OSError as e:
755  pass
756 
757  with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
758  f.write(io.getvalue() + "\n")
759  io.close()
760 
761  ########################################
762  # 2. Write the _package file
763  # for this message
764  ########################################
765 
766  io = StringIO()
767  s = IndentedWriter(io)
768  write_accessor_exports(s, spec)
769  with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
770  f.write(io.getvalue())
771  io.close()
772 
773  ########################################
774  # 3. Write the _package.lisp file
775  # This is being rewritten once per msg
776  # file, which is inefficient
777  ########################################
778 
779  io = StringIO()
780  s = IndentedWriter(io)
781  write_class_exports(s, package)
782  with open('%s/_package.lisp'%output_dir, 'w') as f:
783  f.write(io.getvalue())
784  io.close()
785 
786  ########################################
787  # 4. Write the .asd file
788  # This is being written once per msg
789  # file, which is inefficient
790  ########################################
791 
792  io = StringIO()
793  s = IndentedWriter(io)
794  write_asd(s, package)
795  with open('%s/%s-msg.asd'%(output_dir, package), 'w') as f:
796  f.write(io.getvalue())
797  io.close()
798 
799 # t0 most of this could probably be refactored into being shared with messages
800 def generate_srv(srv_path):
801  "Generate code from .srv file"
802  (pkg_dir, pkg) = roslib.packages.get_dir_pkg(srv_path)
803  (_, spec) = roslib.srvs.load_from_file(srv_path, pkg)
804  output_dir = '%s/srv_gen/lisp'%pkg_dir
805  if (not os.path.exists(output_dir)):
806  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
807  # another copy just created the directory
808  try:
809  os.makedirs(output_dir)
810  except OSError as e:
811  pass
812 
813  ########################################
814  # 1. Write the .lisp file
815  ########################################
816 
817  io = StringIO()
818  s = IndentedWriter(io)
819  write_begin(s, spec, srv_path, True)
820  spec.request.actual_name='%s-request'%spec.short_name
821  spec.response.actual_name='%s-response'%spec.short_name
822  write_srv_component(s, spec.request, spec)
823  s.newline()
824  write_srv_component(s, spec.response, spec)
826 
827  with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
828  f.write(io.getvalue())
829  io.close()
830 
831  ########################################
832  # 2. Write the _package file
833  # for this service
834  ########################################
835 
836  io = StringIO()
837  s = IndentedWriter(io)
838  write_accessor_exports(s, spec)
839  with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
840  f.write(io.getvalue())
841  io.close()
842 
843  ########################################
844  # 3. Write the _package.lisp file
845  ########################################
846 
847  io = StringIO()
848  s = IndentedWriter(io)
849  write_srv_exports(s, pkg)
850  with open('%s/_package.lisp'%output_dir, 'w') as f:
851  f.write(io.getvalue())
852  io.close()
853 
854  ########################################
855  # 4. Write the .asd file
856  ########################################
857 
858  io = StringIO()
859  s = IndentedWriter(io)
860  write_srv_asd(s, pkg)
861  with open('%s/%s-srv.asd'%(output_dir, pkg), 'w') as f:
862  f.write(io.getvalue())
863  io.close()
864 
865 
866 
867 
868 if __name__ == "__main__":
869  roslib.msgs.set_verbose(False)
870  if sys.argv[1].endswith('.msg'):
871  generate_msg(sys.argv[1])
872  elif sys.argv[1].endswith('.srv'):
873  generate_srv(sys.argv[1])
874  else:
875  raise ValueError('Invalid filename %s'%sys.argv[1])
def is_time(t)
Definition: genmsg_lisp.py:85
def generate_srv(srv_path)
Definition: genmsg_lisp.py:800
def write_accessor_exports(s, spec)
Definition: genmsg_lisp.py:565
def write_srv_component(s, spec, parent)
Definition: genmsg_lisp.py:688
def is_unsigned_int(t)
Definition: genmsg_lisp.py:73
def write(self, s, indent=True, newline=True)
Definition: genmsg_lisp.py:168
def generate_msg(msg_path)
Definition: genmsg_lisp.py:717
def message_class(spec)
Definition: genmsg_lisp.py:275
def write_defclass(s, spec)
Definition: genmsg_lisp.py:248
def write_srv_exports(s, pkg)
Definition: genmsg_lisp.py:492
def __init__(self, w, inc=2, indent_first=True)
Definition: genmsg_lisp.py:198
def lisp_type(t)
Definition: genmsg_lisp.py:109
def field_initform(f)
Definition: genmsg_lisp.py:125
def write_html_include(s, spec, is_srv=False)
Definition: genmsg_lisp.py:220
def is_float(t)
Definition: genmsg_lisp.py:82
def write_constants(s, spec)
Definition: genmsg_lisp.py:674
def write_deserialize_length(s, is_array=False)
Definition: genmsg_lisp.py:379
def write_list_converter(s, spec)
Definition: genmsg_lisp.py:663
def write_serialize_builtin(s, f, var='msg', lookup_slot=True)
Definition: genmsg_lisp.py:310
def write_deserialize_field(s, f, pkg)
Definition: genmsg_lisp.py:435
def write_deserialize_bits_signed(s, v, num_bytes)
Definition: genmsg_lisp.py:390
def write_deprecated_readers(s, spec)
Definition: genmsg_lisp.py:236
def write_serialize_bits(s, v, num_bytes)
Definition: genmsg_lisp.py:296
def is_string(t)
Definition: genmsg_lisp.py:79
def __enter__(self)
Definition: genmsg_lisp.py:203
def field_type(f)
Definition: genmsg_lisp.py:88
def parse_msg_type(f)
Definition: genmsg_lisp.py:98
def is_fixnum(t)
Built in types.
Definition: genmsg_lisp.py:64
def write_begin(s, spec, path, is_service=False)
Definition: genmsg_lisp.py:213
def write_deserialize_builtin(s, f, v)
Definition: genmsg_lisp.py:399
def write_slot_definition(s, field)
Definition: genmsg_lisp.py:224
def dec_indent(self, dec=2)
Definition: genmsg_lisp.py:187
def write_serialization_length(s, spec)
Definition: genmsg_lisp.py:637
def inc_indent(self, inc=2)
Definition: genmsg_lisp.py:184
def write_ros_datatype(s, spec)
Definition: genmsg_lisp.py:585
def write_message_definition(s, spec)
Definition: genmsg_lisp.py:605
def new_message_class(spec)
Definition: genmsg_lisp.py:281
def __exit__(self, type, val, traceback)
Definition: genmsg_lisp.py:208
def write_asd(s, pkg)
Definition: genmsg_lisp.py:548
def write_deserialize(s, spec)
Definition: genmsg_lisp.py:466
def write_srv_asd(s, pkg)
Definition: genmsg_lisp.py:527
def write_asd_deps(s, deps, msgs)
Definition: genmsg_lisp.py:509
def write_serialize(s, spec)
Definition: genmsg_lisp.py:366
def is_integer(t)
Definition: genmsg_lisp.py:67
def write_deserialize_bits(s, v, num_bytes)
Definition: genmsg_lisp.py:386
def is_bool(t)
Definition: genmsg_lisp.py:76
def msg_type(f)
Definition: genmsg_lisp.py:105
def write_md5sum(s, spec, parent=None)
Definition: genmsg_lisp.py:592
def write_serialize_field(s, f)
Definition: genmsg_lisp.py:343
def write_serialize_bits_signed(s, v, num_bytes)
Definition: genmsg_lisp.py:300
def write_builtin_length(s, f, var='msg')
Definition: genmsg_lisp.py:621
def lisp_initform(t)
Definition: genmsg_lisp.py:138
def write_serialize_length(s, v, is_array=False)
Definition: genmsg_lisp.py:285
def is_signed_int(t)
Definition: genmsg_lisp.py:70
def write_class_exports(s, pkg)
Definition: genmsg_lisp.py:478
def write_service_specific_methods(s, spec)
Definition: genmsg_lisp.py:703


roslisp
Author(s): Bhaskara Marthi, Brian Gerkey, Lorenz Moesenlechner , Thibault Kruse
autogenerated on Mon May 25 2020 03:23:28