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 
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 
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 
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  if field.array_len:
268  s.write('((:%s __%s) (let (r) (dotimes (i %s) (push (instance %s :init) r)) r))'%(var, var, field.array_len, field_type(field)))
269  else:
270  s.write('((:%s __%s) ())'%(var, var))
271  else:
272  s.write('((:%s __%s) (instance %s :init))'%(var, var, field_type(field)))
273 
274 def write_slot_initialize(s, field):
275  "Write the initialization of a slot corresponding to a single message field"
276  s.write('(setq _%s %s)'%(field.name, field_initform(field)))
277 
278 def write_defclass(s, spec):
279  "Writes the defclass that defines the message type"
280  s.write('(defclass %s::%s'%(spec.package, spec.actual_name))
281  with Indent(s):
282  s.write(':super ros::object')
283  s.write(':slots (')
284  with Indent(s, inc=1, indent_first=False):
285  for field in spec.parsed_fields():
286  write_slot_definition(s, field)
287  s.write('))', indent=False)
288  s.newline()
289 
290 def write_defmethod(s, spec):
291  s.write('(defmethod %s::%s'%(spec.package, spec.actual_name))
292  with Indent(s):
293  s.write('(:init')
294  with Indent(s, inc=1):
295  s.write('(&key')
296  with Indent(s, inc=1):
297  for field in spec.parsed_fields():
298  write_slot_argument(s, field)
299  s.write(')')
300  s.write('(send-super :init)')
301  for field in spec.parsed_fields():
302  write_slot_initialize(s, field)
303  s.write('self)')
304 
305 
306 def write_accessors(s, spec):
307  with Indent(s):
308  for field in spec.parsed_fields():
309  s.write('(:%s'%field.name)
310  var = '_%s'%field.name
311  with Indent(s, inc=1):
312  if field.is_builtin:
313  if field.type == "bool":
314  s.write('(&optional (_%s :null))'%var)
315  s.write('(if (not (eq _%s :null)) (setq %s _%s)) %s)'%(var,var,var,var))
316  else:
317  s.write('(&optional _%s)'%var)
318  s.write('(if _%s (setq %s _%s)) %s)'%(var,var,var,var))
319  else:
320  s.write('(&rest _%s)'%var)
321  s.write('(if (keywordp (car _%s))'%var)
322  s.write(' (send* %s _%s)'%(var,var))
323  with Indent(s, inc=2):
324  s.write('(progn')
325  s.write(' (if _%s (setq %s (car _%s)))'%(var,var,var))
326  s.write(' %s)))'%var)
327 
328 def write_serialize_length(s, v, is_array=False):
329  if is_array:
330  s.write('(write-long (length %s) s)'%(v))
331  else:
332  s.write('(write-long (length %s) s) (princ %s s)'%(v,v))
333 
334 
335 def write_serialize_bits(s, v, num_bytes):
336  if num_bytes == 1:
337  s.write('(write-byte %s s)'%v)
338  elif num_bytes == 2:
339  s.write('(write-word %s s)'%v)
340  elif num_bytes == 4:
341  s.write('(write-long %s s)'%v)
342  else:
343  s.write('\n', indent=False)
344  s.write('#+(or :alpha :irix6 :x86_64)', indent=False, newline=False)
345  s.write('(progn (sys::poke %s (send s :buffer) (send s :count) :long) (incf (stream-count s) 8))'%v)
346  s.write('\n', indent=False)
347  s.write('#-(or :alpha :irix6 :x86_64)', indent=False)
348  s.write('(cond ((and (class %s) (= (length (%s . bv)) 2)) ;; bignum'%(v,v))
349  s.write(' (write-long (ash (elt (%s . bv) 0) 0) s)'%v)
350  s.write(' (write-long (ash (elt (%s . bv) 1) -1) s))'%v)
351  s.write(' ((and (class %s) (= (length (%s . bv)) 1)) ;; big1'%(v,v))
352  s.write(' (write-long (elt (%s . bv) 0) s)'%v)
353  s.write(' (write-long (if (>= %s 0) 0 #xffffffff) s))'%v)
354  s.write(' (t ;; integer')
355  s.write(' (write-long %s s)(write-long (if (>= %s 0) 0 #xffffffff) s)))'%(v,v))
356 
357 
358 def write_serialize_bits_signed(s, v, num_bytes):
359  write_serialize_bits(s, v, num_bytes)
360 
362  if f.base_type == 'string':
364  elif f.base_type == 'float32':
365  s.write('(sys::poke %s (send s :buffer) (send s :count) :float) (incf (stream-count s) 4)'%v)
366  elif f.base_type == 'float64':
367  s.write('(sys::poke %s (send s :buffer) (send s :count) :double) (incf (stream-count s) 8)'%v)
368  elif f.base_type == 'bool':
369  s.write('(if %s (write-byte -1 s) (write-byte 0 s))'%v)
370  elif f.base_type in ['byte', 'char']:
371  s.write('(write-byte %s s)'%v)
372  elif f.base_type in ['duration', 'time']:
373  s.write('(write-long (send %s :sec) s) (write-long (send %s :nsec) s)'%(v,v))
374  elif is_signed_int(f.base_type):
375  write_serialize_bits_signed(s, v, NUM_BYTES[f.base_type])
376  elif is_unsigned_int(f.base_type):
377  write_serialize_bits(s, v, NUM_BYTES[f.base_type])
378  else:
379  raise ValueError('Unknown type: %s', f.base_type)
380 
382  s.write(';; %s _%s'%(f.type, f.name))
383  slot = '_%s'%f.name
384  var = slot
385  if f.is_array and f.base_type == 'uint8':
386  if not f.array_len:
387  s.write('(write-long (length %s) s)'%slot)
388  s.write('(princ %s s)'%slot)
389  elif f.is_array and is_string(f.base_type):
390  s.write('(write-long (length %s) s)'%slot)
391  s.write('(dolist (elem %s)'%slot)
392  var = 'elem'
393  elif f.is_array:
394  if not f.array_len:
395  write_serialize_length(s, slot, True)
396  if f.is_builtin and f.array_len:
397  s.write('(dotimes (i %s)'%f.array_len)
398  elif f.is_builtin and not f.array_len:
399  s.write('(dotimes (i (length %s))'%var)
400  else:
401  s.write('(dolist (elem %s)'%slot)
402  slot = 'elem'
403  var = '(elt %s i)'%var
404  s.block_next_indent()
405  s.write('')
406 
407  if f.is_array and f.base_type == 'uint8':
408  pass
409  elif f.is_builtin:
410  with Indent(s):
411  write_serialize_builtin(s, f, var)
412  else:
413  with Indent(s):
414  s.write('(send %s :serialize s)'%slot)
415 
416  if f.is_array and f.base_type != 'uint8':
417  s.write(' )')
418 
419 def write_serialize(s, spec):
420  """
421  Write the serialize method
422  """
423  with Indent(s):
424  s.write('(:serialize')
425  with Indent(s,inc=1):
426  s.write('(&optional strm)')
427  s.write('(let ((s (if strm strm')
428  s.write(' (make-string-output-stream (send self :serialization-length)))))')
429  with Indent(s):
430  for f in spec.parsed_fields():
432  s.write(';;')
433  s.write('(if (null strm) (get-output-stream-string s))))')
434 
435 def write_deserialize_length(s, f, v, is_array=False):
436  if is_array:
437  s.write('(let (n)')
438  with Indent(s):
439  s.write('(setq n (sys::peek buf ptr- :integer)) (incf ptr- 4)')
440  s.write('(setq %s (let (r) (dotimes (i n) (push (instance %s :init) r)) r))'%(v,field_type(f)))
441  else:
442  set = 'setf' if v[0] == '(' else 'setq'
443  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))
444 
445 def write_deserialize_bits(s, v, num_bytes):
446  if num_bytes == 1:
447  type = ':char'
448  elif num_bytes == 2:
449  type = ':short'
450  elif num_bytes == 4:
451  type = ':integer'
452  elif num_bytes == 8:
453  type = ':long'
454  s.write('')
455  return write_deserialize_bits_signed(s,v,num_bytes)
456  else:
457  raise ValueError('Unknown size: %s', num_bytes)
458 
459  set = 'setf' if v[0] == '(' else 'setq'
460  s.write('(%s %s (sys::peek buf ptr- %s)) (incf ptr- %s)'%(set,v,type,num_bytes))
461 
462 def write_deserialize_bits_signed(s, v, num_bytes):
463  if num_bytes in [1,2,4]:
464  write_deserialize_bits(s, v, num_bytes)
465  else:
466  s.write('\n', indent=False)
467  s.write('#+(or :alpha :irix6 :x86_64)', indent=False)
468  s.write(' (setf %s (prog1 (sys::peek buf ptr- :long) (incf ptr- 8)))\n'%v)
469  s.write('#-(or :alpha :irix6 :x86_64)', indent=False)
470  s.write(' (setf %s (let ((b0 (prog1 (sys::peek buf ptr- :integer) (incf ptr- 4)))'%v)
471  s.write(' (b1 (prog1 (sys::peek buf ptr- :integer) (incf ptr- 4))))')
472  s.write(' (cond ((= b1 -1) b0)')
473  s.write(' ((and (= b1 0)')
474  s.write(' (<= lisp::most-negative-fixnum b0 lisp::most-positive-fixnum))')
475  s.write(' b0)')
476  s.write(' ((= b1 0) (make-instance bignum :size 1 :bv (integer-vector b0)))')
477  s.write(' (t (make-instance bignum :size 2 :bv (integer-vector b0 (ash b1 1)))))))')
478 
480  set = 'setf' if v[0] == '(' else 'setq'
481  if f.base_type == 'string':
483  elif f.base_type == 'float32':
484  s.write('(%s %s (sys::peek buf ptr- :float)) (incf ptr- 4)'%(set, v))
485  elif f.base_type == 'float64':
486  s.write('(%s %s (sys::peek buf ptr- :double)) (incf ptr- 8)'%(set, v))
487  elif f.base_type == 'bool':
488  s.write('(%s %s (not (= 0 (sys::peek buf ptr- :char)))) (incf ptr- 1)'%(set, v))
489  elif f.base_type in ['duration', 'time']:
490  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))
491  elif is_signed_int(f.base_type):
492  write_deserialize_bits_signed(s, v, NUM_BYTES[f.base_type])
493  if NUM_BYTES[f.base_type] == 1: # if signed byte, we have to convert to -128-127
494  s.write('(if (> %s 127) (%s %s (- %s 256)))'%(v,set,v,v))
495  elif is_unsigned_int(f.base_type):
496  write_deserialize_bits(s, v, NUM_BYTES[f.base_type])
497  else:
498  raise ValueError('%s unknown'%f.base_type)
499 
500 def write_deserialize_field(s, f, pkg):
501  var = '_%s'%f.name
502  s.write(';; %s %s'%(f.type, var))
503  if f.is_array:
504  if f.is_builtin:
505  if f.base_type == 'uint8':
506  if f.array_len:
507  s.write('(setq %s (make-array %d :element-type :char))'%(var,f.array_len))
508  s.write('(replace %s buf :start2 ptr-) (incf ptr- %d)'%(var,f.array_len))
509  else:
510  s.write('(let ((n (sys::peek buf ptr- :integer))) (incf ptr- 4)')
511  s.write(' (setq %s (make-array n :element-type :char))'%var)
512  s.write(' (replace %s buf :start2 ptr-) (incf ptr- n))'%(var))
513  elif f.array_len:
514  s.write('(dotimes (i (length %s))'%var)
515  var = '(elt %s i)'%var
516  else:
517  if is_float(f.base_type) or is_integer(f.base_type) or is_string(f.base_type) or is_bool(f.base_type):
518  s.write('(let (n)')
519  with Indent(s):
520  s.write('(setq n (sys::peek buf ptr- :integer)) (incf ptr- 4)')
521  if is_string(f.base_type) or is_bool(f.base_type):
522  s.write('(setq %s (make-list n))'%var)
523  else:
524  s.write('(setq %s (instantiate %s-vector n))'%(var, lisp_type(f.base_type, f.is_array)))
525  s.write('(dotimes (i n)')
526  var = '(elt %s i)'%var
527  else:
528  write_deserialize_length(s, f, var, True)
529  var = 'elem-'
530  with Indent(s):
531  s.write('(dolist (%s _%s)'%(var, f.name))
532  else: # array but not builtin
533  if f.array_len:
534  s.write('(dotimes (i %s)'%f.array_len)
535  var = '(elt _%s i)'%f.name
536  else:
537  write_deserialize_length(s, f, var, True)
538  var = 'elem-'
539  with Indent(s):
540  s.write('(dolist (%s _%s)'%(var, f.name))
541  if f.is_array and f.base_type == 'uint8':
542  pass
543  elif f.is_builtin:
544  with Indent(s):
545  write_deserialize_builtin(s, f, var)
546  else:
547  with Indent(s):
548  s.write('(send %s :deserialize buf ptr-) (incf ptr- (send %s :serialization-length))'%(var, var))
549 
550  if f.is_array and not f.base_type == 'uint8':
551  with Indent(s):
552  if f.array_len:
553  s.write(')')
554  else:
555  s.write('))')
556 
557 
558 def write_deserialize(s, spec):
559  """
560  Write the deserialize method
561  """
562  with Indent(s):
563  s.write('(:deserialize')
564  with Indent(s,inc=1):
565  s.write('(buf &optional (ptr- 0))')
566  for f in spec.parsed_fields():
567  write_deserialize_field(s, f, spec.package)
568  s.write(';;')
569  s.write('self)')
570  s.write(')')
571  s.newline()
572 
573 def write_md5sum(s, msg_context, spec, parent=None):
574  md5sum = genmsg.compute_md5(msg_context, parent or spec)
575  s.write('(setf (get %s::%s :md5sum-) "%s")'%(spec.package, spec.actual_name, md5sum))
576 
577 def write_ros_datatype(s, spec):
578  s.write('(setf (get %s::%s :datatype-) "%s/%s")'%(spec.package, spec.actual_name, spec.package, spec.actual_name))
579 
580 def write_message_definition(s, msg_context, spec):
581  s.write('(setf (get %s::%s :definition-)'%(spec.package, spec.actual_name))
582  with Indent(s,6):
583  s.write('"')
584  definition = genmsg.compute_full_text(msg_context, spec)
585  lines = definition.split('\n')
586  for line in lines:
587  l = line.replace('\\', '\\\\')
588  l = l.replace('"', '\\"')
589  s.write('%s\n'%l, indent=False, newline=False)
590  s.write('")', newline=False)
591  s.write('\n\n')
592 
593 def write_service_definition(s, msg_context, spec, parent):
594  s.write('(setf (get %s::%s :definition-)'%(parent.package, parent.actual_name))
595  with Indent(s,6):
596  s.write('"')
597  for spec_service in [spec.request, spec.response]:
598  definition = genmsg.compute_full_text(msg_context, spec_service)
599  lines = definition.split('\n')
600  for line in lines[:-1]:
601  l = line.replace('\\', '\\\\')
602  l = l.replace('"', '\\"')
603  s.write('%s\n'%l, indent=False, newline=False)
604  if spec_service == spec.request:
605  s.write('---\n', indent=False, newline=False)
606  s.write('")', newline=False)
607 
608 def write_builtin_length(s, f, var='msg'):
609  if f.base_type in ['int8', 'uint8']:
610  s.write('1')
611  elif f.base_type in ['int16', 'uint16']:
612  s.write('2')
613  elif f.base_type in ['int32', 'uint32', 'float32']:
614  s.write('4')
615  elif f.base_type in ['int64', 'uint64', 'float64', 'duration', 'time']:
616  s.write('8')
617  elif f.base_type == 'string':
618  s.write('4 (length _%s)'%f.name)
619  elif f.base_type in ['bool', 'byte', 'char']:
620  s.write('1')
621  else:
622  raise ValueError('Unknown: %s', f.base_type)
623 
625  with Indent(s):
626  s.write('(:serialization-length')
627  with Indent(s, inc=1):
628  s.write('()')
629  s.write('(+')
630  with Indent(s, 1):
631  if not spec.parsed_fields():
632  s.write('0')
633  for field in spec.parsed_fields():
634  s.write(';; %s _%s'%(field.type, field.name))
635  if field.is_array:
636  if field.is_builtin and not is_string(field.base_type):
637  s.write('(* ')
638  else:
639  s.write('(apply #\'+ ')
640  s.block_next_indent()
641 
642  if field.is_builtin:
643  if not field.array_len:
644  if is_string(field.base_type):
645  s.write('(mapcar #\'(lambda (x) (+ 4 (length x))) _%s)) 4'%(field.name))
646  else:
647  write_builtin_length(s, field)
648  s.write('(length _%s)) 4'%field.name, newline=False)
649  else:
650  write_builtin_length(s, field)
651  s.write('%s)'%field.array_len, newline=False)
652  else:
653  if field.array_len:
654  s.write('(send-all _%s :serialization-length))'%field.name)
655  else:
656  s.write('(send-all _%s :serialization-length)) 4'%field.name)
657  else:
658  if field.is_builtin:
659  write_builtin_length(s, field)
660  else:
661  s.write('(send _%s :serialization-length)'%field.name)
662 
663  s.write('))')
664 
665 
666 def write_provide(s, msg_context, spec):
667  md5sum = genmsg.compute_md5(msg_context, spec)
668  s.write('(provide :%s/%s "%s")'%(spec.package, spec.actual_name,md5sum))
669  s.write('\n')
670 
671 def write_constants(s, spec):
672  if spec.constants:
673  for c in spec.constants:
674  s.write('(intern "*%s*" (find-package "%s::%s"))'%(c.name.upper(), spec.package.upper(), spec.actual_name.upper()))
675  s.write('(shadow \'*%s* (find-package "%s::%s"))'%(c.name.upper(), spec.package.upper(), spec.actual_name.upper()))
676  if c.type == 'string':
677  s.write('(defconstant %s::%s::*%s* "%s")'%(spec.package, spec.actual_name, c.name.upper(), c.val.replace('"', '\\"')))
678  elif c.type == 'bool':
679  s.write('(defconstant %s::%s::*%s* %s)'%(spec.package, spec.actual_name, c.name.upper(), "t" if c.val == True else "nil"))
680  else:
681  s.write('(defconstant %s::%s::*%s* %s)'%(spec.package, spec.actual_name, c.name.upper(), c.val))
682  s.write('')
683  s.write('(defun %s::%s-to-symbol (const)'%(spec.package, spec.actual_name))
684  s.write(' (cond')
685  for c in [c for c in spec.constants if is_integer(c.type)]:
686  s.write(" ((= const %s) '%s::%s::*%s*)"%(c.val, spec.package, spec.actual_name, c.name))
687  s.write(' (t nil)))')
688  s.write('')
689 
690 def write_srv_component(s, spec, context, parent):
691  spec.component_type='service'
692  write_constants(s, spec)
693  write_defclass(s, spec)
694  write_defmethod(s, spec)
695  write_accessors(s, spec)
697  write_serialize(s, spec)
698  write_deserialize(s, spec)
699 
700 def write_service_specific_methods(s, context, spec):
701 
702  s.write('(defclass %s::%s'%(spec.package, spec.actual_name))
703  with Indent(s):
704  s.write(':super ros::object')
705  s.write(':slots ())')
706  s.newline()
707  write_md5sum(s, context, spec, parent=spec)
708  write_ros_datatype(s, spec)
709  s.write('(setf (get %s::%s :request) %s::%s)'%(spec.package, spec.actual_name, spec.request.package, spec.request.actual_name))
710  s.write('(setf (get %s::%s :response) %s::%s)'%(spec.package, spec.actual_name, spec.response.package, spec.response.actual_name))
711  s.newline()
712  s.write('(defmethod %s::%s'%(spec.request.package, spec.request.actual_name))
713  s.write(' (:response () (instance %s::%s :init)))'%(spec.response.package, spec.response.actual_name))
714  s.newline()
715  for spec_service in [spec.request, spec.response]:
716  write_md5sum(s, context, spec_service, parent=spec)
717  write_ros_datatype(s, spec_service)
718  write_service_definition(s, context, spec, spec_service)
719  s.newline()
720  s.write('\n')
721  write_provide(s, context, spec)
722  s.write('\n', newline=False)
723 
724 def generate_msg(pkg, files, out_dir, search_path):
725  """
726  Generate euslisp code for all messages in a package
727  """
728  msg_context = MsgContext.create_default()
729  for f in files:
730  f = os.path.abspath(f)
731  infile = os.path.basename(f)
732  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
733  spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
734  generate_msg_from_spec(msg_context, spec, search_path, out_dir, pkg)
735 
736 def generate_srv(pkg, files, out_dir, search_path):
737  """
738  Generate euslisp code for all services in a package
739  """
740  msg_context = MsgContext.create_default()
741  for f in files:
742  f = os.path.abspath(f)
743  infile = os.path.basename(f)
744  full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
745  spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
746  generate_srv_from_spec(msg_context, spec, search_path, out_dir, pkg, f)
747 
748 def msg_list(pkg, search_path, ext):
749  dir_list = search_path[pkg]
750  files = []
751  for d in dir_list:
752  files.extend([f for f in os.listdir(d) if f.endswith(ext)])
753  return [f[:-len(ext)] for f in files]
754 
755 def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package):
756  """
757  Generate a message
758 
759  @param msg_path: The path to the .msg file
760  @type msg_path: str
761  """
762  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
763  spec.actual_name=spec.short_name
764  spec.component_type='message'
765  msgs = msg_list(package, search_path, '.msg')
766  for m in msgs:
767  genmsg.load_msg_by_type(msg_context, '%s/%s'%(package, m), search_path)
768 
769 
770 
773 
774  io = StringIO()
775  s = IndentedWriter(io)
776  write_begin(s, spec)
777  write_include(s, spec)
778  write_constants(s, spec)
779  write_defclass(s, spec)
780  write_defmethod(s, spec)
781  write_accessors(s, spec)
783  write_serialize(s, spec)
784  write_deserialize(s, spec)
785  write_md5sum(s, msg_context, spec)
786  write_ros_datatype(s, spec)
787  write_message_definition(s, msg_context, spec)
788  write_provide(s, msg_context, spec)
789 
790  if (not os.path.exists(output_dir)):
791  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
792  # another copy just created the directory
793  try:
794  os.makedirs(output_dir)
795  except OSError as e:
796  pass
797 
798  with open('%s/%s.l'%(output_dir, spec.short_name), 'w') as f:
799  f.write(io.getvalue() + "\n")
800  io.close()
801 
802 
803 # t0 most of this could probably be refactored into being shared with messages
804 def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path):
805  "Generate code from .srv file"
806  genmsg.msg_loader.load_depends(msg_context, spec, search_path)
807  ext = '.srv'
808  srvs = [f[:-len(ext)] for f in os.listdir(os.path.dirname(path)) if f.endswith(ext)]
809  for s in srvs:
810  load_srv_from_file(msg_context, path, '%s/%s'%(package, s))
811 
812 
815 
816  io = StringIO()
817  s = IndentedWriter(io)
818  write_begin(s, spec, True)
819  write_include(s, spec.request, is_srv=True)
820  write_include(s, spec.response, is_srv=True)
821  spec.request.actual_name='%sRequest'%spec.short_name
822  spec.response.actual_name='%sResponse'%spec.short_name
823  write_srv_component(s, spec.request, msg_context, spec)
824  write_srv_component(s, spec.response, msg_context, spec)
825  write_service_specific_methods(s, msg_context, spec)
826 
827  with open('%s/%s.l'%(output_dir, spec.short_name), 'w') as f:
828  f.write(io.getvalue())
829  io.close()
830 
831 
def write_serialize_bits_signed(s, v, num_bytes)
Definition: generate.py:358
def write_service_specific_methods(s, context, spec)
Definition: generate.py:700
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:724
def is_unsigned_int(t)
Definition: generate.py:62
def write_deserialize_bits(s, v, num_bytes)
Definition: generate.py:445
def write(self, s, indent=True, newline=True)
Definition: generate.py:181
def write_md5sum(s, msg_context, spec, parent=None)
Definition: generate.py:573
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:335
def write_ros_datatype(s, spec)
Definition: generate.py:577
def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package)
Definition: generate.py:755
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:580
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:462
def write_serialize_field(s, f)
Definition: generate.py:381
def write_service_definition(s, msg_context, spec, parent)
Definition: generate.py:593
def msg_list(pkg, search_path, ext)
Definition: generate.py:748
def write_deserialize_length(s, f, v, is_array=False)
Definition: generate.py:435
def write_deserialize_field(s, f, pkg)
Definition: generate.py:500
def is_signed_int(t)
Definition: generate.py:59
def write_builtin_length(s, f, var='msg')
Definition: generate.py:608
def write_defmethod(s, spec)
Definition: generate.py:290
def dec_indent(self, dec=2)
Definition: generate.py:200
def generate_srv(pkg, files, out_dir, search_path)
Definition: generate.py:736
def write_slot_initialize(s, field)
Definition: generate.py:274
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:328
def write_serialization_length(s, spec)
Definition: generate.py:624
def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path)
Definition: generate.py:804
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:690
def write_constants(s, spec)
Definition: generate.py:671
def write_deserialize_builtin(s, f, v)
Definition: generate.py:479
def write_serialize_builtin(s, f, v)
Definition: generate.py:361
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:306
def write_defclass(s, spec)
Definition: generate.py:278
def write_deserialize(s, spec)
Definition: generate.py:558
def write_provide(s, msg_context, spec)
Definition: generate.py:666
def write_serialize(s, spec)
Definition: generate.py:419
def is_string(t)
Definition: generate.py:68
def is_bool(t)
Definition: generate.py:65


geneus
Author(s): Kei Okada
autogenerated on Mon Feb 28 2022 22:23:00