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
 
   56     from cStringIO 
import StringIO 
 
   58     from io 
import StringIO 
 
   65     return t 
in [
'int8', 
'uint8', 
'int16', 
'uint16']
 
   68     return is_fixnum(t) 
or t 
in [
'byte', 
'char', 
'int32', 
'uint32', 
'int64', 
'uint64'] 
 
   71     return t 
in [
'int8', 
'int16', 
'int32', 
'int64']
 
   74     return t 
in [
'uint8', 
'uint16', 
'uint32', 
'uint64']
 
   83     return t 
in [
'float16', 
'float32', 
'float64']
 
   86     return t 
in [
'time', 
'duration']
 
   94         return '(cl:vector %s)'%elt_type
 
   99     if f.base_type == 
'Header':
 
  100         return (
'std_msgs', 
'Header')
 
  102         return f.base_type.split(
'/')
 
  107     return '%s-msg:%s'%(pkg, msg)
 
  123         raise ValueError(
'%s is not a recognized primitive type'%t)
 
  130         initform = 
'(cl:make-instance \'%s)'%
msg_type(f)
 
  133         len = f.array_len 
or 0
 
  134         return '(cl:make-array %s :element-type \'%s :initial-element %s)'%(len, elt_type, initform)
 
  150         raise ValueError(
'%s is not a recognized primitive type'%t)
 
  152 NUM_BYTES = {
'int8': 1, 
'int16': 2, 
'int32': 4, 
'int64': 8,
 
  153              'uint8': 1, 
'uint16': 2, 
'uint32': 4, 
'uint64': 8}
 
  168     def write(self, s, indent=True, newline=True):
 
  206             self.
writer.block_next_indent()
 
  214     "Writes the beginning of the file: a comment saying it's auto-generated and the in-package form" 
  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)
 
  222     s.write(
';//! \\htmlinclude %s.msg.html\n'%spec.actual_name, newline=
False) 
 
  225     "Write the definition of a slot corresponding to a single message field" 
  227     s.write(
'(%s'%field.name)
 
  229         s.write(
':reader %s'%field.name)
 
  230         s.write(
':initarg :%s'%field.name)
 
  232     i = 0 
if field.is_array 
else 1 
 
  237     suffix = 
'srv' if spec.component_type == 
'service' else 'msg' 
  238     for field 
in spec.parsed_fields():
 
  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)))
 
  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)
 
  249     "Writes the defclass that defines the message type" 
  252     suffix = 
'srv' if spec.component_type == 
'service' else 'msg' 
  253     s.write(
'(cl:defclass %s (roslisp-msg-protocol:ros-message)'%cl)
 
  256         with Indent(s, inc=1, indent_first=
False):
 
  257             for field 
in spec.parsed_fields():
 
  259         s.write(
')', indent=
False)
 
  262     s.write(
'(cl:defclass %s (%s)'%(new_cl, cl))
 
  266     s.write(
'(cl:defmethod cl:initialize-instance :after ((m %s) cl:&rest args)'%cl)
 
  268         s.write(
'(cl:declare (cl:ignorable args))')
 
  269         s.write(
'(cl:unless (cl:typep m \'%s)'%new_cl)
 
  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))
 
  277     Return the CLOS class name for this message type 
  279     return '<%s>'%spec.actual_name
 
  282     return spec.actual_name
 
  287     var = 
'__ros_arr_len' if is_array 
else '__ros_str_len' 
  289     s.write(
'(cl:let ((%s (cl:length %s)))'%(var, v))
 
  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)
 
  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))
 
  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))
 
  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)
 
  320     elif f.base_type == 
'float64':
 
  321         s.write(
'(cl:let ((bits %s))'%
'(roslisp-utils:encode-double-float-bits %s)'%v)
 
  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))
 
  341         raise ValueError(
'Unknown type: %s', f.base_type)
 
  344     slot = 
'(cl:slot-value msg \'%s)'%f.name
 
  348         s.write(
'(cl:map cl:nil #\'(cl:lambda (ele) ')
 
  350         s.block_next_indent()
 
  359         to_write = slot 
if lookup_slot 
else var 
 
  360         s.write(
'(roslisp-msg-protocol:serialize %s ostream)'%to_write)
 
  368     Write the serialize method 
  370     s.write(
'(cl:defmethod roslisp-msg-protocol:serialize ((msg %s) ostream)'%
message_class(spec))
 
  372         s.write(
'"Serializes a message object of type \'%s"'%
message_class(spec))
 
  373         for f 
in spec.parsed_fields():
 
  380     var = 
'__ros_arr_len' if is_array 
else '__ros_str_len' 
  381     s.write(
'(cl:let ((%s 0))'%var)
 
  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))
 
  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))
 
  391     s.write(
'(cl:let ((unsigned 0))')
 
  392     num_bits = 8*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))
 
  400     if f.base_type == 
