translator.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 #     _____
00004 #    /  _  \
00005 #   / _/ \  \
00006 #  / / \_/   \
00007 # /  \_/  _   \  ___  _    ___   ___   ____   ____   ___   _____  _   _
00008 # \  / \_/ \  / /  _\| |  | __| / _ \ | ┌┐ \ | ┌┐ \ / _ \ |_   _|| | | |
00009 #  \ \_/ \_/ /  | |  | |  | └─┐| |_| || └┘ / | └┘_/| |_| |  | |  | └─┘ |
00010 #   \  \_/  /   | |_ | |_ | ┌─┘|  _  || |\ \ | |   |  _  |  | |  | ┌─┐ |
00011 #    \_____/    \___/|___||___||_| |_||_| \_\|_|   |_| |_|  |_|  |_| |_|
00012 #            ROBOTICS™
00013 #
00014 #
00015 #  Copyright © 2012 Clearpath Robotics, Inc. 
00016 #  All Rights Reserved
00017 #  
00018 # Redistribution and use in source and binary forms, with or without
00019 # modification, are permitted provided that the following conditions are met:
00020 #     * Redistributions of source code must retain the above copyright
00021 #       notice, this list of conditions and the following disclaimer.
00022 #     * Redistributions in binary form must reproduce the above copyright
00023 #       notice, this list of conditions and the following disclaimer in the
00024 #       documentation and/or other materials provided with the distribution.
00025 #     * Neither the name of Clearpath Robotics, Inc. nor the
00026 #       names of its contributors may be used to endorse or promote products
00027 #       derived from this software without specific prior written permission.
00028 # 
00029 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00030 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00031 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00032 # DISCLAIMED. IN NO EVENT SHALL CLEARPATH ROBOTICS, INC. BE LIABLE FOR ANY
00033 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00034 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00035 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00036 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00037 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00038 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00039 #
00040 # Please send comments, questions, or patches to skynet@clearpathrobotics.com
00041 #
00042 
00043 import genpy.message, genpy.base
00044 import roslib.msgs
00045 
00046 import rospy
00047 import struct
00048 from itertools import izip
00049 from cStringIO import StringIO
00050 
00051 
00052 class EndOfBuffer(BaseException):
00053   pass
00054 
00055 
00056 class TranslatorError(ValueError):
00057   pass
00058 
00059 
00060 class Handler(object):
00061   def field(self, msg):
00062     return getattr(msg, self.name)
00063 
00064   def preserialize(self, msg):
00065     pass
00066 
00067 
00068 class SubMessageHandler(Handler):
00069   def __init__(self, field):
00070     self.name = field.name
00071     self.msg_cls = genpy.message.get_message_class(field.type)
00072 
00073   def deserialize(self, buff, msg):
00074     self.field(msg).translator().deserialize(buff)
00075 
00076   def serialize(self, buff, msg):
00077     self.field(msg).translator().serialize(buff)
00078 
00079 
00080 class FixedFieldsHandler(Handler):
00081   def __init__(self, fields):
00082     struct_strs = ['<']
00083     def pattern(field):
00084       try:
00085         return genpy.base.SIMPLE_TYPES_DICT[field.type]
00086       except KeyError:
00087         if field.base_type in ['uint8', 'char'] and field.array_len is not None:
00088           return "%is" % field.array_len
00089         else:
00090           raise ValueError("Field type " + str(field.type) + " not found")
00091           
00092     struct_strs.extend([pattern(f) for f in fields])
00093     self.struct = struct.Struct(''.join(struct_strs))
00094     self.names = [f.name for f in fields]
00095     self.size = self.struct.size
00096 
00097   def serialize(self, buff, msg):
00098     buff.write(self.struct.pack(*[getattr(msg, name) for name in self.names])) 
00099 
00100   def deserialize(self, buff, msg):
00101     st = buff.read(self.struct.size)
00102     if st == '': raise EndOfBuffer()
00103     values = self.struct.unpack(st) 
00104     for name, value in izip(self.names, values):
00105       setattr(msg, name, value)
00106 
00107 
00108 class SubMessageArrayHandler(Handler):
00109   struct_uint16 = struct.Struct('<H')
00110   struct_uint8 = struct.Struct('<B')
00111 
00112   def __init__(self, field):
00113     self.name = field.name
00114     self.name_count = "%s_count" % self.name
00115     self.msg_cls = genpy.message.get_message_class(field.base_type)
00116     self.submessage_size = self.msg_cls().translator().size
00117 
00118   def deserialize(self, buff, msg):
00119     if hasattr(msg, self.name_count):
00120       # Another field specifies number of array items to deserialize.
00121       length = getattr(msg, self.name_count) * self.submessage_size 
00122       data = StringIO(buff.read(length))
00123     else:
00124       # Consume as much as we can straight from the buffer.
00125       data = buff
00126 
00127     # Find and empty the array to be populated.
00128     array = self.field(msg)
00129     array[:] = []
00130 
00131     try:
00132       while True:
00133         submessage = self.msg_cls()
00134         submessage.translator().deserialize(data)
00135         array.append(submessage)
00136     except EndOfBuffer:
00137       pass
00138 
00139   def serialize(self, buff, msg):
00140     for submessage in self.field(msg):
00141       submessage.translator().serialize(buff)
00142 
00143   def preserialize(self, msg):
00144     if hasattr(msg, self.name_count):
00145       setattr(msg, self.name_count, len(self.field(msg)))
00146 
00147 
00148 class VariableStringHandler(Handler):
00149   struct_bytes = struct.Struct('<H')
00150 
00151   def __init__(self, field):
00152     self.name = field.name
00153 
00154   def deserialize(self, buff, msg):
00155     length = self.struct_bytes.unpack(buff.read(self.struct_bytes.size))[0]
00156     setattr(msg, self.name, str(buff.read(length)))
00157 
00158 
00159 class Translator:
00160   def __init__(self, msg_cls):
00161     self.handlers = []
00162     self.size = None
00163 
00164     cls_name, spec = roslib.msgs.load_by_type(msg_cls._type)
00165 
00166     fixed_fields = []
00167     for field in spec.parsed_fields():
00168       if genpy.base.is_simple(field.base_type) and (field.array_len != None or not field.is_array):
00169         # Simple types and fixed-length character arrays.
00170         fixed_fields.append(field)
00171       else:
00172         # Before dealing with this non-simple field, add a handler for the fixed fields
00173         # encountered so far.
00174         if len(fixed_fields) > 0:
00175           self.handlers.append(FixedFieldsHandler(fixed_fields))
00176           fixed_fields = []
00177 
00178         # Handle this other type.
00179         if field.type == 'string' or (field.base_type == 'uint8' and field.is_array):
00180           self.handlers.append(VariableStringHandler(field))
00181         elif field.is_array:
00182           self.handlers.append(SubMessageArrayHandler(field))
00183         else:
00184           self.handlers.append(SubMessageHandler(field))
00185 
00186     if len(fixed_fields) > 0:
00187       self.handlers.append(FixedFieldsHandler(fixed_fields))
00188 
00189     if len(self.handlers) == 1 and hasattr(self.handlers[0], 'size'):
00190       self.size = self.handlers[0].size
00191 
00192 
00193 class TranslatorProxy:
00194   def __init__(self, translator, msg):
00195     self.translator = translator
00196     self.size = translator.size
00197     self.msg = msg
00198 
00199   def deserialize(self, buff):
00200     try:
00201       for handler in self.translator.handlers:
00202         handler.deserialize(buff, self.msg)
00203     except struct.error as e:
00204       raise TranslatorError(e)
00205 
00206   def serialize(self, buff):
00207     #rospy.loginfo(str(self.msg))
00208     try:
00209       for handler in self.translator.handlers:
00210         handler.serialize(buff, self.msg)
00211     except struct.error as e:
00212       raise TranslatorError(e)
00213 
00214   def preserialize(self):
00215     for handler in self.translator.handlers:
00216       handler.preserialize(self.msg)
00217 
00218 
00219 def translator(self):
00220   if not hasattr(self.__class__, "_translator"):
00221     self.__class__._translator = Translator(self.__class__)
00222   return TranslatorProxy(self.__class__._translator, self)
00223 
00224 genpy.message.Message.translator = translator


applanix_bridge
Author(s): Mike Purvis
autogenerated on Thu Aug 27 2015 12:15:53