generate.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2014, JSK Robotics Laboratory.
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 JSK Robotics Laboratory. 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 EusLisp(roseus)
35 
37 
38 import sys
39 import os
40 import traceback
41 import re
42 
43 from genmsg import SrvSpec, MsgSpec, MsgContext
44 from genmsg.msg_loader import load_srv_from_file, load_msg_by_type
45 import genmsg.gentools
46 
47 try:
48  from cStringIO import StringIO #Python 2.x
49 except ImportError:
50  from io import StringIO #Python 3.x
51 
52 ############################################################
53 # Built in types
54 ############################################################
55 
56 def is_integer(t):
57  return t in ['byte', 'char', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64'] #t char/byte deprecated alias for uint8/int8, see http://wiki.ros.org/msg#Fields
58 
60  return t in ['byte', 'int8', 'int16', 'int32', 'int64']
61 
63  return t in ['char', 'uint8', 'uint16', 'uint32', 'uint64']
64 
65 def is_bool(t):
66  return t == 'bool'
67 
68 def is_string(t):
69  return t == 'string'
70 
71 def is_float(t):
72  return t in ['float16', 'float32', 'float64']
73 
74 def is_time(t):
75  return t in ['time', 'duration']
76 
77 def field_type(f):
78  if f.is_builtin:
79  elt_type = lisp_type(f.base_type, f.is_array)
80  else:
81  elt_type = msg_type(f)
82  return elt_type
83 
85  "returns (package, msg_or_srv)"
86  if f.base_type == 'Header':
87  return ('std_msgs', 'Header')
88  else:
89  return f.base_type.split('/')
90 
91 def msg_type(f):
92  "returns roseus namespace package::msg_or_srv"
93  (pkg, msg) = parse_msg_type(f)
94  return '%s::%s'%(pkg, msg)
95 
96 def lisp_type(t, array):
97  if t == 'uint8' and array:
98  return 'char'
99  if is_integer(t):
100  return 'integer'
101  elif is_bool(t):
102  return 'object'
103  elif is_float(t):
104  return 'float'
105  elif is_time(t):
106  return 'ros::time'
107  elif is_string(t):
108  return 'string'
109  else:
110  raise ValueError('%s is not a recognized primitive type'%t)
111 
113  var = "__%s"%f.name
114  if f.is_builtin and not f.is_array:
115  if is_integer(f.base_type):
116  return '(round %s)'%var
117  elif is_float(f.base_type):
118  return '(float %s)'%var
119  elif is_string(f.base_type):
120  return '(string %s)'%var
121  return var
122 
124  initvalue = lisp_initvalue(f.base_type)
125  elt_type = lisp_type(f.base_type, f.is_array)
126  if not is_time(f.base_type):
127  elt_type = ':'+elt_type
128  if f.is_array:
129  len = f.array_len or 0
130  if f.is_builtin and not is_string(f.base_type) and not is_bool(f.base_type) and not is_time(f.base_type):
131  return '(make-array %s :initial-element %s :element-type %s)'%(len, initvalue, elt_type)
132  else:
133  return '(let (r) (dotimes (i %s) (push %s r)) r)'%(len, initvalue)
134  else:
135  return initvalue
136 
138  if is_integer(t):
139  return '0'
140  elif is_bool(t):
141  return 'nil'
142  elif is_float(t):
143  return '0.0'
144  elif is_time(t):
145  return '(instance ros::time :init)'
146  elif is_string(t):
147  return '\"\"'
148  else:
149  raise ValueError('%s is not a recognized primitive type'%t)
150 
152  if is_integer(t):
153  return 'round'
154  elif is_bool(t):
155  return 'nil'
156  elif is_float(t):
157  return 'float'
158  elif is_time(t):
159  return 'ros::time'
160  elif is_string(t):
161  return 'string'
162  else:
163  raise ValueError('%s is not a recognized primitive type'%t)
164 
165 NUM_BYTES = {'byte': 1, 'int8': 1, 'int16': 2, 'int32': 4, 'int64': 8,
166  'char': 1, 'uint8': 1, 'uint16': 2, 'uint32': 4, 'uint64': 8}
167 
168 
169 
170 ############################################################
171 # Indented writer
172 ############################################################
173 
175 
176  def __init__(self, s):
177  self.str = s
178  self.indentation = 0
179  self.block_indent = False
180 
181  def write(self, s, indent=True, newline=True):
182  if not indent:
183  newline = False
184  if self.block_indent:
185  self.block_indent = False
186  else:
187  if newline:
188  self.str.write('\n')
189  if indent:
190  for i in range(self.indentation):
191  self.str.write(' ')
192  self.str.write(s)
193 
194  def newline(self):
195  self.str.write('\n')
196 
197  def inc_indent(self, inc=2):
198  self.indentation += inc
199 
200  def dec_indent(self, dec=2):
201  self.indentation -= dec
202 
203  def reset_indent(self):
204  self.indentation = 0
205 
206  def block_next_indent(self):
207  self.block_indent = True
208 
209 class Indent():
210 
211  def __init__(self, w, inc=2, indent_first=True):
212  self.writer = w
213  self.inc = inc
214  self.indent_first = indent_first
215 
216  def __enter__(self):
217  self.writer.inc_indent(self.inc)
218  if not self.indent_first:
219  self.writer.block_next_indent()
220 
221  def __exit__(self, type, val, traceback):
222  self.writer.dec_indent(self.inc)
223 
224 def write_begin(s, spec, is_service=False):
225  "Writes the beginning of the file: a comment saying it's auto-generated and the in-package form"
226 
227  s.write(';; Auto-generated. Do not edit!\n\n', newline=False)
228  suffix = 'srv' if is_service else 'msg'
229  if is_service:
230  spec.actual_name=spec.short_name
231  s.write('(when (boundp \'%s::%s)'%(spec.package, spec.actual_name))
232  s.write(' (if (not (find-package "%s"))'%(spec.package.upper()))
233  s.write(' (make-package "%s"))'%(spec.package.upper()))
234  s.write(' (shadow \'%s (find-package "%s")))'%(spec.actual_name, spec.package.upper()))
235  s.write('(unless (find-package "%s::%s")'%(spec.package.upper(), spec.actual_name.upper()))
236  s.write(' (make-package "%s::%s"))'%(spec.package.upper(), spec.actual_name.upper()))
237  if is_service:
238  s.write('(unless (find-package "%s::%sREQUEST")'%(spec.package.upper(), spec.actual_name.upper()))
239  s.write(' (make-package "%s::%sREQUEST"))'%(spec.package.upper(), spec.actual_name.upper()))
240  s.write('(unless (find-package "%s::%sRESPONSE")'%(spec.package.upper(), spec.actual_name.upper()))
241  s.write(' (make-package "%s::%sRESPONSE"))'%(spec.package.upper(), spec.actual_name.upper()))
242  s.write('')
243  s.write('(in-package "ROS")')
244  s.newline()
245 
246 def write_include(s, spec, is_srv=False):
247  if not is_srv:
248  s.write(';;//! \\htmlinclude %s.msg.html'%spec.actual_name, newline=False) # t2
249  for msg_type in sorted(set([parse_msg_type(field)[0] for field in spec.parsed_fields() if not field.is_builtin and parse_msg_type(field)[0] != spec.package])):
250  s.write('(if (not (find-package "%s"))'%msg_type.upper())
251  s.write(' (ros::roseus-add-msgs "%s"))'%msg_type)
252  s.newline()
253  s.newline()
254 
255 def write_slot_definition(s, field):
256  "Write the definition of a slot corresponding to a single message field"
257  s.write('_%s '%field.name, indent=False, newline=False)
258 
259 
260 def write_slot_argument(s, field):
261  "Write the key arguments of a slot corresponding to a single message field"
262  var = field.name
263  if field.is_builtin:
264  s.write('((:%s __%s) %s)'%(var, var, field_initvalue(field)))
265  else:
266  if field.is_array:
267  len = field.array_len or 0
268  s.write('((:%s __%s) (let (r) (dotimes (i %s) (push (instance %s :init) r)) r))'%(var, var, len, field_type(field))) ## FIX??? need to use len = f.array_len or 0
269  else:
270  s.write('((:%s __%s) (instance %s :init))'%(var, var, field_type(field)))
271 
272 def write_slot_initialize(s, field):
273  "Write the initialization of a slot corresponding to a single message field"
274  s.write('(setq _%s %s)'%(field.name, field_initform(field)))
275 
276 def write_defclass(s, spec):
277  "Writes the defclass that defines the message type"
278  s.write('(defclass %s::%s'%(spec.package, spec.actual_name))
279  with Indent(s):
280  s.write(':super ros::object')
281  s.write(':slots (')
282  with Indent(s, inc=1, indent_first=False):
283  for field in spec.parsed_fields():
284  write_slot_definition(s, field)
285  s.write('))', indent=False)
286  s.newline()
287 
288 def write_defmethod(s, spec):
289  s.write('(defmethod %s::%s'%(spec.package, spec.actual_name))
290  with Indent(s):
291  s.write('(:init')
292  with Indent(s, inc=1):
293  s.write('(&key')
294  with Indent(s, inc=1):
295  for field in spec.parsed_fields():
296  write_slot_argument(s, field)
297  s.write(')')
298  s.write('(send-super :init)')
299  for field in spec.parsed_fields():
300  write_slot_initialize(s, field)
301  s.write('self)')
302 
303 
304 def write_accessors(s, spec):
305  with Indent(s):
306  for field in spec.parsed_fields():
307  s.write('(:%s'%field.name)
308  var = '_%s'%field.name
309  with Indent(s, inc=1):
310  if field.is_builtin:
311  if field.type == "bool":
312  s.write('(&optional (_%s :null))'%var)
313  s.write('(if (not (eq _%s :null)) (setq %s _%s)) %s)'%(var,var,var,var))
314  else:
315  s.write('(&optional _%s)'%var)
316  s.write('(if _%s (setq %s _%s)) %s)'%(var,var,var,var))
317  else:
318  s.write('(&rest _%s)'%var)
319  s.write('(if (keywordp (car _%s))'%var)
320  s.write(' (send* %s _%s)'%(var,var))
321  with Indent(s, inc=2):
322  s.write('(progn')
323  s.write(' (if _%s (setq %s (car _%s)))'%(var,var,var))
324  s.write(' %s)))'%var)
325 
326 def write_serialize_length(s, v, is_array=False):
327  if is_array:
328  s.write('(write-long (length %s) s)'%(v))
329  else:
330  s.write('(write-long (length %s) s) (princ %s s)'%(v,v))
331 
332 
333 def write_serialize_bits(s, v, num_bytes):
334  if num_bytes == 1:
335  s.write('(write-byte %s s)'%v)
336  elif num_bytes == 2:
337  s.write('(write-word %s s)'%v)
338  elif num_bytes == 4:
339  s.write('(write-long %s s)'%v)
340  else:
341  s.write('\n', indent=False)
342  s.write('#+(or :alpha :irix6 :x86_64)', indent=False, newline=False)
343  s.write('(progn (sys::poke %s (send s :buffer) (send s :count) :long) (incf (stream-count s) 8))'%v)
344  s.write('\n', indent=False)
345  s.write('#-(or :alpha :irix6 :x86_64)', indent=False)
346  s.write('(cond ((and (class %s) (= (length (%s . bv)) 2)) ;; bignum'%(v,v))
347  s.write(' (write-long (ash (elt (%s . bv) 0) 0) s)'%v)
348  s.write(' (write-long (ash (elt (%s . bv) 1) -1) s))'%v)
349  s.write(' ((and (class %s) (= (length (%s . bv)) 1)) ;; big1'%(v,v))
350  s.write(' (write-long (elt (%s . bv) 0) s)'%v)
351  s.write(' (write-long (if (>= %s 0) 0 #xffffffff) s))'%v)
352  s.write(' (t ;; integer')
353  s.write(' (write-long %s s)(write-long (if (>= %s 0) 0 #xffffffff) s)))'%(v,v))
354 
355 
356 def write_serialize_bits_signed(s, v, num_bytes):
357  write_serialize_bits(s, v, num_bytes)
358 
360  if f.base_type == 'string':
362  elif f.base_type == 'float32':
363  s.write('(sys::poke %s (send s :buffer) (send s :count) :float) (incf (stream-count s) 4)'%v)
364  elif f.base_type == 'float64':
365  s.write('(sys::poke %s (send s :buffer) (send s :count) :double) (incf (stream-count s) 8)'%v)
366  elif f.base_type == 'bool':
367  s.write('(if %s (write-byte -1 s) (write-byte 0 s))'%v)
368  elif f.base_type in ['byte', 'char']:
369  s.write('(write-byte %s s)'%v)
370  elif f.base_type in ['duration', 'time']:
371  s.write('(write-long (send %s :sec) s) (write-long (send %s :nsec) s)'%(v,v))
372  elif is_signed_int(f.base_type):
373  write_serialize_bits_signed(s, v, NUM_BYTES[f.base_type])
374  elif is_unsigned_int(f.base_type):
375  write_serialize_bits(s, v, NUM_BYTES[f.base_type])
376  else:
377  raise ValueError('Unknown type: %s', f.base_type)
378 
380  s.write(';; %s _%s'%(f.type, f.name))
381  slot = '_%s'%f.name
382  var = slot
383  if f.is_array and f.base_type == 'uint8':
384  if not f.array_len:
385  s.write('(write-long (length %s) s)'%slot)
386  s.write('(princ %s s)'%slot)
387  elif f.is_array and is_string(f.base_type):
388  s.write('(write-long (length %s) s)'%slot)
389  s.write('(dolist (elem %s)'%slot)
390  var = 'elem'
391  elif f.is_array:
392  if not f.array_len:
393  write_serialize_length(s, slot, True)
394  if f.is_builtin and f.array_len:
395  s.write('(dotimes (i %s)'%f.array_len)
396  elif f.is_builtin and not f.array_len:
397  s.write('(dotimes (i (length %s))'%var)
398  else:
399  s.write('(dolist (elem %s)'%slot)
400  slot = 'elem'
401  var = '(elt %s i)'%var
402  s.block_next_indent()
403  s.write('')
404 
405  if f.is_array and f.base_type == 'uint8':
406  pass
407  elif f.is_builtin:
408  with Indent(s):
409  write_serialize_builtin(s, f, var)
410  else:
411  with Indent(s):
412  s.write('(send %s :serialize s)'%slot)
413 
414  if f.is_array and f.base_type != 'uint8':
415  s.write(' )')
416 
417 def write_serialize(s, spec):
418  """
419  Write the serialize method
420  """
421  with Indent(s):
422  s.write('(:serialize')
423  with Indent(s,inc=1):
424  s.write('(&optional strm)')
425  s.write('(let ((s (if strm strm')
426  s.write(' (make-string-output-stream (send self :serialization-length)))))')
427  with Indent(s):
428  for f in spec.parsed_fields():
430  s.write(';;')
431  s.write('(if (null strm) (get-output-stream-string s))))')
432 
433 def write_deserialize_length(s, f, v, is_array=False):
434  if is_array:
435  s.write('(let (n)') ## TODO should not be here
436  with Indent(s):
437  s.write('(setq n (sys::peek buf ptr- :integer)) (incf ptr- 4)')
438  s.write('(setq %s (let (r) (dotimes (i n) (push (instance %s :init) r)) r))'%(v,field_type(f)))
439  else:
440  set = 'setf' if v[0] == '(' else 'setq'
441  s.write('(let (n) (setq n (sys::peek buf ptr- :integer)) (incf ptr- 4) (%s %s (subseq buf ptr- (+ ptr- n))) (incf ptr- n))'%(set, v))
442 
443 def write_deserialize_bits(s, v, num_bytes):
444  if num_bytes == 1:
445  type = ':char'
446  elif num_bytes == 2:
447  type = ':short'
448  elif num_bytes == 4:
449  type = ':integer'
450  elif num_bytes == 8:
451  type = ':long'
452  s.write('')
453  return write_deserialize_bits_signed(s,v,num_bytes)
454  else:
455  raise ValueError('Unknown size: %s', num_bytes)
456 
457  set = 'setf' if v[0] == '(' else 'setq'
458  s.write('(%s %s (sys::peek buf ptr- %s)) (incf ptr- %s)'%(set,v,type,num_bytes))
459 
460 def write_deserialize_bits_signed(s, v, num_bytes):
461  if num_bytes in [1,2,4]:
462  write_deserialize_bits(s, v, num_bytes)
463  else:
464  s.write('\n', indent=False)
465  s.write('#+(or :alpha :irix6 :x86_64)', indent=False)
466  s.write(' (setf %s (prog1 (sys::peek buf ptr- :long) (incf ptr- 8)))\n'%v)
467  s.write('#-(or :alpha :irix6 :x86_64)', indent=False)
468  s.write(' (setf %s (let ((b0 (prog1 (sys::peek buf ptr- :integer) (incf ptr- 4)))'%v)
469  s.write(' (b1 (prog1 (sys::peek buf ptr- :integer) (incf ptr- 4))))')
470  s.write(' (cond ((= b1 -1) b0)')
471  s.write(' ((and (= b1 0)')
472  s.write(' (<= lisp::most-negative-fixnum b0 lisp::most-positive-fixnum))')
473  s.write(' b0)')
474  s.write(' ((= b1 0) (make-instance bignum :size 1 :bv (integer-vector b0)))')
475  s.write(' (t (make-instance bignum :size 2 :bv (integer-vector b0 (ash b1 1)))))))')
476 
478  set = 'setf' if v[0] == '(' else 'setq'
479  if f.base_type == 'string':
481  elif f.base_type == 'float32':
482  s.write('(%s %s (sys::peek buf ptr- :float)) (incf ptr- 4)'%(set, v))
483  elif f.base_type == 'float64':
484  s.write('(%s %s (sys::peek buf ptr- :double)) (incf ptr- 8)'%(set, v))
485  elif f.base_type == 'bool':
486  s.write('(%s %s (not (= 0 (sys::peek buf ptr- :char)))) (incf ptr- 1)'%(set, v))
487  elif f.base_type in ['duration', 'time']:
488  s.write('(send %s :sec (sys::peek buf ptr- :integer)) (incf ptr- 4) (send %s :nsec (sys::peek buf ptr- :integer)) (incf ptr- 4)'%(v,v))
489  elif is_signed_int(f.base_type):
490  write_deserialize_bits_signed(s, v, NUM_BYTES[f.base_type])
491  if NUM_BYTES[f.base_type] == 1: # if signed byte, we have to convert to -128-127
492  s.write('(if (> %s 127) (%s %s (- %s 256)))'%(v,set,v,v))
493  elif is_unsigned_int(f.base_type):
494  write_deserialize_bits(s, v, NUM_BYTES[f.base_type])
495  else:
496  raise ValueError('%s unknown'%f.base_type)
497 
498 def write_deserialize_field(s, f, pkg):
499  var = '_%s'%f.name
500  s.write(';; %s %s'%(f.type, var))
501  if f.is_array:
502  if f.is_builtin:
503  if f.base_type == 'uint8':
504  if f.array_len:
505  s.write('(setq %s (make-array %d :element-type :char))'%(var,f.array_len))
506  s.write('(replace %s buf :start2 ptr-) (incf ptr- %d)'%(var,f.array_len))
507  else:
508  s.write('(let ((n (sys::peek buf ptr- :integer))) (incf ptr- 4)')
509  s.write(' (setq %s (make-array n :element-type :char))'%var)
510  s.write(' (replace %s buf :start2 ptr-) (incf ptr- n))'%(var))
511  elif f.array_len:
512  s.write('(dotimes (i (length %s))'%var)
513  var = '(elt %s i)'%var
514  else:
515  if is_float(f.base_type) or is_integer(f.base_type) or is_string(f.base_type) or is_bool(f.base_type):
516  s.write('(let (n)')
517  with Indent(s):
518  s.write('(setq n (sys::peek buf ptr- :integer)) (incf ptr- 4)')
519  if is_string(f.base_type) or is_bool(f.base_type):
520  s.write('(setq %s (make-list n))'%var)
521  else:
522  s.write('(setq %s (instantiate %s-vector n))'%(var, lisp_type(f.base_type, f.is_array)))
523  s.write('(dotimes (i n)')
524  var = '(elt %s i)'%var
525  else:
526  write_deserialize_length(s, f, var, True)
527  var = 'elem-'
528  with Indent(s):
529  s.write('(dolist (%s _%s)'%(var, f.name))
530  else: # array but not builtin
531  if f.array_len:
532  s.write('(dotimes (i %s)'%f.array_len)
533  var = '(elt _%s i)'%f.name
534  else:
535  write_deserialize_length(s, f, var, True)
536  var = 'elem-'
537  with Indent(s):
538  s.write('(dolist (%s _%s)'%(var, f.name))
539  if f.is_array and f.base_type == 'uint8':
540  pass
541  elif f.is_builtin:
542  with Indent(s):
543  write_deserialize_builtin(s, f, var)
544  else:
545  with Indent(s):
546  s.write('(send %s :deserialize buf ptr-) (incf ptr- (send %s :serialization-length))'%(var, var))
547 
548  if f.is_array and not f.base_type == 'uint8':
549  with Indent(s):
550  if f.array_len:
551  s.write(')')
552  else:
553  s.write('))')
554 
555 
556 def write_deserialize(s, spec):
557  """
558  Write the deserialize method
559  """
560  with Indent(s):
561  s.write('(:deserialize')
562  with Indent(s,inc=1):
563  s.write('(buf &optional (ptr- 0))')
564  for f in spec.parsed_fields():
565  write_deserialize_field(s, f, spec.package)
566  s.write(';;')
567  s.write('self)')
568  s.write(')')
569  s.newline()
570 
571 def write_md5sum(s, msg_context, spec, parent=None):
572  md5sum = genmsg.compute_md5(msg_context, parent or spec)
573  s.write('(setf (get %s::%s :md5sum-) "%s")'%(spec.package, spec.actual_name, md5sum))
574 
575 def write_ros_datatype(s, spec):
576  s.write('(setf (get %s::%s :datatype-) "%s/%s")'%(spec.package, spec.actual_name, spec.package, spec.actual_name))
577 
578 def write_message_definition(s, msg_context, spec):
579  s.write('(setf (get %s::%s :definition-)'%(spec.package, spec.actual_name))
580  with Indent(s,6):
581  s.write('"')
582  definition = genmsg.compute_full_text(msg_context, spec)
583  lines = definition.split('\n')
584  for line in lines:
585  l = line.replace('\\', '\\\\')
586  l = l.replace('"', '\\"')
587  s.write('%s\n'%l, indent=False, newline=False)
588  s.write('")', newline=False)
589  s.write('\n\n')
590 
591 def write_service_definition(s, msg_context, spec, parent):
592  s.write('(setf (get %s::%s :definition-)'%(parent.package, parent.actual_name))
593  with Indent(s,6):
594  s.write('"')
595  for spec_service in [spec.request, spec.response]:
596  definition = genmsg.compute_full_text(msg_context, spec_service)
597  lines = definition.split('\n')
598  for line in lines[:-1]:
599  l = line.replace('\\', '\\\\')
600  l = l.replace('"', '\\"')
601  s.write('%s\n'%l, indent=False, newline=False)
602  if spec_service == spec.request:
603  s.write('---\n', indent=False, newline=False)
604  s.write('")', newline=False)
605 
606 def write_builtin_length(s, f, var='msg'):
607  if f.base_type in ['int8', 'uint8']:
608  s.write('1')
609  elif f.base_type in ['int16', 'uint16']:
610  s.write('2')
611  elif f.base_type in ['int32', 'uint32', 'float32']:
612  s.write('4')
613  elif f.base_type in ['int64', 'uint64', 'float64', 'duration', 'time']:
614  s.write('8')
615  elif f.base_type == 'string':
616  s.write('4 (length _%s)'%f.name)
617  elif f.base_type in ['bool', 'byte', 'char']:
618  s.write('1')
619  else:
620  raise ValueError('Unknown: %s', f.base_type)
621 
623  with Indent(s):
624  s.write('(:serialization-length')
625  with Indent(s, inc=1):
626  s.write('()')
627  s.write('(+')
628  with Indent(s, 1):
629  if not spec.parsed_fields():
630  s.write('0')
631  for field in spec.parsed_fields():
632  s.write(';; %s _%s'%(field.type, field.name))
633  if field.is_array:
634  if field.is_builtin and not is_string(field.base_type):
635  s.write('(* ')
636  else:
637  s.write('(apply #\'+ ')
638  s.block_next_indent()
639 
640  if field.is_builtin:
641  if not field.array_len:
642  if is_string(field.base_type):
643  s.write('(mapcar #\'(lambda (x) (+ 4 (length x))) _%s)) 4'%(field.name))
644  else:
645  write_builtin_length(s, field)
646  s.write('(length _%s)) 4'%field.name, newline=False)
647  else:
648  write_builtin_length(s, field)
649  s.write('%s)'%field.array_len, newline=False)
650  else:
651  if field.array_len:
652  s.write('(send-all _%s :serialization-length))'%field.name)
653  else:
654  s.write('(send-all _%s :serialization-length)) 4'%field.name)
655  else:
656  if field.is_builtin:
657  write_builtin_length(s, field)
658  else:
659  s.write('(send _%s :serialization-length)'%field.name)
660 
661  s.write('))')
662 
663 
664 def write_provide(s, msg_context, spec):
665  md5sum = genmsg.compute_md5(msg_context, spec)
666  s.write('(provide :%s/%s "%s")'%(spec.package, spec.actual_name,md5sum))
667  s.write('\n')
668 
669 def write_constants(s, spec):
670  if spec.constants:
671  for c in spec.constants:
672  s.write('(intern "*%s*" (find-package "%s::%s"))'%(c.name.upper(), spec.package.upper(), spec.actual_name.upper()))
673  s.write('(shadow \'*%s* (find-package "%s::%s"))'%(c.name.upper(), spec.package.upper(), spec.actual_name.upper()))
674  if c.type == 'string':
675  s.write('(defconstant %s::%s::*%s* "%s")'%(spec.package, spec.actual_name, c.name.upper(), c.val.replace('"', '\\"')))
676  elif c.type == 'bool':
677  s.write('(defconstant %s::%s::*%s* %s)'%(spec.package, spec.actual_name, c.name.upper(), "t" if c.val == True else "nil"))
678  else:
679  s.write('(defconstant %s::%s::*%s* %s)'%(spec.package, spec.actual_name, c.name.upper(), c.val))
680 
681 def write_srv_component(s, spec, context, parent):
682  spec.component_type='service'
683  write_constants(s, spec)
684  write_defclass(s, spec)
685  write_defmethod(s, spec)
686  write_accessors(s, spec)
688  write_serialize(s, spec)
689  write_deserialize(s, spec)
690 
691 def write_service_specific_methods(s, context, spec):
692  ### this should be move to previsou definition section ???
693  s.write('(defclass %s::%s'%(spec.package, spec.actual_name))
694  with Indent(s):
695  s.write(':super ros::object')
696  s.write(':slots ())')
697  s.newline()
698  write_md5sum(s, context, spec, parent=spec)
699  write_ros_datatype(s, spec)
700  s.write('(setf (get %s::%s :request) %s::%s)'%(spec.package, spec.actual_name, spec.request.package, spec.request.actual_name))
701  s.write('(setf (get %s::%s :response) %s::%s)'%(spec.package, spec.actual_name, spec.response.package, spec.response.actual_name))
702  s.newline()
703  s.write('(defmethod %s::%s'%(spec.request.package, spec.request.actual_name))
704  s.write(' (:response () (instance %s::%s :init)))'%(spec.response.package, spec.response.actual_name))
705  s.newline()
706  for spec_service in [spec.request, spec.response]:
707  write_md5sum(s, context, spec_service, parent=spec)
708  write_ros_datatype(s, spec_service)
709  write_service_definition(s, context, spec, spec_service)
710  s.newline()
711  s.write('\n')
712  write_provide(s, context, spec)
713  s.write('\n', newline=False)
714 
715 def generate_msg(pkg, files, out_dir, search_path):
716  """
717  Generate euslisp code for all messages in a package
718  """
719  msg_context = MsgContext.create_default()
720  for f in files:
721  f = os.path.abspath(f)
722  infile = os.path.basename(f)
723  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
724  spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
725  generate_msg_from_spec(msg_context, spec, search_path, out_dir, pkg)
726 
727 def generate_srv(pkg, files, out_dir, search_path):
728  """
729  Generate euslisp code for all services in a package
730  """
731  msg_context = MsgContext.create_default()
732  for f in files:
733  f = os.path.abspath(f)
734  infile = os.path.basename(f)
735  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
736  spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
737  generate_srv_from_spec(msg_context, spec, search_path, out_dir, pkg, f)
738 
739 def msg_list(pkg, search_path, ext):
740  dir_list = search_path[pkg]
741  files = []
742  for d in dir_list:
743  files.extend([f for f in os.listdir(d) if f.endswith(ext)])
744  return [f[:-len(ext)] for f in files]
745 
746 def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package):
747  """
748  Generate a message
749 
750  @param msg_path: The path to the .msg file
751  @type msg_path: str
752  """
753  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
754  spec.actual_name=spec.short_name
755  spec.component_type='message'
756  msgs = msg_list(package, search_path, '.msg')
757  for m in msgs:
758  genmsg.load_msg_by_type(msg_context, '%s/%s'%(package, m), search_path)
759 
760 
761  ########################################
762  # 1. Write the .l file
763  ########################################
764 
765  io = StringIO()
766  s = IndentedWriter(io)
767  write_begin(s, spec)
768  write_include(s, spec)
769  write_constants(s, spec)
770  write_defclass(s, spec)
771  write_defmethod(s, spec)
772  write_accessors(s, spec)
774  write_serialize(s, spec)
775  write_deserialize(s, spec)
776  write_md5sum(s, msg_context, spec)
777  write_ros_datatype(s, spec)
778  write_message_definition(s, msg_context, spec)
779  write_provide(s, msg_context, spec)
780 
781  if (not os.path.exists(output_dir)):
782  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
783  # another copy just created the directory
784  try:
785  os.makedirs(output_dir)
786  except OSError as e:
787  pass
788 
789  with open('%s/%s.l'%(output_dir, spec.short_name), 'w') as f:
790  f.write(io.getvalue() + "\n")
791  io.close()
792 
793 
794 # t0 most of this could probably be refactored into being shared with messages
795 def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path):
796  "Generate code from .srv file"
797  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
798  ext = '.srv'
799  srvs = [f[:-len(ext)] for f in os.listdir(os.path.dirname(path)) if f.endswith(ext)]
800  for s in srvs:
801  load_srv_from_file(msg_context, path, '%s/%s'%(package, s))
802 
803  ########################################
804  # 1. Write the .l file
805  ########################################
806 
807  io = StringIO()
808  s = IndentedWriter(io)
809  write_begin(s, spec, True)
810  write_include(s, spec.request, is_srv=True)
811  write_include(s, spec.response, is_srv=True)
812  spec.request.actual_name='%sRequest'%spec.short_name
813  spec.response.actual_name='%sResponse'%spec.short_name
814  write_srv_component(s, spec.request, msg_context, spec)
815  write_srv_component(s, spec.response, msg_context, spec)
816  write_service_specific_methods(s, msg_context, spec)
817 
818  with open('%s/%s.l'%(output_dir, spec.short_name), 'w') as f:
819  f.write(io.getvalue())
820  io.close()
821 
822 
def write_serialize_bits_signed(s, v, num_bytes)
Definition: generate.py:356
def write_service_specific_methods(s, context, spec)
Definition: generate.py:691
def __init__(self, w, inc=2, indent_first=True)
Definition: generate.py:211
def lisp_type(t, array)
Definition: generate.py:96
def inc_indent(self, inc=2)
Definition: generate.py:197
def generate_msg(pkg, files, out_dir, search_path)
Definition: generate.py:715
def is_unsigned_int(t)
Definition: generate.py:62
def write_deserialize_bits(s, v, num_bytes)
Definition: generate.py:443
def write(self, s, indent=True, newline=True)
Definition: generate.py:181
def write_md5sum(s, msg_context, spec, parent=None)
Definition: generate.py:571
def field_initvalue(f)
Definition: generate.py:123
def lisp_initvalue(t)
Definition: generate.py:137
def write_serialize_bits(s, v, num_bytes)
Definition: generate.py:333
def write_ros_datatype(s, spec)
Definition: generate.py:575
def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package)
Definition: generate.py:746
def write_begin(s, spec, is_service=False)
Definition: generate.py:224
def write_slot_definition(s, field)
Definition: generate.py:255
def write_message_definition(s, msg_context, spec)
Definition: generate.py:578
def parse_msg_type(f)
Definition: generate.py:84
def field_initform(f)
Definition: generate.py:112
def is_float(t)
Definition: generate.py:71
def write_deserialize_bits_signed(s, v, num_bytes)
Definition: generate.py:460
def write_serialize_field(s, f)
Definition: generate.py:379
def write_service_definition(s, msg_context, spec, parent)
Definition: generate.py:591
def msg_list(pkg, search_path, ext)
Definition: generate.py:739
def write_deserialize_length(s, f, v, is_array=False)
Definition: generate.py:433
def write_deserialize_field(s, f, pkg)
Definition: generate.py:498
def is_signed_int(t)
Definition: generate.py:59
def write_builtin_length(s, f, var='msg')
Definition: generate.py:606
def write_defmethod(s, spec)
Definition: generate.py:288
def dec_indent(self, dec=2)
Definition: generate.py:200
def generate_srv(pkg, files, out_dir, search_path)
Definition: generate.py:727
def write_slot_initialize(s, field)
Definition: generate.py:272
def is_integer(t)
Built in types.
Definition: generate.py:56
def __exit__(self, type, val, traceback)
Definition: generate.py:221
def write_serialize_length(s, v, is_array=False)
Definition: generate.py:326
def write_serialization_length(s, spec)
Definition: generate.py:622
def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path)
Definition: generate.py:795
def msg_type(f)
Definition: generate.py:91
def write_slot_argument(s, field)
Definition: generate.py:260
def write_srv_component(s, spec, context, parent)
Definition: generate.py:681
def write_constants(s, spec)
Definition: generate.py:669
def write_deserialize_builtin(s, f, v)
Definition: generate.py:477
def write_serialize_builtin(s, f, v)
Definition: generate.py:359
def field_type(f)
Definition: generate.py:77
def write_include(s, spec, is_srv=False)
Definition: generate.py:246
def lisp_initform(t)
Definition: generate.py:151
def is_time(t)
Definition: generate.py:74
def write_accessors(s, spec)
Definition: generate.py:304
def write_defclass(s, spec)
Definition: generate.py:276
def write_deserialize(s, spec)
Definition: generate.py:556
def write_provide(s, msg_context, spec)
Definition: generate.py:664
def write_serialize(s, spec)
Definition: generate.py:417
def is_string(t)
Definition: generate.py:68
def is_bool(t)
Definition: generate.py:65


geneus
Author(s): Kei Okada
autogenerated on Wed Jun 5 2019 19:32:31