'string':
 
  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)')
 
  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))')
 
  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))')
 
  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))')
 
  426             s.write(
'(cl:setf %s (cl:+ (cl:coerce __sec \'cl:double-float) (cl:/ __nsec 1e9))))'%v)
 
  432         raise ValueError(
'%s unknown'%f.base_type)
 
  436     slot = 
'(cl:slot-value msg \'%s)'%f.name
 
  441             length = 
'__ros_arr_len' 
  443             length = 
'%s'%f.array_len
 
  445         s.write(
'(cl:setf %s (cl:make-array %s))'%(slot, length))
 
  446         s.write(
'(cl:let ((vals %s))'%slot) 
 
  447         var = 
'(cl:aref vals i)' 
  449             s.write(
'(cl:dotimes (i %s)'%length)
 
  457                 s.write(
'(cl:setf %s (cl:make-instance \'%s))'%(var, 
msg_type(f)))
 
  458         s.write(
'(roslisp-msg-protocol:deserialize %s istream)'%var)
 
  468     Write the deserialize method 
  470     s.write(
'(cl:defmethod roslisp-msg-protocol:deserialize ((msg %s) istream)'%
message_class(spec))
 
  472         s.write(
'"Deserializes a message object of type \'%s"'%
message_class(spec))
 
  473         for f 
in spec.parsed_fields():
 
  479     "Write the _package.lisp file" 
  480     s.write(
'(cl:defpackage %s-msg'%pkg, 
False)
 
  487                 s.write(
'"%s"'%msg_class.upper())
 
  488                 s.write(
'"%s"'%m.upper())
 
  492     "Write the _package.lisp file for a service directory" 
  493     s.write(
'(cl:defpackage %s-srv'%pkg, 
False)
 
  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())
 
  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):
 
  515         s.write(
':components ((:file "_package")')
 
  518                 s.write(
'(:file "%s" :depends-on ("_package_%s"))'%(name, name))
 
  519                 s.write(
'(:file "_package_%s" :depends-on ("_package"))'%name)
 
  525     s.write(
'(cl:in-package :asdf)')
 
  527     s.write(
'(defsystem "%s-srv"'%pkg)
 
  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():
 
  538         for f 
in resp_spec.parsed_fields():
 
  547     s.write(
'(cl:in-package :asdf)')
 
  549     s.write(
'(defsystem "%s-msg"'%pkg)
 
  554         spec = context.get_registered(
'%s/%s'%(pkg, m))
 
  555         for f 
in spec.parsed_fields():
 
  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 \'(')
 
  570         fields = spec.request.parsed_fields()[:]
 
  571         fields.extend(spec.response.parsed_fields())
 
  573         fields = spec.parsed_fields()
 
  575     with Indent(s, inc=10, indent_first=
False):
 
  577             accessor = 
'%s-val'%f.name
 
  578             s.write(
'%s'%accessor.upper())
 
  579             s.write(
'%s'%f.name.upper())
 
  585         s.write(
'(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%c)
 
  587             s.write(
'"Returns string type for a %s object of type \'%s"'%(spec.component_type, c))
 
  588             s.write(
'"%s")'%spec.full_name)
 
  591     md5sum = genmsg.compute_md5(msg_context, parent 
or spec)
 
  593         s.write(
'(cl:defmethod roslisp-msg-protocol:md5sum ((type (cl:eql \'%s)))'%c)
 
  596             s.write(
'"Returns md5sum for a message object of type \'%s"'%c)
 
  597             s.write(
'"%s")'%md5sum)
 
  601         s.write(
'(cl:defmethod roslisp-msg-protocol:message-definition ((type (cl:eql \'%s)))'%c)
 
  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')
 
  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)
 
  616     if f.base_type 
in [
'int8', 
'uint8']:
 
  618     elif f.base_type 
in [
'int16', 
'uint16']:
 
  620     elif f.base_type 
in [
'int32', 
'uint32', 
'float32']:
 
  622     elif f.base_type 
in [
'int64', 
'uint64', 
'float64', 
'duration', 
'time']:
 
  624     elif f.base_type == 
'string':
 
  625         s.write(
'4 (cl:length %s)'%var)
 
  626     elif f.base_type 
in [
'bool', 
'byte', 
'char']:
 
  629         raise ValueError(
'Unknown: %s', f.base_type)
 
  633     s.write(
'(cl:defmethod roslisp-msg-protocol:serialization-length ((msg %s))'%c)
 
  637             for field 
in spec.parsed_fields():
 
  638                 slot = 
