generate.py
Go to the documentation of this file.
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 ## ROS message source code generation for Lisp
35 ##
36 ## Converts ROS .msg and .srv files in a package into Lisp source code
37 
38 ## t0: needed for script to work
39 ## t1: for reference; remove once running
40 ## t2: can be changed once we remove strict diff-compatibility requirement with old version of genmsg_lisp
41 
42 import sys
43 import os
44 import traceback
45 import re
46 
47 #import roslib.msgs
48 #import roslib.srvs
49 #import roslib.packages
50 #import roslib.gentools
51 from genmsg import SrvSpec, MsgSpec, MsgContext
52 from genmsg.msg_loader import load_srv_from_file, load_msg_by_type
53 import genmsg.gentools
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, 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 
478 def write_class_exports(s, msgs, pkg):
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 m in msgs:
486  msg_class = '<%s>'%m
487  s.write('"%s"'%msg_class.upper())
488  s.write('"%s"'%m.upper())
489  s.write('))\n\n')
490 
491 def write_srv_exports(s, srvs, pkg):
492  "Write the _package.lisp file for a service directory"
493  s.write('(cl:defpackage %s-srv'%pkg, False)
494  with Indent(s):
495  s.write('(:use )')
496  s.write('(:export')
497  with Indent(s, inc=1):
498  for srv in srvs:
499  s.write('"%s"'%srv.upper())
500  s.write('"<%s-REQUEST>"'%srv.upper())
501  s.write('"%s-REQUEST"'%srv.upper())
502  s.write('"<%s-RESPONSE>"'%srv.upper())
503  s.write('"%s-RESPONSE"'%srv.upper())
504  s.write('))\n\n')
505 
506 
507 def write_asd_deps(s, deps, msgs):
508  with Indent(s):
509  s.write(':depends-on (:roslisp-msg-protocol :roslisp-utils ')
510  with Indent(s, inc=13, indent_first=False):
511  for d in sorted(deps):
512  s.write(':%s-msg'%d)
513  s.write(')') #t2 indentation
514  with Indent(s):
515  s.write(':components ((:file "_package")')
516  with Indent(s):
517  for name in msgs:
518  s.write('(:file "%s" :depends-on ("_package_%s"))'%(name, name))
519  s.write('(:file "_package_%s" :depends-on ("_package"))'%name)
520  s.write('))')
521 
522 
523 
524 def write_srv_asd(s, pkg, srvs, context):
525  s.write('(cl:in-package :asdf)')
526  s.newline()
527  s.write('(defsystem "%s-srv"'%pkg)
528 
529  # Figure out set of depended-upon ros packages
530  deps = set()
531  for srv in srvs:
532  req_spec = context.get_registered('%s/%sRequest'%(pkg, srv))
533  resp_spec = context.get_registered('%s/%sResponse'%(pkg, srv))
534  for f in req_spec.parsed_fields():
535  if not f.is_builtin:
536  (p, _) = parse_msg_type(f)
537  deps.add(p)
538  for f in resp_spec.parsed_fields():
539  if not f.is_builtin:
540  (p, _) = parse_msg_type(f)
541  deps.add(p)
542 
543  write_asd_deps(s, deps, srvs)
544 
545 
546 def write_asd(s, pkg, msgs, context):
547  s.write('(cl:in-package :asdf)')
548  s.newline()
549  s.write('(defsystem "%s-msg"'%pkg)
550 
551  # Figure out set of depended-upon ros packages
552  deps = set()
553  for m in msgs:
554  spec = context.get_registered('%s/%s'%(pkg, m))
555  for f in spec.parsed_fields():
556  if not f.is_builtin:
557  (p, _) = parse_msg_type(f)
558  deps.add(p)
559  if pkg in deps:
560  deps.remove(pkg)
561  write_asd_deps(s, deps, msgs)
562 
564  "Write the package exports for this message/service"
565  is_srv = isinstance(spec, SrvSpec)
566  suffix = 'srv' if is_srv else 'msg'
567  s.write('(cl:in-package %s-%s)'%(spec.package, suffix), indent=False)
568  s.write('(cl:export \'(')
569  if is_srv:
570  fields = spec.request.parsed_fields()[:]
571  fields.extend(spec.response.parsed_fields())
572  else:
573  fields = spec.parsed_fields()
574 
575  with Indent(s, inc=10, indent_first=False):
576  for f in fields:
577  accessor = '%s-val'%f.name
578  s.write('%s'%accessor.upper())
579  s.write('%s'%f.name.upper())
580  s.write('))')
581 
582 
583 def write_ros_datatype(s, spec):
584  for c in (message_class(spec), new_message_class(spec)):
585  s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%c)
586  with Indent(s):
587  s.write('"Returns string type for a %s object of type \'%s"'%(spec.component_type, c))
588  s.write('"%s")'%spec.full_name)
589 
590 def write_md5sum(s, msg_context, spec, parent=None):
591  md5sum = genmsg.compute_md5(msg_context, parent or spec)
592  for c in (message_class(spec), new_message_class(spec)):
593  s.write('(cl:defmethod roslisp-msg-protocol:md5sum ((type (cl:eql \'%s)))'%c)
594  with Indent(s):
595  # t2 this should print 'service' instead of 'message' if it's a service request or response
596  s.write('"Returns md5sum for a message object of type \'%s"'%c)
597  s.write('"%s")'%md5sum)
598 
599 def write_message_definition(s, msg_context, spec):
600  for c in (message_class(spec), new_message_class(spec)):
601  s.write('(cl:defmethod roslisp-msg-protocol:message-definition ((type (cl:eql \'%s)))'%c)
602  with Indent(s):
603  s.write('"Returns full string definition for message of type \'%s"'%c)
604  s.write('(cl:format cl:nil "')
605  definition = genmsg.compute_full_text(msg_context, spec)
606  lines = definition.split('\n')
607  for line in lines:
608  l = line.replace('\\', '\\\\')
609  l = l.replace('"', '\\"')
610  l = l.replace('~', '~~')
611  s.write('%s~%%'%l, indent=False)
612  s.write('~%', indent=False)
613  s.write('"))', indent=False)
614 
615 def write_builtin_length(s, f, var='msg'):
616  if f.base_type in ['int8', 'uint8']:
617  s.write('1')
618  elif f.base_type in ['int16', 'uint16']:
619  s.write('2')
620  elif f.base_type in ['int32', 'uint32', 'float32']:
621  s.write('4')
622  elif f.base_type in ['int64', 'uint64', 'float64', 'duration', 'time']:
623  s.write('8')
624  elif f.base_type == 'string':
625  s.write('4 (cl:length %s)'%var)
626  elif f.base_type in ['bool', 'byte', 'char']:
627  s.write('1')
628  else:
629  raise ValueError('Unknown: %s', f.base_type)
630 
632  c = message_class(spec)
633  s.write('(cl:defmethod roslisp-msg-protocol:serialization-length ((msg %s))'%c)
634  with Indent(s):
635  s.write('(cl:+ 0')
636  with Indent(s, 3):
637  for field in spec.parsed_fields():
638  slot = '(cl:slot-value msg \'%s)'%field.name
639  if field.is_array:
640  l = '0' if field.array_len else '4'
641  s.write('%s (cl:reduce #\'cl:+ %s :key #\'(cl:lambda (ele) (cl:declare (cl:ignorable ele)) (cl:+ '%(l, slot))
642  var = 'ele'
643  s.block_next_indent()
644  else:
645  var = slot
646 
647  if field.is_builtin:
648  write_builtin_length(s, field, var)
649  else:
650  s.write('(roslisp-msg-protocol:serialization-length %s)'%var)
651 
652  if field.is_array:
653  s.write(')))', False)
654  s.write('))')
655 
656 
657 def write_list_converter(s, spec):
658  c = message_class(spec)
659  s.write('(cl:defmethod roslisp-msg-protocol:ros-message-to-list ((msg %s))'%c)
660  with Indent(s):
661  s.write('"Converts a ROS message object to a list"')
662  s.write('(cl:list \'%s'%new_message_class(spec))
663  with Indent(s):
664  for f in spec.parsed_fields():
665  s.write('(cl:cons \':%s (%s msg))'%(f.name, f.name))
666  s.write('))')
667 
668 def write_constants(s, spec):
669  if spec.constants:
670  for cls in (message_class(spec), new_message_class(spec)):
671  s.write('(cl:defmethod roslisp-msg-protocol:symbol-codes ((msg-type (cl:eql \'%s)))'%cls)
672  with Indent(s):
673  s.write(' "Constants for message type \'%s"'%cls)
674  s.write('\'(')
675  with Indent(s, indent_first=False):
676  for c in spec.constants:
677  s.write('(:%s . %s)'%(c.name.upper(), c.val))
678  s.write(')', False)
679  s.write(')')
680 
681 
682 def write_srv_component(s, spec, context, parent):
683  spec.component_type='service'
684  write_html_include(s, spec)
685  write_defclass(s, spec)
686  write_deprecated_readers(s, spec)
687  write_constants(s, spec)
688  write_serialize(s, spec)
689  write_deserialize(s, spec)
690  write_ros_datatype(s, spec)
691  write_md5sum(s, context, spec, parent=parent)
692  write_message_definition(s, context, spec)
694  write_list_converter(s, spec)
695 
696 
698  spec.actual_name=spec.short_name
699  s.write('(cl:defmethod roslisp-msg-protocol:service-request-type ((msg (cl:eql \'%s)))'%spec.short_name)
700  with Indent(s):
701  s.write('\'%s)'%new_message_class(spec.request))
702  s.write('(cl:defmethod roslisp-msg-protocol:service-response-type ((msg (cl:eql \'%s)))'%spec.short_name)
703  with Indent(s):
704  s.write('\'%s)'%new_message_class(spec.response))
705  s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%spec.short_name)
706  with Indent(s):
707  s.write('"Returns string type for a service object of type \'%s"'%message_class(spec))
708  s.write('"%s")'%spec.full_name)
709 
710 
711 def generate_msg(pkg, files, out_dir, search_path):
712  """
713  Generate lisp code for all messages in a package
714  """
715  msg_context = MsgContext.create_default()
716  for f in files:
717  f = os.path.abspath(f)
718  infile = os.path.basename(f)
719  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
720  spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
721  generate_msg_from_spec(msg_context, spec, search_path, out_dir, pkg)
722 
723 def generate_srv(pkg, files, out_dir, search_path):
724  """
725  Generate lisp code for all services in a package
726  """
727  msg_context = MsgContext.create_default()
728  for f in files:
729  f = os.path.abspath(f)
730  infile = os.path.basename(f)
731  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
732  spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
733  generate_srv_from_spec(msg_context, spec, search_path, out_dir, pkg, f)
734 
735 def msg_list(pkg, search_path, ext):
736  dir_list = search_path[pkg]
737  files = []
738  for d in dir_list:
739  files.extend([f for f in os.listdir(d) if f.endswith(ext)])
740  # sort list because listdir is filesystem specific
741  return sorted([f[:-len(ext)] for f in files])
742 
743 def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package):
744  """
745  Generate a message
746 
747  @param msg_path: The path to the .msg file
748  @type msg_path: str
749  """
750  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
751  spec.actual_name=spec.short_name
752  spec.component_type='message'
753  msgs = msg_list(package, search_path, '.msg')
754  for m in msgs:
755  genmsg.load_msg_by_type(msg_context, '%s/%s'%(package, m), search_path)
756 
757 
758  ########################################
759  # 1. Write the .lisp file
760  ########################################
761 
762  io = StringIO()
763  s = IndentedWriter(io)
764  write_begin(s, spec)
765  write_html_include(s, spec)
766  write_defclass(s, spec)
767  write_deprecated_readers(s, spec)
768  write_constants(s, spec)
769  write_serialize(s, spec)
770  write_deserialize(s, spec)
771  write_ros_datatype(s, spec)
772  write_md5sum(s, msg_context, spec)
773  write_message_definition(s, msg_context, spec)
775  write_list_converter(s, spec)
776 
777  if (not os.path.exists(output_dir)):
778  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
779  # another copy just created the directory
780  try:
781  os.makedirs(output_dir)
782  except OSError as e:
783  pass
784 
785  with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
786  f.write(io.getvalue() + "\n")
787  io.close()
788 
789  ########################################
790  # 2. Write the _package file
791  # for this message
792  ########################################
793 
794  io = StringIO()
795  s = IndentedWriter(io)
796  write_accessor_exports(s, spec)
797  with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
798  f.write(io.getvalue())
799  io.close()
800 
801  ########################################
802  # 3. Write the _package.lisp file
803  # This is being rewritten once per msg
804  # file, which is inefficient
805  ########################################
806 
807  io = StringIO()
808  s = IndentedWriter(io)
809  write_class_exports(s, msgs, package)
810  with open('%s/_package.lisp'%output_dir, 'w') as f:
811  f.write(io.getvalue())
812  io.close()
813 
814  ########################################
815  # 4. Write the .asd file
816  # This is being written once per msg
817  # file, which is inefficient
818  ########################################
819 
820  io = StringIO()
821  s = IndentedWriter(io)
822  write_asd(s, package, msgs, msg_context)
823  with open('%s/%s-msg.asd'%(output_dir, package), 'w') as f:
824  f.write(io.getvalue())
825  io.close()
826 
827 # t0 most of this could probably be refactored into being shared with messages
828 def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path):
829  "Generate code from .srv file"
830  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
831  ext = '.srv'
832  srv_path = os.path.dirname(path)
833  srvs = msg_list(package, {package: [srv_path]}, ext)
834  for srv in srvs:
835  load_srv_from_file(msg_context, '%s/%s%s'%(srv_path, srv, ext), '%s/%s'%(package, srv))
836 
837  ########################################
838  # 1. Write the .lisp file
839  ########################################
840 
841  io = StringIO()
842  s = IndentedWriter(io)
843  write_begin(s, spec, True)
844  spec.request.actual_name='%s-request'%spec.short_name
845  spec.response.actual_name='%s-response'%spec.short_name
846  write_srv_component(s, spec.request, msg_context, spec)
847  s.newline()
848  write_srv_component(s, spec.response, msg_context, spec)
850 
851  with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
852  f.write(io.getvalue())
853  io.close()
854 
855  ########################################
856  # 2. Write the _package file
857  # for this service
858  ########################################
859 
860  io = StringIO()
861  s = IndentedWriter(io)
862  write_accessor_exports(s, spec)
863  with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
864  f.write(io.getvalue())
865  io.close()
866 
867  ########################################
868  # 3. Write the _package.lisp file
869  ########################################
870 
871  io = StringIO()
872  s = IndentedWriter(io)
873  write_srv_exports(s, srvs, package)
874  with open('%s/_package.lisp'%output_dir, 'w') as f:
875  f.write(io.getvalue())
876  io.close()
877 
878  ########################################
879  # 4. Write the .asd file
880  ########################################
881 
882  io = StringIO()
883  s = IndentedWriter(io)
884  write_srv_asd(s, package, srvs, msg_context)
885  with open('%s/%s-srv.asd'%(output_dir, package), 'w') as f:
886  f.write(io.getvalue())
887  io.close()
888 
889 
def write_ros_datatype(s, spec)
Definition: generate.py:583
def is_fixnum(t)
Built in types.
Definition: generate.py:64
def write_deserialize_bits_signed(s, v, num_bytes)
Definition: generate.py:390
def is_signed_int(t)
Definition: generate.py:70
def generate_msg(pkg, files, out_dir, search_path)
Definition: generate.py:711
def write_serialize_builtin(s, f, var='msg', lookup_slot=True)
Definition: generate.py:310
def write_deserialize_builtin(s, f, v)
Definition: generate.py:399
def write_asd_deps(s, deps, msgs)
Definition: generate.py:507
def write_srv_asd(s, pkg, srvs, context)
Definition: generate.py:524
def new_message_class(spec)
Definition: generate.py:281
def write_srv_exports(s, srvs, pkg)
Definition: generate.py:491
def write_slot_definition(s, field)
Definition: generate.py:224
def __init__(self, w, inc=2, indent_first=True)
Definition: generate.py:198
def is_time(t)
Definition: generate.py:85
def write_serialize(s, spec)
Definition: generate.py:366
def is_unsigned_int(t)
Definition: generate.py:73
def lisp_initform(t)
Definition: generate.py:138
def generate_srv(pkg, files, out_dir, search_path)
Definition: generate.py:723
def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package)
Definition: generate.py:743
def is_integer(t)
Definition: generate.py:67
def write_srv_component(s, spec, context, parent)
Definition: generate.py:682
def write_class_exports(s, msgs, pkg)
Definition: generate.py:478
def write_asd(s, pkg, msgs, context)
Definition: generate.py:546
def write_md5sum(s, msg_context, spec, parent=None)
Definition: generate.py:590
def write_serialization_length(s, spec)
Definition: generate.py:631
def write_message_definition(s, msg_context, spec)
Definition: generate.py:599
def write_list_converter(s, spec)
Definition: generate.py:657
def write_constants(s, spec)
Definition: generate.py:668
def msg_type(f)
Definition: generate.py:105
def field_initform(f)
Definition: generate.py:125
def parse_msg_type(f)
Definition: generate.py:98
def write_deserialize_length(s, is_array=False)
Definition: generate.py:379
def write_builtin_length(s, f, var='msg')
Definition: generate.py:615
def write_deserialize(s, spec)
Definition: generate.py:466
def write_serialize_bits_signed(s, v, num_bytes)
Definition: generate.py:300
def write_serialize_length(s, v, is_array=False)
Definition: generate.py:285
def is_bool(t)
Definition: generate.py:76
def write_begin(s, spec, is_service=False)
Definition: generate.py:213
def write_deserialize_bits(s, v, num_bytes)
Definition: generate.py:386
def message_class(spec)
Definition: generate.py:275
def is_float(t)
Definition: generate.py:82
def write_deprecated_readers(s, spec)
Definition: generate.py:236
def inc_indent(self, inc=2)
Definition: generate.py:184
def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path)
Definition: generate.py:828
def write_accessor_exports(s, spec)
Definition: generate.py:563
def dec_indent(self, dec=2)
Definition: generate.py:187
def write_serialize_field(s, f)
Definition: generate.py:343
def write_serialize_bits(s, v, num_bytes)
Definition: generate.py:296
def write_deserialize_field(s, f, pkg)
Definition: generate.py:435
def __exit__(self, type, val, traceback)
Definition: generate.py:208
def lisp_type(t)
Definition: generate.py:109
def is_string(t)
Definition: generate.py:79
def msg_list(pkg, search_path, ext)
Definition: generate.py:735
def write_html_include(s, spec, is_srv=False)
Definition: generate.py:220
def field_type(f)
Definition: generate.py:88
def write_service_specific_methods(s, spec)
Definition: generate.py:697
def write_defclass(s, spec)
Definition: generate.py:248
def write(self, s, indent=True, newline=True)
Definition: generate.py:168


genlisp
Author(s): Bhaskara Marti
autogenerated on Fri Jun 7 2019 21:53:48