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


novatel_span_driver
Author(s): NovAtel Support
autogenerated on Thu Sep 28 2017 03:12:25