'(cl:slot-value msg \'%s)'%field.name
 
  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))
 
  643                     s.block_next_indent()
 
  650                     s.write(
'(roslisp-msg-protocol:serialization-length %s)'%var)
 
  653                     s.write(
')))', 
False)
 
  659     s.write(
'(cl:defmethod roslisp-msg-protocol:ros-message-to-list ((msg %s))'%c)
 
  661         s.write(
'"Converts a ROS message object to a list"')
 
  664             for f 
in spec.parsed_fields():
 
  665                 s.write(
'(cl:cons \':%s (%s msg))'%(f.name, f.name))
 
  671             s.write(
'(cl:defmethod roslisp-msg-protocol:symbol-codes ((msg-type (cl:eql \'%s)))'%cls)
 
  673                 s.write(
'  "Constants for message type \'%s"'%cls)
 
  675                 with Indent(s, indent_first=
False):
 
  676                     for c 
in spec.constants:
 
  677                         if c.type == 
'string':
 
  680                                 escaped = c.val.replace(
'\\', 
'\\\\')
 
  681                                 escaped = escaped.replace(
'\"', 
'\\"')
 
  682                                 s.write(
'(:%s . "%s")'%(c.name.upper(), escaped))
 
  684                                 s.write(
'(:%s . "%s")'%(c.name.upper(), c.val))
 
  686                             s.write(
'(:%s . %s)'%(c.name.upper(), c.val))
 
  692     spec.component_type=
'service' 
  707     spec.actual_name=spec.short_name
 
  708     s.write(
'(cl:defmethod roslisp-msg-protocol:service-request-type ((msg (cl:eql \'%s)))'%spec.short_name)
 
  711     s.write(
'(cl:defmethod roslisp-msg-protocol:service-response-type ((msg (cl:eql \'%s)))'%spec.short_name)
 
  714     s.write(
'(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%spec.short_name)
 
  716         s.write(
'"Returns string type for a service object of type \'%s"'%
message_class(spec))
 
  717         s.write(
'"%s")'%spec.full_name)
 
  722     Generate lisp code for all messages in a package 
  724     msg_context = MsgContext.create_default()
 
  726         f = os.path.abspath(f)
 
  727         infile = os.path.basename(f)
 
  728         full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
 
  729         spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
 
  734     Generate lisp code for all services in a package 
  736     msg_context = MsgContext.create_default()
 
  738         f = os.path.abspath(f)
 
  739         infile = os.path.basename(f)
 
  740         full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
 
  741         spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
 
  745     dir_list = search_path[pkg]
 
  748         files.extend([f 
for f 
in os.listdir(d) 
if f.endswith(ext)])
 
  750     return sorted([f[:-len(ext)] 
for f 
in files])
 
  756     @param msg_path: The path to the .msg file 
  759     genmsg.msg_loader.load_depends(msg_context, spec, search_path)
 
  760     spec.actual_name=spec.short_name
 
  761     spec.component_type=
'message' 
  762     msgs = 
msg_list(package, search_path, 
'.msg')
 
  764         genmsg.load_msg_by_type(msg_context, 
'%s/%s'%(package, m), search_path)
 
  786     if (
not os.path.exists(output_dir)):
 
  790             os.makedirs(output_dir)
 
  794     with open(
'%s/%s.lisp'%(output_dir, spec.short_name), 
'w') 
as f:
 
  795         f.write(io.getvalue() + 
"\n")
 
  806     with open(
'%s/_package_%s.lisp'%(output_dir, spec.short_name), 
'w') 
as f:
 
  807         f.write(io.getvalue())
 
  819     with open(
'%s/_package.lisp'%output_dir, 
'w') 
as f:
 
  820         f.write(io.getvalue())
 
  832     with open(
'%s/%s-msg.asd'%(output_dir, package), 
'w') 
as f:
 
  833         f.write(io.getvalue())
 
  838     "Generate code from .srv file" 
  839     genmsg.msg_loader.load_depends(msg_context, spec, search_path)
 
  841     srv_path = os.path.dirname(path)
 
  842     srvs = 
msg_list(package, {package: [srv_path]}, ext)
 
  844         load_srv_from_file(msg_context, 
'%s/%s%s'%(srv_path, srv, ext), 
'%s/%s'%(package, srv))
 
  853     spec.request.actual_name=
'%s-request'%spec.short_name
 
  854     spec.response.actual_name=
'%s-response'%spec.short_name
 
  860     with open(
'%s/%s.lisp'%(output_dir, spec.short_name), 
'w') 
as f:
 
  861         f.write(io.getvalue())
 
  872     with open(
'%s/_package_%s.lisp'%(output_dir, spec.short_name), 
'w') 
as f:
 
  873         f.write(io.getvalue())
 
  883     with open(
'%s/_package.lisp'%output_dir, 
'w') 
as f:
 
  884         f.write(io.getvalue())
 
  894     with open(
'%s/%s-srv.asd'%(output_dir, package), 
'w') 
as f:
 
  895         f.write(io.getvalue())