(this is more of an addition to @ahendrix's answer (but I didn't want to edit his))
See the (de)serialisation code for UInt8.msg
for how this works in Python fi (taken from /opt/ros/kinetic/lib/python2.7/dist-packages/std_msgs/msg/_UInt8.py
):
def serialize(self, buff):
"""
serialize message into buffer
:param buff: buffer, ``StringIO``
"""
try:
buff.write(_get_struct_B().pack(self.data))
except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self)))))
except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(locals().get('_x', self)))))
def deserialize(self, str):
"""
unpack serialized message in str into this message instance
:param str: byte array of serialized message, ``str``
"""
try:
end = 0
start = end
end += 1
(self.data,) = _get_struct_B().unpack(str[start:end])
return self
except struct.error as e:
raise genpy.DeserializationError(e) #most likely buffer underfill
At least at this level (and this is the ony place message content is actually (de)serialised, called from here and here), values that are unrepresentable by the type that was specced for a field in a message will result in exceptions being thrown.
@ahendrix wrote:
I believe Python is using the struct
library to pack objects into the serialization format, so you will get an exception if the value in that message field is outside of the allowed bounds.
Exactly: _get_struct_B()
essentially just returns an instance of struct.Struct("B")
:
def _get_struct_B():
global _struct_B
if _struct_B is None:
_struct_B = struct.Struct("<B")
return _struct_B
Note also the endianness specification there.
Just a pedantic nitpick, but the range for
uint8
is actually 2^8 - 1 = 255, while 2*8 - 1 = 31. So, either this is a typo or if you're publishing values in the range [32, 255] you're actually still in range foruint8
.Right. Python 2**8-1. fixed
Another nitpick: are we mixing up the concepts "out of band messaging" and an "out of bounds" problem when representing a value? The former may be possible, depending on how strict you define it and map that to ROS infrastructure. The latter makes a little less sense to me in this context.
I am not sure if I understand "out of band messaging" in the ROS context. It is about message field values which are inside the range of the underlying Python data type (e.g. Python int) but outside the corresponding ROS data type (e.g. ROS uint8). (E.g. here int with wider value range as uint8).
Your question title says "receive messages [..] which are out-of-bound". That doesn't make sense to me. Fields could potentially have values in the serialised bytestream that are out-of-bounds for their specced types, but this statement cannot apply to complete messages ..
You are right. I adjusted the question accordingly. :) Sry for the confusion.