From b6cb6790165a400bcd6b8e32e6c488da1d4ef141 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 22 Apr 2019 21:42:11 +0900 Subject: [PATCH 01/11] Fix test.py --- tiny_tf/test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tiny_tf/test.py b/tiny_tf/test.py index 456ec82..ee0708f 100644 --- a/tiny_tf/test.py +++ b/tiny_tf/test.py @@ -12,15 +12,15 @@ def test_tree(): tree.add_transform('map', 'odom', Transform(1, 1, 1, 0, 0, 0, 1)) tree.add_transform('odom', 'camera1', Transform.from_position_euler(0, 0, 0, np.pi, 0, 0)) - print tree.lookup_transform('camera1', 'map').euler + print( tree.lookup_transform('camera1', 'map').euler) tree.add_transform('camera1', 'camera2', Transform.from_position_euler(0, 0, 0, np.pi, 0, 0)) - print tree.lookup_transform('camera2', 'map').euler + print(tree.lookup_transform('camera2', 'map').euler) - pprint(tree.to_dict()) + print(tree.to_dict()) - pprint(TFTree.from_dict(tree.to_dict()).to_dict()) + print(TFTree.from_dict(tree.to_dict()).to_dict()) if __name__ == '__main__': test_transform() From 05481d2bae9e63654feef1bcda5cd4128a328e62 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 22 Apr 2019 21:54:19 +0900 Subject: [PATCH 02/11] Comments --- tiny_tf/tf.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tiny_tf/tf.py b/tiny_tf/tf.py index 08d92a5..128de67 100644 --- a/tiny_tf/tf.py +++ b/tiny_tf/tf.py @@ -39,7 +39,7 @@ def get_parent(self): parent_nodes.append(node) if len(parent_nodes) > 1: - raise Exception("More than one tree found, this case is unsupported") + raise Exception("A frame with more than one parent was found, this case is unsupported (more than one tree or cyclical connections)") if len(parent_nodes) == 0: raise Exception("No parent node found, there are probably cycles in the tree") @@ -65,7 +65,7 @@ def lookup_transform(self, frame, target): else: break - # Note: I do not understand why the part below works + # Note safijari: I do not understand why the part below works def get_inverse_xform_for_path(path): transform_to_parent = np.identity(4) @@ -99,6 +99,10 @@ def _get_path_to_parent(self, parent_node, node_name): return path def transform_point(self, x, y, z, target, base): + """ + Transforms the input parameters x, y, z from "base" frame to "target" frame. + Output is a list: [x, y, z] + """ t = self.lookup_transform(base, target) return np.dot(t.matrix, np.array([x, y, z, 1]))[0:3] From ebff760526ac2d6688fa9751ccb8b0f5cfd7b254 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 22 Apr 2019 21:54:44 +0900 Subject: [PATCH 03/11] Add transform_pose --- tiny_tf/tf.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tiny_tf/tf.py b/tiny_tf/tf.py index 128de67..0bb555d 100644 --- a/tiny_tf/tf.py +++ b/tiny_tf/tf.py @@ -105,7 +105,16 @@ def transform_point(self, x, y, z, target, base): """ t = self.lookup_transform(base, target) return np.dot(t.matrix, np.array([x, y, z, 1]))[0:3] - + + def transform_pose(self, x, y, z, qx, qy, qz, qw, target, base): + """ + Transforms the input parameters (point x,y,z and quaternion qx,qy,qz,qw) from "base" frame to "target" frame. + Output is a list: [x, y, z, qx, qy, qz, qw] + """ + t = self.lookup_transform(base, target) + xyz = np.dot(t.matrix, np.array([x, y, z, 1]))[0:3] + q = tft.quaternion_multiply([qx, qy, qz, qw], [t.qx, t.qy, t.qz, t.qw]) + return [*xyz, *q] class TFNode(object): def __init__(self, name, parent, transform): From a3c6f65b3270feaa9cab1cd659582f1af8a080d5 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 22 Apr 2019 21:55:57 +0900 Subject: [PATCH 04/11] Add geometry_msgs Kind of hacky, but it works for now. This is just the built version of the ROS Melodic messages. --- geometry_msgs/__init__.py | 0 geometry_msgs/msg/_Accel.py | 136 +++++++++ geometry_msgs/msg/_AccelStamped.py | 209 ++++++++++++++ geometry_msgs/msg/_AccelWithCovariance.py | 158 +++++++++++ .../msg/_AccelWithCovarianceStamped.py | 235 ++++++++++++++++ geometry_msgs/msg/_Inertia.py | 163 +++++++++++ geometry_msgs/msg/_InertiaStamped.py | 221 +++++++++++++++ geometry_msgs/msg/_Point.py | 119 ++++++++ geometry_msgs/msg/_Point32.py | 125 +++++++++ geometry_msgs/msg/_PointStamped.py | 198 +++++++++++++ geometry_msgs/msg/_Polygon.py | 149 ++++++++++ geometry_msgs/msg/_PolygonStamped.py | 229 +++++++++++++++ geometry_msgs/msg/_Pose.py | 140 ++++++++++ geometry_msgs/msg/_Pose2D.py | 128 +++++++++ geometry_msgs/msg/_PoseArray.py | 261 ++++++++++++++++++ geometry_msgs/msg/_PoseStamped.py | 213 ++++++++++++++ geometry_msgs/msg/_PoseWithCovariance.py | 162 +++++++++++ .../msg/_PoseWithCovarianceStamped.py | 240 ++++++++++++++++ geometry_msgs/msg/_Quaternion.py | 124 +++++++++ geometry_msgs/msg/_QuaternionStamped.py | 201 ++++++++++++++ geometry_msgs/msg/_Transform.py | 146 ++++++++++ geometry_msgs/msg/_TransformStamped.py | 259 +++++++++++++++++ geometry_msgs/msg/_Twist.py | 136 +++++++++ geometry_msgs/msg/_TwistStamped.py | 209 ++++++++++++++ geometry_msgs/msg/_TwistWithCovariance.py | 158 +++++++++++ .../msg/_TwistWithCovarianceStamped.py | 235 ++++++++++++++++ geometry_msgs/msg/_Vector3.py | 124 +++++++++ geometry_msgs/msg/_Vector3Stamped.py | 203 ++++++++++++++ geometry_msgs/msg/_Wrench.py | 137 +++++++++ geometry_msgs/msg/_WrenchStamped.py | 210 ++++++++++++++ geometry_msgs/msg/__init__.py | 29 ++ 31 files changed, 5257 insertions(+) create mode 100644 geometry_msgs/__init__.py create mode 100644 geometry_msgs/msg/_Accel.py create mode 100644 geometry_msgs/msg/_AccelStamped.py create mode 100644 geometry_msgs/msg/_AccelWithCovariance.py create mode 100644 geometry_msgs/msg/_AccelWithCovarianceStamped.py create mode 100644 geometry_msgs/msg/_Inertia.py create mode 100644 geometry_msgs/msg/_InertiaStamped.py create mode 100644 geometry_msgs/msg/_Point.py create mode 100644 geometry_msgs/msg/_Point32.py create mode 100644 geometry_msgs/msg/_PointStamped.py create mode 100644 geometry_msgs/msg/_Polygon.py create mode 100644 geometry_msgs/msg/_PolygonStamped.py create mode 100644 geometry_msgs/msg/_Pose.py create mode 100644 geometry_msgs/msg/_Pose2D.py create mode 100644 geometry_msgs/msg/_PoseArray.py create mode 100644 geometry_msgs/msg/_PoseStamped.py create mode 100644 geometry_msgs/msg/_PoseWithCovariance.py create mode 100644 geometry_msgs/msg/_PoseWithCovarianceStamped.py create mode 100644 geometry_msgs/msg/_Quaternion.py create mode 100644 geometry_msgs/msg/_QuaternionStamped.py create mode 100644 geometry_msgs/msg/_Transform.py create mode 100644 geometry_msgs/msg/_TransformStamped.py create mode 100644 geometry_msgs/msg/_Twist.py create mode 100644 geometry_msgs/msg/_TwistStamped.py create mode 100644 geometry_msgs/msg/_TwistWithCovariance.py create mode 100644 geometry_msgs/msg/_TwistWithCovarianceStamped.py create mode 100644 geometry_msgs/msg/_Vector3.py create mode 100644 geometry_msgs/msg/_Vector3Stamped.py create mode 100644 geometry_msgs/msg/_Wrench.py create mode 100644 geometry_msgs/msg/_WrenchStamped.py create mode 100644 geometry_msgs/msg/__init__.py diff --git a/geometry_msgs/__init__.py b/geometry_msgs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geometry_msgs/msg/_Accel.py b/geometry_msgs/msg/_Accel.py new file mode 100644 index 0000000..ef29606 --- /dev/null +++ b/geometry_msgs/msg/_Accel.py @@ -0,0 +1,136 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/Accel.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Accel(genpy.Message): + _md5sum = "9f195f881246fdfa2798d1d3eebca84a" + _type = "geometry_msgs/Accel" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This expresses acceleration in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['linear','angular'] + _slot_types = ['geometry_msgs/Vector3','geometry_msgs/Vector3'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + linear,angular + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Accel, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + else: + self.linear = geometry_msgs.msg.Vector3() + self.angular = geometry_msgs.msg.Vector3() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z)) + 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: + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_6d = None +def _get_struct_6d(): + global _struct_6d + if _struct_6d is None: + _struct_6d = struct.Struct("<6d") + return _struct_6d diff --git a/geometry_msgs/msg/_AccelStamped.py b/geometry_msgs/msg/_AccelStamped.py new file mode 100644 index 0000000..f10378f --- /dev/null +++ b/geometry_msgs/msg/_AccelStamped.py @@ -0,0 +1,209 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/AccelStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class AccelStamped(genpy.Message): + _md5sum = "d8a98a5d81351b6eb0578c78557e7659" + _type = "geometry_msgs/AccelStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# An accel with reference coordinate frame and timestamp +Header header +Accel accel + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Accel +# This expresses acceleration in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','accel'] + _slot_types = ['std_msgs/Header','geometry_msgs/Accel'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,accel + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(AccelStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.accel is None: + self.accel = geometry_msgs.msg.Accel() + else: + self.header = std_msgs.msg.Header() + self.accel = geometry_msgs.msg.Accel() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class AccelWithCovariance(genpy.Message): + _md5sum = "ad5a718d699c6be72a02b8d6a139f334" + _type = "geometry_msgs/AccelWithCovariance" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This expresses acceleration in free space with uncertainty. + +Accel accel + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Accel +# This expresses acceleration in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['accel','covariance'] + _slot_types = ['geometry_msgs/Accel','float64[36]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + accel,covariance + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(AccelWithCovariance, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.accel is None: + self.accel = geometry_msgs.msg.Accel() + if self.covariance is None: + self.covariance = [0.] * 36 + else: + self.accel = geometry_msgs.msg.Accel() + self.covariance = [0.] * 36 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.accel.linear.x, _x.accel.linear.y, _x.accel.linear.z, _x.accel.angular.x, _x.accel.angular.y, _x.accel.angular.z)) + buff.write(_get_struct_36d().pack(*self.covariance)) + 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: + if self.accel is None: + self.accel = geometry_msgs.msg.Accel() + end = 0 + _x = self + start = end + end += 48 + (_x.accel.linear.x, _x.accel.linear.y, _x.accel.linear.z, _x.accel.angular.x, _x.accel.angular.y, _x.accel.angular.z,) = _get_struct_6d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = _get_struct_36d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.accel.linear.x, _x.accel.linear.y, _x.accel.linear.z, _x.accel.angular.x, _x.accel.angular.y, _x.accel.angular.z)) + buff.write(self.covariance.tostring()) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.accel is None: + self.accel = geometry_msgs.msg.Accel() + end = 0 + _x = self + start = end + end += 48 + (_x.accel.linear.x, _x.accel.linear.y, _x.accel.linear.z, _x.accel.angular.x, _x.accel.angular.y, _x.accel.angular.z,) = _get_struct_6d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = numpy.frombuffer(str[start:end], dtype=numpy.float64, count=36) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_36d = None +def _get_struct_36d(): + global _struct_36d + if _struct_36d is None: + _struct_36d = struct.Struct("<36d") + return _struct_36d +_struct_6d = None +def _get_struct_6d(): + global _struct_6d + if _struct_6d is None: + _struct_6d = struct.Struct("<6d") + return _struct_6d diff --git a/geometry_msgs/msg/_AccelWithCovarianceStamped.py b/geometry_msgs/msg/_AccelWithCovarianceStamped.py new file mode 100644 index 0000000..3f681fb --- /dev/null +++ b/geometry_msgs/msg/_AccelWithCovarianceStamped.py @@ -0,0 +1,235 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/AccelWithCovarianceStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class AccelWithCovarianceStamped(genpy.Message): + _md5sum = "96adb295225031ec8d57fb4251b0a886" + _type = "geometry_msgs/AccelWithCovarianceStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents an estimated accel with reference coordinate frame and timestamp. +Header header +AccelWithCovariance accel + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/AccelWithCovariance +# This expresses acceleration in free space with uncertainty. + +Accel accel + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Accel +# This expresses acceleration in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','accel'] + _slot_types = ['std_msgs/Header','geometry_msgs/AccelWithCovariance'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,accel + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(AccelWithCovarianceStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.accel is None: + self.accel = geometry_msgs.msg.AccelWithCovariance() + else: + self.header = std_msgs.msg.Header() + self.accel = geometry_msgs.msg.AccelWithCovariance() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Inertia(genpy.Message): + _md5sum = "1d26e4bb6c83ff141c5cf0d883c2b0fe" + _type = "geometry_msgs/Inertia" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Mass [kg] +float64 m + +# Center of mass [m] +geometry_msgs/Vector3 com + +# Inertia Tensor [kg-m^2] +# | ixx ixy ixz | +# I = | ixy iyy iyz | +# | ixz iyz izz | +float64 ixx +float64 ixy +float64 ixz +float64 iyy +float64 iyz +float64 izz + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['m','com','ixx','ixy','ixz','iyy','iyz','izz'] + _slot_types = ['float64','geometry_msgs/Vector3','float64','float64','float64','float64','float64','float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + m,com,ixx,ixy,ixz,iyy,iyz,izz + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Inertia, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.m is None: + self.m = 0. + if self.com is None: + self.com = geometry_msgs.msg.Vector3() + if self.ixx is None: + self.ixx = 0. + if self.ixy is None: + self.ixy = 0. + if self.ixz is None: + self.ixz = 0. + if self.iyy is None: + self.iyy = 0. + if self.iyz is None: + self.iyz = 0. + if self.izz is None: + self.izz = 0. + else: + self.m = 0. + self.com = geometry_msgs.msg.Vector3() + self.ixx = 0. + self.ixy = 0. + self.ixz = 0. + self.iyy = 0. + self.iyz = 0. + self.izz = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_10d().pack(_x.m, _x.com.x, _x.com.y, _x.com.z, _x.ixx, _x.ixy, _x.ixz, _x.iyy, _x.iyz, _x.izz)) + 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: + if self.com is None: + self.com = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 80 + (_x.m, _x.com.x, _x.com.y, _x.com.z, _x.ixx, _x.ixy, _x.ixz, _x.iyy, _x.iyz, _x.izz,) = _get_struct_10d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_10d().pack(_x.m, _x.com.x, _x.com.y, _x.com.z, _x.ixx, _x.ixy, _x.ixz, _x.iyy, _x.iyz, _x.izz)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.com is None: + self.com = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 80 + (_x.m, _x.com.x, _x.com.y, _x.com.z, _x.ixx, _x.ixy, _x.ixz, _x.iyy, _x.iyz, _x.izz,) = _get_struct_10d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_10d = None +def _get_struct_10d(): + global _struct_10d + if _struct_10d is None: + _struct_10d = struct.Struct("<10d") + return _struct_10d diff --git a/geometry_msgs/msg/_InertiaStamped.py b/geometry_msgs/msg/_InertiaStamped.py new file mode 100644 index 0000000..6f9253e --- /dev/null +++ b/geometry_msgs/msg/_InertiaStamped.py @@ -0,0 +1,221 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/InertiaStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class InertiaStamped(genpy.Message): + _md5sum = "ddee48caeab5a966c5e8d166654a9ac7" + _type = "geometry_msgs/InertiaStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """Header header +Inertia inertia + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Inertia +# Mass [kg] +float64 m + +# Center of mass [m] +geometry_msgs/Vector3 com + +# Inertia Tensor [kg-m^2] +# | ixx ixy ixz | +# I = | ixy iyy iyz | +# | ixz iyz izz | +float64 ixx +float64 ixy +float64 ixz +float64 iyy +float64 iyz +float64 izz + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','inertia'] + _slot_types = ['std_msgs/Header','geometry_msgs/Inertia'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,inertia + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(InertiaStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.inertia is None: + self.inertia = geometry_msgs.msg.Inertia() + else: + self.header = std_msgs.msg.Header() + self.inertia = geometry_msgs.msg.Inertia() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + + +class Point(genpy.Message): + _md5sum = "4a842b65f413084dc2b10fb484ea7f17" + _type = "geometry_msgs/Point" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This contains the position of a point in free space +float64 x +float64 y +float64 z +""" + __slots__ = ['x','y','z'] + _slot_types = ['float64','float64','float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + x,y,z + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Point, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.x is None: + self.x = 0. + if self.y is None: + self.y = 0. + if self.z is None: + self.z = 0. + else: + self.x = 0. + self.y = 0. + self.z = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.z)) + 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 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.z,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + end = 0 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.z,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_3d = None +def _get_struct_3d(): + global _struct_3d + if _struct_3d is None: + _struct_3d = struct.Struct("<3d") + return _struct_3d diff --git a/geometry_msgs/msg/_Point32.py b/geometry_msgs/msg/_Point32.py new file mode 100644 index 0000000..f68785b --- /dev/null +++ b/geometry_msgs/msg/_Point32.py @@ -0,0 +1,125 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/Point32.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + + +class Point32(genpy.Message): + _md5sum = "cc153912f1453b708d221682bc23d9ac" + _type = "geometry_msgs/Point32" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This contains the position of a point in free space(with 32 bits of precision). +# It is recommeded to use Point wherever possible instead of Point32. +# +# This recommendation is to promote interoperability. +# +# This message is designed to take up less space when sending +# lots of points at once, as in the case of a PointCloud. + +float32 x +float32 y +float32 z""" + __slots__ = ['x','y','z'] + _slot_types = ['float32','float32','float32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + x,y,z + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Point32, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.x is None: + self.x = 0. + if self.y is None: + self.y = 0. + if self.z is None: + self.z = 0. + else: + self.x = 0. + self.y = 0. + self.z = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3f().pack(_x.x, _x.y, _x.z)) + 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 + _x = self + start = end + end += 12 + (_x.x, _x.y, _x.z,) = _get_struct_3f().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_3f().pack(_x.x, _x.y, _x.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + end = 0 + _x = self + start = end + end += 12 + (_x.x, _x.y, _x.z,) = _get_struct_3f().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_3f = None +def _get_struct_3f(): + global _struct_3f + if _struct_3f is None: + _struct_3f = struct.Struct("<3f") + return _struct_3f diff --git a/geometry_msgs/msg/_PointStamped.py b/geometry_msgs/msg/_PointStamped.py new file mode 100644 index 0000000..ab5ef02 --- /dev/null +++ b/geometry_msgs/msg/_PointStamped.py @@ -0,0 +1,198 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/PointStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class PointStamped(genpy.Message): + _md5sum = "c63aecb41bfdfd6b7e1fac37c7cbe7bf" + _type = "geometry_msgs/PointStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents a Point with reference coordinate frame and timestamp +Header header +Point point + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z +""" + __slots__ = ['header','point'] + _slot_types = ['std_msgs/Header','geometry_msgs/Point'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,point + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PointStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.point is None: + self.point = geometry_msgs.msg.Point() + else: + self.header = std_msgs.msg.Header() + self.point = geometry_msgs.msg.Point() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Polygon(genpy.Message): + _md5sum = "cd60a26494a087f577976f0329fa120e" + _type = "geometry_msgs/Polygon" + _has_header = False #flag to mark the presence of a Header object + _full_text = """#A specification of a polygon where the first and last points are assumed to be connected +Point32[] points + +================================================================================ +MSG: geometry_msgs/Point32 +# This contains the position of a point in free space(with 32 bits of precision). +# It is recommeded to use Point wherever possible instead of Point32. +# +# This recommendation is to promote interoperability. +# +# This message is designed to take up less space when sending +# lots of points at once, as in the case of a PointCloud. + +float32 x +float32 y +float32 z""" + __slots__ = ['points'] + _slot_types = ['geometry_msgs/Point32[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + points + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Polygon, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.points is None: + self.points = [] + else: + self.points = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + length = len(self.points) + buff.write(_struct_I.pack(length)) + for val1 in self.points: + _x = val1 + buff.write(_get_struct_3f().pack(_x.x, _x.y, _x.z)) + 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: + if self.points is None: + self.points = None + end = 0 + start = end + end += 4 + (length,) = _struct_I.unpack(str[start:end]) + self.points = [] + for i in range(0, length): + val1 = geometry_msgs.msg.Point32() + _x = val1 + start = end + end += 12 + (_x.x, _x.y, _x.z,) = _get_struct_3f().unpack(str[start:end]) + self.points.append(val1) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + length = len(self.points) + buff.write(_struct_I.pack(length)) + for val1 in self.points: + _x = val1 + buff.write(_get_struct_3f().pack(_x.x, _x.y, _x.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.points is None: + self.points = None + end = 0 + start = end + end += 4 + (length,) = _struct_I.unpack(str[start:end]) + self.points = [] + for i in range(0, length): + val1 = geometry_msgs.msg.Point32() + _x = val1 + start = end + end += 12 + (_x.x, _x.y, _x.z,) = _get_struct_3f().unpack(str[start:end]) + self.points.append(val1) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_3f = None +def _get_struct_3f(): + global _struct_3f + if _struct_3f is None: + _struct_3f = struct.Struct("<3f") + return _struct_3f diff --git a/geometry_msgs/msg/_PolygonStamped.py b/geometry_msgs/msg/_PolygonStamped.py new file mode 100644 index 0000000..3d58214 --- /dev/null +++ b/geometry_msgs/msg/_PolygonStamped.py @@ -0,0 +1,229 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/PolygonStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class PolygonStamped(genpy.Message): + _md5sum = "c6be8f7dc3bee7fe9e8d296070f53340" + _type = "geometry_msgs/PolygonStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents a Polygon with reference coordinate frame and timestamp +Header header +Polygon polygon + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Polygon +#A specification of a polygon where the first and last points are assumed to be connected +Point32[] points + +================================================================================ +MSG: geometry_msgs/Point32 +# This contains the position of a point in free space(with 32 bits of precision). +# It is recommeded to use Point wherever possible instead of Point32. +# +# This recommendation is to promote interoperability. +# +# This message is designed to take up less space when sending +# lots of points at once, as in the case of a PointCloud. + +float32 x +float32 y +float32 z""" + __slots__ = ['header','polygon'] + _slot_types = ['std_msgs/Header','geometry_msgs/Polygon'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,polygon + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PolygonStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.polygon is None: + self.polygon = geometry_msgs.msg.Polygon() + else: + self.header = std_msgs.msg.Header() + self.polygon = geometry_msgs.msg.Polygon() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Pose(genpy.Message): + _md5sum = "e45d45a5a1ce597b249e23fb30fc871f" + _type = "geometry_msgs/Pose" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# A representation of pose in free space, composed of position and orientation. +Point position +Quaternion orientation + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['position','orientation'] + _slot_types = ['geometry_msgs/Point','geometry_msgs/Quaternion'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + position,orientation + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Pose, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.position is None: + self.position = geometry_msgs.msg.Point() + if self.orientation is None: + self.orientation = geometry_msgs.msg.Quaternion() + else: + self.position = geometry_msgs.msg.Point() + self.orientation = geometry_msgs.msg.Quaternion() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.position.x, _x.position.y, _x.position.z, _x.orientation.x, _x.orientation.y, _x.orientation.z, _x.orientation.w)) + 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: + if self.position is None: + self.position = geometry_msgs.msg.Point() + if self.orientation is None: + self.orientation = geometry_msgs.msg.Quaternion() + end = 0 + _x = self + start = end + end += 56 + (_x.position.x, _x.position.y, _x.position.z, _x.orientation.x, _x.orientation.y, _x.orientation.z, _x.orientation.w,) = _get_struct_7d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.position.x, _x.position.y, _x.position.z, _x.orientation.x, _x.orientation.y, _x.orientation.z, _x.orientation.w)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.position is None: + self.position = geometry_msgs.msg.Point() + if self.orientation is None: + self.orientation = geometry_msgs.msg.Quaternion() + end = 0 + _x = self + start = end + end += 56 + (_x.position.x, _x.position.y, _x.position.z, _x.orientation.x, _x.orientation.y, _x.orientation.z, _x.orientation.w,) = _get_struct_7d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_7d = None +def _get_struct_7d(): + global _struct_7d + if _struct_7d is None: + _struct_7d = struct.Struct("<7d") + return _struct_7d diff --git a/geometry_msgs/msg/_Pose2D.py b/geometry_msgs/msg/_Pose2D.py new file mode 100644 index 0000000..186fd69 --- /dev/null +++ b/geometry_msgs/msg/_Pose2D.py @@ -0,0 +1,128 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/Pose2D.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + + +class Pose2D(genpy.Message): + _md5sum = "938fa65709584ad8e77d238529be13b8" + _type = "geometry_msgs/Pose2D" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Deprecated +# Please use the full 3D pose. + +# In general our recommendation is to use a full 3D representation of everything and for 2D specific applications make the appropriate projections into the plane for their calculations but optimally will preserve the 3D information during processing. + +# If we have parallel copies of 2D datatypes every UI and other pipeline will end up needing to have dual interfaces to plot everything. And you will end up with not being able to use 3D tools for 2D use cases even if they're completely valid, as you'd have to reimplement it with different inputs and outputs. It's not particularly hard to plot the 2D pose or compute the yaw error for the Pose message and there are already tools and libraries that can do this for you. + + +# This expresses a position and orientation on a 2D manifold. + +float64 x +float64 y +float64 theta +""" + __slots__ = ['x','y','theta'] + _slot_types = ['float64','float64','float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + x,y,theta + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Pose2D, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.x is None: + self.x = 0. + if self.y is None: + self.y = 0. + if self.theta is None: + self.theta = 0. + else: + self.x = 0. + self.y = 0. + self.theta = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.theta)) + 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 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.theta,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.theta)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + end = 0 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.theta,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_3d = None +def _get_struct_3d(): + global _struct_3d + if _struct_3d is None: + _struct_3d = struct.Struct("<3d") + return _struct_3d diff --git a/geometry_msgs/msg/_PoseArray.py b/geometry_msgs/msg/_PoseArray.py new file mode 100644 index 0000000..13fbc2f --- /dev/null +++ b/geometry_msgs/msg/_PoseArray.py @@ -0,0 +1,261 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/PoseArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class PoseArray(genpy.Message): + _md5sum = "916c28c5764443f268b296bb671b9d97" + _type = "geometry_msgs/PoseArray" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# An array of poses with a header for global reference. + +Header header + +Pose[] poses + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Pose +# A representation of pose in free space, composed of position and orientation. +Point position +Quaternion orientation + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['header','poses'] + _slot_types = ['std_msgs/Header','geometry_msgs/Pose[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,poses + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PoseArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.poses is None: + self.poses = [] + else: + self.header = std_msgs.msg.Header() + self.poses = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class PoseStamped(genpy.Message): + _md5sum = "d3812c3cbc69362b77dc0b19b345f8f5" + _type = "geometry_msgs/PoseStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# A Pose with reference coordinate frame and timestamp +Header header +Pose pose + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Pose +# A representation of pose in free space, composed of position and orientation. +Point position +Quaternion orientation + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['header','pose'] + _slot_types = ['std_msgs/Header','geometry_msgs/Pose'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,pose + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PoseStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.pose is None: + self.pose = geometry_msgs.msg.Pose() + else: + self.header = std_msgs.msg.Header() + self.pose = geometry_msgs.msg.Pose() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class PoseWithCovariance(genpy.Message): + _md5sum = "c23e848cf1b7533a8d7c259073a97e6f" + _type = "geometry_msgs/PoseWithCovariance" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This represents a pose in free space with uncertainty. + +Pose pose + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Pose +# A representation of pose in free space, composed of position and orientation. +Point position +Quaternion orientation + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['pose','covariance'] + _slot_types = ['geometry_msgs/Pose','float64[36]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + pose,covariance + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PoseWithCovariance, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.pose is None: + self.pose = geometry_msgs.msg.Pose() + if self.covariance is None: + self.covariance = [0.] * 36 + else: + self.pose = geometry_msgs.msg.Pose() + self.covariance = [0.] * 36 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.pose.position.x, _x.pose.position.y, _x.pose.position.z, _x.pose.orientation.x, _x.pose.orientation.y, _x.pose.orientation.z, _x.pose.orientation.w)) + buff.write(_get_struct_36d().pack(*self.covariance)) + 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: + if self.pose is None: + self.pose = geometry_msgs.msg.Pose() + end = 0 + _x = self + start = end + end += 56 + (_x.pose.position.x, _x.pose.position.y, _x.pose.position.z, _x.pose.orientation.x, _x.pose.orientation.y, _x.pose.orientation.z, _x.pose.orientation.w,) = _get_struct_7d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = _get_struct_36d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.pose.position.x, _x.pose.position.y, _x.pose.position.z, _x.pose.orientation.x, _x.pose.orientation.y, _x.pose.orientation.z, _x.pose.orientation.w)) + buff.write(self.covariance.tostring()) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.pose is None: + self.pose = geometry_msgs.msg.Pose() + end = 0 + _x = self + start = end + end += 56 + (_x.pose.position.x, _x.pose.position.y, _x.pose.position.z, _x.pose.orientation.x, _x.pose.orientation.y, _x.pose.orientation.z, _x.pose.orientation.w,) = _get_struct_7d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = numpy.frombuffer(str[start:end], dtype=numpy.float64, count=36) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_36d = None +def _get_struct_36d(): + global _struct_36d + if _struct_36d is None: + _struct_36d = struct.Struct("<36d") + return _struct_36d +_struct_7d = None +def _get_struct_7d(): + global _struct_7d + if _struct_7d is None: + _struct_7d = struct.Struct("<7d") + return _struct_7d diff --git a/geometry_msgs/msg/_PoseWithCovarianceStamped.py b/geometry_msgs/msg/_PoseWithCovarianceStamped.py new file mode 100644 index 0000000..684b870 --- /dev/null +++ b/geometry_msgs/msg/_PoseWithCovarianceStamped.py @@ -0,0 +1,240 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/PoseWithCovarianceStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class PoseWithCovarianceStamped(genpy.Message): + _md5sum = "953b798c0f514ff060a53a3498ce6246" + _type = "geometry_msgs/PoseWithCovarianceStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This expresses an estimated pose with a reference coordinate frame and timestamp + +Header header +PoseWithCovariance pose + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/PoseWithCovariance +# This represents a pose in free space with uncertainty. + +Pose pose + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Pose +# A representation of pose in free space, composed of position and orientation. +Point position +Quaternion orientation + +================================================================================ +MSG: geometry_msgs/Point +# This contains the position of a point in free space +float64 x +float64 y +float64 z + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['header','pose'] + _slot_types = ['std_msgs/Header','geometry_msgs/PoseWithCovariance'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,pose + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(PoseWithCovarianceStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.pose is None: + self.pose = geometry_msgs.msg.PoseWithCovariance() + else: + self.header = std_msgs.msg.Header() + self.pose = geometry_msgs.msg.PoseWithCovariance() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + + +class Quaternion(genpy.Message): + _md5sum = "a779879fadf0160734f906b8c19c7004" + _type = "geometry_msgs/Quaternion" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['x','y','z','w'] + _slot_types = ['float64','float64','float64','float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + x,y,z,w + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Quaternion, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.x is None: + self.x = 0. + if self.y is None: + self.y = 0. + if self.z is None: + self.z = 0. + if self.w is None: + self.w = 0. + else: + self.x = 0. + self.y = 0. + self.z = 0. + self.w = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_4d().pack(_x.x, _x.y, _x.z, _x.w)) + 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 + _x = self + start = end + end += 32 + (_x.x, _x.y, _x.z, _x.w,) = _get_struct_4d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_4d().pack(_x.x, _x.y, _x.z, _x.w)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + end = 0 + _x = self + start = end + end += 32 + (_x.x, _x.y, _x.z, _x.w,) = _get_struct_4d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_4d = None +def _get_struct_4d(): + global _struct_4d + if _struct_4d is None: + _struct_4d = struct.Struct("<4d") + return _struct_4d diff --git a/geometry_msgs/msg/_QuaternionStamped.py b/geometry_msgs/msg/_QuaternionStamped.py new file mode 100644 index 0000000..75a2ff3 --- /dev/null +++ b/geometry_msgs/msg/_QuaternionStamped.py @@ -0,0 +1,201 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/QuaternionStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class QuaternionStamped(genpy.Message): + _md5sum = "e57f1e547e0e1fd13504588ffc8334e2" + _type = "geometry_msgs/QuaternionStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents an orientation with reference coordinate frame and timestamp. + +Header header +Quaternion quaternion + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['header','quaternion'] + _slot_types = ['std_msgs/Header','geometry_msgs/Quaternion'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,quaternion + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(QuaternionStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.quaternion is None: + self.quaternion = geometry_msgs.msg.Quaternion() + else: + self.header = std_msgs.msg.Header() + self.quaternion = geometry_msgs.msg.Quaternion() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Transform(genpy.Message): + _md5sum = "ac9eff44abf714214112b05d54a3cf9b" + _type = "geometry_msgs/Transform" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This represents the transform between two coordinate frames in free space. + +Vector3 translation +Quaternion rotation + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['translation','rotation'] + _slot_types = ['geometry_msgs/Vector3','geometry_msgs/Quaternion'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + translation,rotation + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Transform, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.translation is None: + self.translation = geometry_msgs.msg.Vector3() + if self.rotation is None: + self.rotation = geometry_msgs.msg.Quaternion() + else: + self.translation = geometry_msgs.msg.Vector3() + self.rotation = geometry_msgs.msg.Quaternion() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.translation.x, _x.translation.y, _x.translation.z, _x.rotation.x, _x.rotation.y, _x.rotation.z, _x.rotation.w)) + 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: + if self.translation is None: + self.translation = geometry_msgs.msg.Vector3() + if self.rotation is None: + self.rotation = geometry_msgs.msg.Quaternion() + end = 0 + _x = self + start = end + end += 56 + (_x.translation.x, _x.translation.y, _x.translation.z, _x.rotation.x, _x.rotation.y, _x.rotation.z, _x.rotation.w,) = _get_struct_7d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_7d().pack(_x.translation.x, _x.translation.y, _x.translation.z, _x.rotation.x, _x.rotation.y, _x.rotation.z, _x.rotation.w)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.translation is None: + self.translation = geometry_msgs.msg.Vector3() + if self.rotation is None: + self.rotation = geometry_msgs.msg.Quaternion() + end = 0 + _x = self + start = end + end += 56 + (_x.translation.x, _x.translation.y, _x.translation.z, _x.rotation.x, _x.rotation.y, _x.rotation.z, _x.rotation.w,) = _get_struct_7d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_7d = None +def _get_struct_7d(): + global _struct_7d + if _struct_7d is None: + _struct_7d = struct.Struct("<7d") + return _struct_7d diff --git a/geometry_msgs/msg/_TransformStamped.py b/geometry_msgs/msg/_TransformStamped.py new file mode 100644 index 0000000..7b94928 --- /dev/null +++ b/geometry_msgs/msg/_TransformStamped.py @@ -0,0 +1,259 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/TransformStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class TransformStamped(genpy.Message): + _md5sum = "b5764a33bfeb3588febc2682852579b0" + _type = "geometry_msgs/TransformStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This expresses a transform from coordinate frame header.frame_id +# to the coordinate frame child_frame_id +# +# This message is mostly used by the +# tf package. +# See its documentation for more information. + +Header header +string child_frame_id # the frame id of the child frame +Transform transform + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Transform +# This represents the transform between two coordinate frames in free space. + +Vector3 translation +Quaternion rotation + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z +================================================================================ +MSG: geometry_msgs/Quaternion +# This represents an orientation in free space in quaternion form. + +float64 x +float64 y +float64 z +float64 w +""" + __slots__ = ['header','child_frame_id','transform'] + _slot_types = ['std_msgs/Header','string','geometry_msgs/Transform'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,child_frame_id,transform + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(TransformStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.child_frame_id is None: + self.child_frame_id = '' + if self.transform is None: + self.transform = geometry_msgs.msg.Transform() + else: + self.header = std_msgs.msg.Header() + self.child_frame_id = '' + self.transform = geometry_msgs.msg.Transform() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Twist(genpy.Message): + _md5sum = "9f195f881246fdfa2798d1d3eebca84a" + _type = "geometry_msgs/Twist" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This expresses velocity in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['linear','angular'] + _slot_types = ['geometry_msgs/Vector3','geometry_msgs/Vector3'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + linear,angular + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Twist, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + else: + self.linear = geometry_msgs.msg.Vector3() + self.angular = geometry_msgs.msg.Vector3() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z)) + 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: + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.linear is None: + self.linear = geometry_msgs.msg.Vector3() + if self.angular is None: + self.angular = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.linear.x, _x.linear.y, _x.linear.z, _x.angular.x, _x.angular.y, _x.angular.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_6d = None +def _get_struct_6d(): + global _struct_6d + if _struct_6d is None: + _struct_6d = struct.Struct("<6d") + return _struct_6d diff --git a/geometry_msgs/msg/_TwistStamped.py b/geometry_msgs/msg/_TwistStamped.py new file mode 100644 index 0000000..1f96bad --- /dev/null +++ b/geometry_msgs/msg/_TwistStamped.py @@ -0,0 +1,209 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/TwistStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class TwistStamped(genpy.Message): + _md5sum = "98d34b0043a2093cf9d9345ab6eef12e" + _type = "geometry_msgs/TwistStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# A twist with reference coordinate frame and timestamp +Header header +Twist twist + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Twist +# This expresses velocity in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','twist'] + _slot_types = ['std_msgs/Header','geometry_msgs/Twist'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,twist + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(TwistStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.twist is None: + self.twist = geometry_msgs.msg.Twist() + else: + self.header = std_msgs.msg.Header() + self.twist = geometry_msgs.msg.Twist() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class TwistWithCovariance(genpy.Message): + _md5sum = "1fe8a28e6890a4cc3ae4c3ca5c7d82e6" + _type = "geometry_msgs/TwistWithCovariance" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This expresses velocity in free space with uncertainty. + +Twist twist + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Twist +# This expresses velocity in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['twist','covariance'] + _slot_types = ['geometry_msgs/Twist','float64[36]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + twist,covariance + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(TwistWithCovariance, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.twist is None: + self.twist = geometry_msgs.msg.Twist() + if self.covariance is None: + self.covariance = [0.] * 36 + else: + self.twist = geometry_msgs.msg.Twist() + self.covariance = [0.] * 36 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.twist.linear.x, _x.twist.linear.y, _x.twist.linear.z, _x.twist.angular.x, _x.twist.angular.y, _x.twist.angular.z)) + buff.write(_get_struct_36d().pack(*self.covariance)) + 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: + if self.twist is None: + self.twist = geometry_msgs.msg.Twist() + end = 0 + _x = self + start = end + end += 48 + (_x.twist.linear.x, _x.twist.linear.y, _x.twist.linear.z, _x.twist.angular.x, _x.twist.angular.y, _x.twist.angular.z,) = _get_struct_6d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = _get_struct_36d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.twist.linear.x, _x.twist.linear.y, _x.twist.linear.z, _x.twist.angular.x, _x.twist.angular.y, _x.twist.angular.z)) + buff.write(self.covariance.tostring()) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.twist is None: + self.twist = geometry_msgs.msg.Twist() + end = 0 + _x = self + start = end + end += 48 + (_x.twist.linear.x, _x.twist.linear.y, _x.twist.linear.z, _x.twist.angular.x, _x.twist.angular.y, _x.twist.angular.z,) = _get_struct_6d().unpack(str[start:end]) + start = end + end += 288 + self.covariance = numpy.frombuffer(str[start:end], dtype=numpy.float64, count=36) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_36d = None +def _get_struct_36d(): + global _struct_36d + if _struct_36d is None: + _struct_36d = struct.Struct("<36d") + return _struct_36d +_struct_6d = None +def _get_struct_6d(): + global _struct_6d + if _struct_6d is None: + _struct_6d = struct.Struct("<6d") + return _struct_6d diff --git a/geometry_msgs/msg/_TwistWithCovarianceStamped.py b/geometry_msgs/msg/_TwistWithCovarianceStamped.py new file mode 100644 index 0000000..2da025d --- /dev/null +++ b/geometry_msgs/msg/_TwistWithCovarianceStamped.py @@ -0,0 +1,235 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/TwistWithCovarianceStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class TwistWithCovarianceStamped(genpy.Message): + _md5sum = "8927a1a12fb2607ceea095b2dc440a96" + _type = "geometry_msgs/TwistWithCovarianceStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents an estimated twist with reference coordinate frame and timestamp. +Header header +TwistWithCovariance twist + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/TwistWithCovariance +# This expresses velocity in free space with uncertainty. + +Twist twist + +# Row-major representation of the 6x6 covariance matrix +# The orientation parameters use a fixed-axis representation. +# In order, the parameters are: +# (x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis) +float64[36] covariance + +================================================================================ +MSG: geometry_msgs/Twist +# This expresses velocity in free space broken into its linear and angular parts. +Vector3 linear +Vector3 angular + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','twist'] + _slot_types = ['std_msgs/Header','geometry_msgs/TwistWithCovariance'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,twist + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(TwistWithCovarianceStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.twist is None: + self.twist = geometry_msgs.msg.TwistWithCovariance() + else: + self.header = std_msgs.msg.Header() + self.twist = geometry_msgs.msg.TwistWithCovariance() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + + +class Vector3(genpy.Message): + _md5sum = "4a842b65f413084dc2b10fb484ea7f17" + _type = "geometry_msgs/Vector3" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['x','y','z'] + _slot_types = ['float64','float64','float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + x,y,z + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Vector3, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.x is None: + self.x = 0. + if self.y is None: + self.y = 0. + if self.z is None: + self.z = 0. + else: + self.x = 0. + self.y = 0. + self.z = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.z)) + 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 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.z,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_3d().pack(_x.x, _x.y, _x.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + end = 0 + _x = self + start = end + end += 24 + (_x.x, _x.y, _x.z,) = _get_struct_3d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_3d = None +def _get_struct_3d(): + global _struct_3d + if _struct_3d is None: + _struct_3d = struct.Struct("<3d") + return _struct_3d diff --git a/geometry_msgs/msg/_Vector3Stamped.py b/geometry_msgs/msg/_Vector3Stamped.py new file mode 100644 index 0000000..b56e6d7 --- /dev/null +++ b/geometry_msgs/msg/_Vector3Stamped.py @@ -0,0 +1,203 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/Vector3Stamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class Vector3Stamped(genpy.Message): + _md5sum = "7b324c7325e683bf02a9b14b01090ec7" + _type = "geometry_msgs/Vector3Stamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# This represents a Vector3 with reference coordinate frame and timestamp +Header header +Vector3 vector + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','vector'] + _slot_types = ['std_msgs/Header','geometry_msgs/Vector3'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,vector + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Vector3Stamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.vector is None: + self.vector = geometry_msgs.msg.Vector3() + else: + self.header = std_msgs.msg.Header() + self.vector = geometry_msgs.msg.Vector3() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg + +class Wrench(genpy.Message): + _md5sum = "4f539cf138b23283b520fd271b567936" + _type = "geometry_msgs/Wrench" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# This represents force in free space, separated into +# its linear and angular parts. +Vector3 force +Vector3 torque + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['force','torque'] + _slot_types = ['geometry_msgs/Vector3','geometry_msgs/Vector3'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + force,torque + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Wrench, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.force is None: + self.force = geometry_msgs.msg.Vector3() + if self.torque is None: + self.torque = geometry_msgs.msg.Vector3() + else: + self.force = geometry_msgs.msg.Vector3() + self.torque = geometry_msgs.msg.Vector3() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.force.x, _x.force.y, _x.force.z, _x.torque.x, _x.torque.y, _x.torque.z)) + 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: + if self.force is None: + self.force = geometry_msgs.msg.Vector3() + if self.torque is None: + self.torque = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.force.x, _x.force.y, _x.force.z, _x.torque.x, _x.torque.y, _x.torque.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + + + def serialize_numpy(self, buff, numpy): + """ + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + """ + try: + _x = self + buff.write(_get_struct_6d().pack(_x.force.x, _x.force.y, _x.force.z, _x.torque.x, _x.torque.y, _x.torque.z)) + 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_numpy(self, str, numpy): + """ + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + """ + try: + if self.force is None: + self.force = geometry_msgs.msg.Vector3() + if self.torque is None: + self.torque = geometry_msgs.msg.Vector3() + end = 0 + _x = self + start = end + end += 48 + (_x.force.x, _x.force.y, _x.force.z, _x.torque.x, _x.torque.y, _x.torque.z,) = _get_struct_6d().unpack(str[start:end]) + return self + except struct.error as e: + raise genpy.DeserializationError(e) #most likely buffer underfill + +_struct_I = genpy.struct_I +def _get_struct_I(): + global _struct_I + return _struct_I +_struct_6d = None +def _get_struct_6d(): + global _struct_6d + if _struct_6d is None: + _struct_6d = struct.Struct("<6d") + return _struct_6d diff --git a/geometry_msgs/msg/_WrenchStamped.py b/geometry_msgs/msg/_WrenchStamped.py new file mode 100644 index 0000000..a3f12c8 --- /dev/null +++ b/geometry_msgs/msg/_WrenchStamped.py @@ -0,0 +1,210 @@ +# This Python file uses the following encoding: utf-8 +"""autogenerated by genpy from geometry_msgs/WrenchStamped.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False +import genpy +import struct + +import geometry_msgs.msg +import std_msgs.msg + +class WrenchStamped(genpy.Message): + _md5sum = "d78d3cb249ce23087ade7e7d0c40cfa7" + _type = "geometry_msgs/WrenchStamped" + _has_header = True #flag to mark the presence of a Header object + _full_text = """# A wrench with reference coordinate frame and timestamp +Header header +Wrench wrench + +================================================================================ +MSG: std_msgs/Header +# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +# 0: no frame +# 1: global frame +string frame_id + +================================================================================ +MSG: geometry_msgs/Wrench +# This represents force in free space, separated into +# its linear and angular parts. +Vector3 force +Vector3 torque + +================================================================================ +MSG: geometry_msgs/Vector3 +# This represents a vector in free space. +# It is only meant to represent a direction. Therefore, it does not +# make sense to apply a translation to it (e.g., when applying a +# generic rigid transformation to a Vector3, tf2 will only apply the +# rotation). If you want your data to be translatable too, use the +# geometry_msgs/Point message instead. + +float64 x +float64 y +float64 z""" + __slots__ = ['header','wrench'] + _slot_types = ['std_msgs/Header','geometry_msgs/Wrench'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + header,wrench + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(WrenchStamped, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.header is None: + self.header = std_msgs.msg.Header() + if self.wrench is None: + self.wrench = geometry_msgs.msg.Wrench() + else: + self.header = std_msgs.msg.Header() + self.wrench = geometry_msgs.msg.Wrench() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types + + def serialize(self, buff): + """ + serialize message into buffer + :param buff: buffer, ``StringIO`` + """ + try: + _x = self + buff.write(_get_struct_3I().pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs)) + _x = self.header.frame_id + length = len(_x) + if python3 or type(_x) == unicode: + _x = _x.encode('utf-8') + length = len(_x) + buff.write(struct.pack(' Date: Mon, 22 Apr 2019 21:56:24 +0900 Subject: [PATCH 05/11] Add transformer class as ROS-like interface --- tiny_tf/test_transformer.py | 128 ++++++++++++++++++++++++++++++++++++ tiny_tf/transformer.py | 70 ++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 tiny_tf/test_transformer.py create mode 100644 tiny_tf/transformer.py diff --git a/tiny_tf/test_transformer.py b/tiny_tf/test_transformer.py new file mode 100644 index 0000000..d969770 --- /dev/null +++ b/tiny_tf/test_transformer.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +import transformer as tf +import transformations as tf_transformations +import numpy as np +import geometry_msgs.msg + +from math import pi + +class TFTest(): + def transformTargetPoseFromTipLinkToEE(self, tree, ps, robot_name, end_effector_link): + """ + Example of a function using TF copied from another project. + """ + print("Received a pose to transform to EE link:") + print(str(ps.pose.position.x) + ", " + str(ps.pose.position.y) + ", " + str(ps.pose.position.z)) + print(str(ps.pose.orientation.x) + ", " + str(ps.pose.orientation.y) + ", " + str(ps.pose.orientation.z) + ", " + str(ps.pose.orientation.w)) + + # t = tree.lookupTransform(end_effector_link, robot_name + "_tool0") + t = tree.lookup_transform(end_effector_link, robot_name + "_tool0") + + m = geometry_msgs.msg.TransformStamped() + m.header.frame_id = ps.header.frame_id + m.child_frame_id = "temp_goal_pose" + m.transform.translation.x = ps.pose.position.x + m.transform.translation.y = ps.pose.position.y + m.transform.translation.z = ps.pose.position.z + m.transform.rotation.x = ps.pose.orientation.x + m.transform.rotation.y = ps.pose.orientation.y + m.transform.rotation.z = ps.pose.orientation.z + m.transform.rotation.w = ps.pose.orientation.w + tree.setTransform(m) + + # m.header.frame_id = "temp_goal_pose" + # m.child_frame_id = "temp_wrist_pose" + # m.transform.translation.x = t[0][0] + # m.transform.translation.y = t[0][1] + # m.transform.translation.z = t[0][2] + # m.transform.rotation.x = t[1][0] + # m.transform.rotation.y = t[1][1] + # m.transform.rotation.z = t[1][2] + # m.transform.rotation.w = t[1][3] + # tree.setTransform(m) + + m.header.frame_id = "temp_goal_pose" + m.child_frame_id = "temp_wrist_pose" + m.transform.translation.x = t.x + m.transform.translation.y = t.y + m.transform.translation.z = t.z + m.transform.rotation.x = t.qx + m.transform.rotation.y = t.qy + m.transform.rotation.z = t.qz + m.transform.rotation.w = t.qw + tree.setTransform(m) + + ps_wrist = geometry_msgs.msg.PoseStamped() + ps_wrist.header.frame_id = "temp_wrist_pose" + ps_wrist.pose.orientation.w = 1.0 + + ps_new = tree.transformPose(ps.header.frame_id, ps_wrist) + + print("New pose:") + print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + + return ps_new + + def set_transformations(self, tree): + '''This sets up a TF tree for testing.''' + + m = geometry_msgs.msg.TransformStamped() + m.header.frame_id = "world" + m.child_frame_id = "robot_tool0" + m.transform.translation.z = 5.0 + m.transform.rotation.w = 1.0 + tree.setTransform(m) + + self.points = [ [0.0,0.0,1.0], [0.0,0.0,1.0], [0.0,0.0,1.0], + [0.0,1.0,0.0], [0.0,1.0,0.0], [0.0,1.0,0.0], + [1.0,0.0,0.0], [1.0,0.0,0.0], [1.0,0.0,0.0], + [1.0,0.0,1.0], [1.0,0.0,1.0], [1.0,0.0,1.0], + [0.0,1.0,2.0], [0.0,1.0,2.0], [0.0,1.0,2.0]] + self.rpys = [ [pi, pi*45/180, pi/2], [pi/2, pi, pi*45/180], [pi*45/180, pi/2, pi], + [0, pi*555/180, pi/2], [pi/2, 0, pi*555/180], [pi*555/180, pi/2, 0], + [pi*30/180, pi*45/180, pi/2], [pi/2, pi*30/180, pi*45/180], [pi*45/180, pi/2, pi*30/180], + [0, pi*15/180, 0], [0, 0, pi*15/180], [pi*15/180, 0, 0], + [pi/2, pi/2, pi/2], [pi, pi, pi], [2*pi, 2*pi, 2*pi] ] + + for i in range(len(self.points)): + m.transform.translation = geometry_msgs.msg.Point(*self.points[i]) + m.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*self.rpys[i])) + m.child_frame_id = "frame" + str(i) + tree.setTransform(m) + + m.header.frame_id = "frame5" + for i in range(len(self.points)): + m.transform.translation = geometry_msgs.msg.Point(*self.points[i]) + m.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*self.rpys[i])) + m.child_frame_id = "frame" + str(i + len(self.points)) + tree.setTransform(m) + return + + def test_transformations(self, tree): + ps = geometry_msgs.msg.PoseStamped() + ps.pose.orientation.w = 1.0 + + for i in range(len(self.points) * 2): + ps.header.frame_id = "frame"+str(i) + ps_new = tree.transformPose("world", ps) + print("Pose nr. " + str(i) + ": " \ + + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z) + "; " \ + + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + + ps.header.frame_id = "world" + ps.pose.position.z = 8.0 + ps_new = self.transformTargetPoseFromTipLinkToEE(tree, ps, "robot", "frame0") + print("Pose nr. " + str(len(self.points) * 2) + ": " \ + + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z) + "; " \ + + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + return + +if __name__ == '__main__': + c = TFTest() + tree = tf.Transformer() + c.set_transformations(tree) + c.test_transformations(tree) + print("============ Done!") + \ No newline at end of file diff --git a/tiny_tf/transformer.py b/tiny_tf/transformer.py new file mode 100644 index 0000000..db1a73a --- /dev/null +++ b/tiny_tf/transformer.py @@ -0,0 +1,70 @@ +from tf import * +import numpy as np +import transformations as tft +from collections import namedtuple +import geometry_msgs + + +class Transformer(TFTree): + """ + This class implements the same interfaces as the ROS tf.TransformListener(). + """ + def __init__(self): + super(Transformer, self).__init__() + + def setTransform(self, transform_stamped): + """ + For geometry_msgs.msg.TransformStamped + """ + xform = Transform(transform_stamped.transform.translation.x, + transform_stamped.transform.translation.y, + transform_stamped.transform.translation.z, + transform_stamped.transform.rotation.x, + transform_stamped.transform.rotation.y, + transform_stamped.transform.rotation.z, + transform_stamped.transform.rotation.w) + parent = transform_stamped.header.frame_id + child = transform_stamped.child_frame_id + self.add_transform(parent, child, xform) + + def transformPoint(self, target_frame, point_stamped): + """ + point_stamped is a geometry_msgs.msg.PointStamped object. + Returns a PointStamped transformed to target_frame. + """ + t = self.lookup_transform(point_stamped.header.frame_id, target_frame) + p = self.transform_point(point_stamped.point.position.x, point_stamped.point.position.y, point_stamped.point.position.z, target_frame, point_stamped.header.frame_id) + ps_out = geometry_msgs.msg.PointStamped() + ps_out.header.frame_id = target_frame + ps_out.point.position.x = p[0] + ps_out.point.position.y = p[1] + ps_out.point.position.z = p[2] + return ps_out + + def transformPose(self, target_frame, pose_stamped): + """ + pose_stamped is a geometry_msgs.msg.PoseStamped object + Returns a PoseStamped transformed to target_frame. + """ + t = self.lookup_transform(pose_stamped.header.frame_id, target_frame) + p = self.transform_pose(pose_stamped.pose.position.x, pose_stamped.pose.position.y, pose_stamped.pose.position.z, + pose_stamped.pose.orientation.x, pose_stamped.pose.orientation.y, pose_stamped.pose.orientation.z, pose_stamped.pose.orientation.w, + target_frame, pose_stamped.header.frame_id) + ps_out = geometry_msgs.msg.PoseStamped() + ps_out.header.frame_id = target_frame + ps_out.pose.position.x = p[0] + ps_out.pose.position.y = p[1] + ps_out.pose.position.z = p[2] + ps_out.pose.orientation.x = p[3] + ps_out.pose.orientation.y = p[4] + ps_out.pose.orientation.z = p[5] + ps_out.pose.orientation.w = p[6] + return ps_out + + def lookupTransform(self, base_frame, target_frame): + """ + Returns a TransformStamped from base_frame to target_frame + """ + # TODO + # t = geometry_msgs.msg.TransformStamped() + return self.lookup_transform(base_frame, target_frame) \ No newline at end of file From 6b1081223bf74aa81312fb1b6049272b1f6b5f49 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 29 Apr 2019 16:36:11 +0900 Subject: [PATCH 06/11] Simplify test_transformer.py --- tiny_tf/test_transformer.py | 200 ++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 114 deletions(-) diff --git a/tiny_tf/test_transformer.py b/tiny_tf/test_transformer.py index d969770..fba3243 100644 --- a/tiny_tf/test_transformer.py +++ b/tiny_tf/test_transformer.py @@ -7,122 +7,94 @@ from math import pi -class TFTest(): - def transformTargetPoseFromTipLinkToEE(self, tree, ps, robot_name, end_effector_link): - """ - Example of a function using TF copied from another project. - """ - print("Received a pose to transform to EE link:") - print(str(ps.pose.position.x) + ", " + str(ps.pose.position.y) + ", " + str(ps.pose.position.z)) - print(str(ps.pose.orientation.x) + ", " + str(ps.pose.orientation.y) + ", " + str(ps.pose.orientation.z) + ", " + str(ps.pose.orientation.w)) - - # t = tree.lookupTransform(end_effector_link, robot_name + "_tool0") - t = tree.lookup_transform(end_effector_link, robot_name + "_tool0") - - m = geometry_msgs.msg.TransformStamped() - m.header.frame_id = ps.header.frame_id - m.child_frame_id = "temp_goal_pose" - m.transform.translation.x = ps.pose.position.x - m.transform.translation.y = ps.pose.position.y - m.transform.translation.z = ps.pose.position.z - m.transform.rotation.x = ps.pose.orientation.x - m.transform.rotation.y = ps.pose.orientation.y - m.transform.rotation.z = ps.pose.orientation.z - m.transform.rotation.w = ps.pose.orientation.w - tree.setTransform(m) - - # m.header.frame_id = "temp_goal_pose" - # m.child_frame_id = "temp_wrist_pose" - # m.transform.translation.x = t[0][0] - # m.transform.translation.y = t[0][1] - # m.transform.translation.z = t[0][2] - # m.transform.rotation.x = t[1][0] - # m.transform.rotation.y = t[1][1] - # m.transform.rotation.z = t[1][2] - # m.transform.rotation.w = t[1][3] - # tree.setTransform(m) - - m.header.frame_id = "temp_goal_pose" - m.child_frame_id = "temp_wrist_pose" - m.transform.translation.x = t.x - m.transform.translation.y = t.y - m.transform.translation.z = t.z - m.transform.rotation.x = t.qx - m.transform.rotation.y = t.qy - m.transform.rotation.z = t.qz - m.transform.rotation.w = t.qw - tree.setTransform(m) - - ps_wrist = geometry_msgs.msg.PoseStamped() - ps_wrist.header.frame_id = "temp_wrist_pose" - ps_wrist.pose.orientation.w = 1.0 - - ps_new = tree.transformPose(ps.header.frame_id, ps_wrist) - - print("New pose:") - print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) - print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) - - return ps_new - - def set_transformations(self, tree): - '''This sets up a TF tree for testing.''' - - m = geometry_msgs.msg.TransformStamped() - m.header.frame_id = "world" - m.child_frame_id = "robot_tool0" - m.transform.translation.z = 5.0 - m.transform.rotation.w = 1.0 - tree.setTransform(m) - - self.points = [ [0.0,0.0,1.0], [0.0,0.0,1.0], [0.0,0.0,1.0], - [0.0,1.0,0.0], [0.0,1.0,0.0], [0.0,1.0,0.0], - [1.0,0.0,0.0], [1.0,0.0,0.0], [1.0,0.0,0.0], - [1.0,0.0,1.0], [1.0,0.0,1.0], [1.0,0.0,1.0], - [0.0,1.0,2.0], [0.0,1.0,2.0], [0.0,1.0,2.0]] - self.rpys = [ [pi, pi*45/180, pi/2], [pi/2, pi, pi*45/180], [pi*45/180, pi/2, pi], - [0, pi*555/180, pi/2], [pi/2, 0, pi*555/180], [pi*555/180, pi/2, 0], - [pi*30/180, pi*45/180, pi/2], [pi/2, pi*30/180, pi*45/180], [pi*45/180, pi/2, pi*30/180], - [0, pi*15/180, 0], [0, 0, pi*15/180], [pi*15/180, 0, 0], - [pi/2, pi/2, pi/2], [pi, pi, pi], [2*pi, 2*pi, 2*pi] ] - - for i in range(len(self.points)): - m.transform.translation = geometry_msgs.msg.Point(*self.points[i]) - m.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*self.rpys[i])) - m.child_frame_id = "frame" + str(i) - tree.setTransform(m) - - m.header.frame_id = "frame5" - for i in range(len(self.points)): - m.transform.translation = geometry_msgs.msg.Point(*self.points[i]) - m.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*self.rpys[i])) - m.child_frame_id = "frame" + str(i + len(self.points)) - tree.setTransform(m) - return - - def test_transformations(self, tree): - ps = geometry_msgs.msg.PoseStamped() - ps.pose.orientation.w = 1.0 - - for i in range(len(self.points) * 2): - ps.header.frame_id = "frame"+str(i) - ps_new = tree.transformPose("world", ps) - print("Pose nr. " + str(i) + ": " \ - + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z) + "; " \ - + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) - - ps.header.frame_id = "world" - ps.pose.position.z = 8.0 - ps_new = self.transformTargetPoseFromTipLinkToEE(tree, ps, "robot", "frame0") - print("Pose nr. " + str(len(self.points) * 2) + ": " \ - + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z) + "; " \ - + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) - return + +def set_transformations(tree): + '''This sets up a TF tree for testing.''' + + # Define a little robot + ts = geometry_msgs.msg.TransformStamped() + ts.header.frame_id = "world" + ts.child_frame_id = "robot_wrist" + ts.transform.translation.z = 1.0 + ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, pi*90/180, 0)) + tree.setTransform(ts) + + ts.header.frame_id = "robot_wrist" + ts.child_frame_id = "robot_tooltip" + ts.transform.translation.z = 0.1 + ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, 0, 0)) + tree.setTransform(ts) + + ts.header.frame_id = "robot_wrist" + ts.child_frame_id = "robot_camera" + ts.transform.translation.x = geometry_msgs.msg.Point(x=-0.1, y=0.0, z=0.05) + ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, pi*20/180, 0)) + tree.setTransform(ts) + + + # Define a shelf + ts.header.frame_id = "world" + ts.child_frame_id = "shelf" + ts.transform.translation.x = geometry_msgs.msg.Point(1.0, 0.0, 0.0) + ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, 0, 0)) + tree.setTransform(ts) + + # Define some objects in the shelf + points = [ [0.0, 0.0, 0.5], [0.0, 0.0, 1.0], [0.0, 0.0, 1.5]] + rpys = [ [pi, pi*45/180, 0], [0, pi, pi*45/180], [pi*45/180, 0, pi]] + + ts.header.frame_id = "shelf" + for i in range(len(points)): + ts.transform.translation = geometry_msgs.msg.Point(*points[i]) + ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*rpys[i])) + ts.child_frame_id = "object_frame_" + str(i) + tree.setTransform(ts) + return + +def test_transformations(tree): + ## Transform a pose + ps = geometry_msgs.msg.PoseStamped() + ps.pose.orientation.w = 1.0 # == no rotation + ps.header.frame_id = "robot_tooltip" + + ps_new = tree.transformPose("world", ps) + print("Robot tooltip position in the world frame:") + print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) + print("In Euler angles: " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + + ps_new = tree.transformPose("robot_camera", ps) + print("Robot tooltip position, as seen by the camera / in the camera frame:") + print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) + print("In Euler angles: " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + + ps.header.frame_id = "object_frame_3" + ps_new = tree.transformPose("robot_camera", ps) + print("object_frame_3 position, as seen by the camera / in the camera frame:") + print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + + ## Transform a point + pt = geometry_msgs.msg.PointStamped() + pt.point.position.z = 0.5 + pt.header.frame_id = "shelf" + + pt_new = tree.transformPoint("world", pt) + print("z = 0.5 on the shelf, in world coordinates:") + print(str(pt_new.point.position.x) + ", " + str(pt_new.point.position.y) + ", " + str(pt_new.point.position.z)) + + pt.point.position.z = 0.0 + pt.header.frame_id = "object_frame_2" + pt_new = tree.transformPoint("robot_wrist", pt) + point_array = np.array([pt_new.point.position.x, pt_new.point.position.y, pt_new.point.position.z]) + print("Distance of object_frame_2 to robot_wrist:" + str(np.norm(point_array))) + return if __name__ == '__main__': - c = TFTest() tree = tf.Transformer() - c.set_transformations(tree) - c.test_transformations(tree) + set_transformations(tree) + test_transformations(tree) print("============ Done!") \ No newline at end of file From 78740ded73c061790522f13b7a555ba4e5ff64c5 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Mon, 29 Apr 2019 16:54:50 +0900 Subject: [PATCH 07/11] Bugfixes --- tiny_tf/test_transformer.py | 15 +++++++-------- tiny_tf/transformer.py | 8 ++++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/tiny_tf/test_transformer.py b/tiny_tf/test_transformer.py index fba3243..2c79f18 100644 --- a/tiny_tf/test_transformer.py +++ b/tiny_tf/test_transformer.py @@ -31,7 +31,6 @@ def set_transformations(tree): ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, pi*20/180, 0)) tree.setTransform(ts) - # Define a shelf ts.header.frame_id = "world" ts.child_frame_id = "shelf" @@ -47,7 +46,7 @@ def set_transformations(tree): for i in range(len(points)): ts.transform.translation = geometry_msgs.msg.Point(*points[i]) ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(*rpys[i])) - ts.child_frame_id = "object_frame_" + str(i) + ts.child_frame_id = "object_frame_" + str(i+1) tree.setTransform(ts) return @@ -62,14 +61,14 @@ def test_transformations(tree): print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) - print("In Euler angles: " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + print("In Euler angles (rad): " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) ps_new = tree.transformPose("robot_camera", ps) print("Robot tooltip position, as seen by the camera / in the camera frame:") print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) - print("In Euler angles: " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + print("In Euler angles (rad): " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) ps.header.frame_id = "object_frame_3" ps_new = tree.transformPose("robot_camera", ps) @@ -78,17 +77,17 @@ def test_transformations(tree): ## Transform a point pt = geometry_msgs.msg.PointStamped() - pt.point.position.z = 0.5 + pt.point.z = 0.5 pt.header.frame_id = "shelf" pt_new = tree.transformPoint("world", pt) print("z = 0.5 on the shelf, in world coordinates:") - print(str(pt_new.point.position.x) + ", " + str(pt_new.point.position.y) + ", " + str(pt_new.point.position.z)) + print(str(pt_new.point.x) + ", " + str(pt_new.point.y) + ", " + str(pt_new.point.z)) - pt.point.position.z = 0.0 + pt.point.z = 0.0 pt.header.frame_id = "object_frame_2" pt_new = tree.transformPoint("robot_wrist", pt) - point_array = np.array([pt_new.point.position.x, pt_new.point.position.y, pt_new.point.position.z]) + point_array = np.array([pt_new.point.x, pt_new.point.y, pt_new.point.z]) print("Distance of object_frame_2 to robot_wrist:" + str(np.norm(point_array))) return diff --git a/tiny_tf/transformer.py b/tiny_tf/transformer.py index db1a73a..e0840b0 100644 --- a/tiny_tf/transformer.py +++ b/tiny_tf/transformer.py @@ -33,12 +33,12 @@ def transformPoint(self, target_frame, point_stamped): Returns a PointStamped transformed to target_frame. """ t = self.lookup_transform(point_stamped.header.frame_id, target_frame) - p = self.transform_point(point_stamped.point.position.x, point_stamped.point.position.y, point_stamped.point.position.z, target_frame, point_stamped.header.frame_id) + p = self.transform_point(point_stamped.point.x, point_stamped.point.y, point_stamped.point.z, target_frame, point_stamped.header.frame_id) ps_out = geometry_msgs.msg.PointStamped() ps_out.header.frame_id = target_frame - ps_out.point.position.x = p[0] - ps_out.point.position.y = p[1] - ps_out.point.position.z = p[2] + ps_out.point.x = p[0] + ps_out.point.y = p[1] + ps_out.point.z = p[2] return ps_out def transformPose(self, target_frame, pose_stamped): From 4b2001976266b6702414c7e9e3970bdc517f2f54 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Tue, 30 Apr 2019 19:42:47 +0900 Subject: [PATCH 08/11] More bugfixes --- tiny_tf/test_transformer.py | 4 ++-- tiny_tf/tf.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tiny_tf/test_transformer.py b/tiny_tf/test_transformer.py index 2c79f18..df5465d 100644 --- a/tiny_tf/test_transformer.py +++ b/tiny_tf/test_transformer.py @@ -27,14 +27,14 @@ def set_transformations(tree): ts.header.frame_id = "robot_wrist" ts.child_frame_id = "robot_camera" - ts.transform.translation.x = geometry_msgs.msg.Point(x=-0.1, y=0.0, z=0.05) + ts.transform.translation = geometry_msgs.msg.Point(x=-0.1, y=0.0, z=0.05) ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, pi*20/180, 0)) tree.setTransform(ts) # Define a shelf ts.header.frame_id = "world" ts.child_frame_id = "shelf" - ts.transform.translation.x = geometry_msgs.msg.Point(1.0, 0.0, 0.0) + ts.transform.translation = geometry_msgs.msg.Point(1.0, 0.0, 0.0) ts.transform.rotation = geometry_msgs.msg.Quaternion(*tf_transformations.quaternion_from_euler(0, 0, 0)) tree.setTransform(ts) diff --git a/tiny_tf/tf.py b/tiny_tf/tf.py index 0bb555d..f3d1d62 100644 --- a/tiny_tf/tf.py +++ b/tiny_tf/tf.py @@ -114,7 +114,7 @@ def transform_pose(self, x, y, z, qx, qy, qz, qw, target, base): t = self.lookup_transform(base, target) xyz = np.dot(t.matrix, np.array([x, y, z, 1]))[0:3] q = tft.quaternion_multiply([qx, qy, qz, qw], [t.qx, t.qy, t.qz, t.qw]) - return [*xyz, *q] + return [xyz[0], xyz[1], xyz[2], q[0], q[1], q[2], q[3]] class TFNode(object): def __init__(self, name, parent, transform): From 9453cda88b9138c4a10d5ba3ee9cba083d32ace3 Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Wed, 1 May 2019 14:45:20 +0900 Subject: [PATCH 09/11] Fix up test_transformer.py --- tiny_tf/test_transformer.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tiny_tf/test_transformer.py b/tiny_tf/test_transformer.py index df5465d..5691e49 100644 --- a/tiny_tf/test_transformer.py +++ b/tiny_tf/test_transformer.py @@ -58,22 +58,22 @@ def test_transformations(tree): ps_new = tree.transformPose("world", ps) print("Robot tooltip position in the world frame:") - print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) - print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + print("xyz: " + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print("rotation: " + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) - print("In Euler angles (rad): " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + print("In Euler angles (deg): " + str(rpy[0]*180/pi) + ", " + str(rpy[1]*180/pi) + ", " + str(rpy[2]*180/pi) + "\n") ps_new = tree.transformPose("robot_camera", ps) print("Robot tooltip position, as seen by the camera / in the camera frame:") - print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) - print(str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) + print("xyz: " + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print("rotation: " + str(ps_new.pose.orientation.x) + ", " + str(ps_new.pose.orientation.y) + ", " + str(ps_new.pose.orientation.z) + ", " + str(ps_new.pose.orientation.w)) rpy = tf_transformations.euler_from_quaternion([ps_new.pose.orientation.x, ps_new.pose.orientation.y, ps_new.pose.orientation.z, ps_new.pose.orientation.w]) - print("In Euler angles (rad): " + str(rpy[0]) + ", " + str(rpy[1]) + ", " + str(rpy[2])) + print("In Euler angles (deg): " + str(rpy[0]*180/pi) + ", " + str(rpy[1]*180/pi) + ", " + str(rpy[2]*180/pi) + "\n") ps.header.frame_id = "object_frame_3" ps_new = tree.transformPose("robot_camera", ps) print("object_frame_3 position, as seen by the camera / in the camera frame:") - print(str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z)) + print("xyz: " + str(ps_new.pose.position.x) + ", " + str(ps_new.pose.position.y) + ", " + str(ps_new.pose.position.z) + "\n") ## Transform a point pt = geometry_msgs.msg.PointStamped() @@ -82,13 +82,13 @@ def test_transformations(tree): pt_new = tree.transformPoint("world", pt) print("z = 0.5 on the shelf, in world coordinates:") - print(str(pt_new.point.x) + ", " + str(pt_new.point.y) + ", " + str(pt_new.point.z)) + print("xyz: " + str(pt_new.point.x) + ", " + str(pt_new.point.y) + ", " + str(pt_new.point.z) + "\n") pt.point.z = 0.0 pt.header.frame_id = "object_frame_2" pt_new = tree.transformPoint("robot_wrist", pt) point_array = np.array([pt_new.point.x, pt_new.point.y, pt_new.point.z]) - print("Distance of object_frame_2 to robot_wrist:" + str(np.norm(point_array))) + print("Distance of object_frame_2 to robot_wrist:" + str(np.linalg.norm(point_array)) + "\n") return if __name__ == '__main__': From b9ab4242e16ba3b9e052d653654668d85ecaae9d Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Tue, 7 May 2019 20:59:38 +0900 Subject: [PATCH 10/11] Brutally add all ROS dependencies From Melodic --- tiny_tf/genmsg/__init__.py | 40 + tiny_tf/genmsg/base.py | 75 ++ tiny_tf/genmsg/command_line.py | 41 + tiny_tf/genmsg/deps.py | 94 ++ tiny_tf/genmsg/gentools.py | 175 +++ tiny_tf/genmsg/msg_loader.py | 489 ++++++++ tiny_tf/genmsg/msgs.py | 349 ++++++ tiny_tf/genmsg/names.py | 145 +++ tiny_tf/genmsg/srvs.py | 78 ++ tiny_tf/genmsg/template_tools.py | 217 ++++ tiny_tf/genpy/__init__.py | 37 + tiny_tf/genpy/base.py | 65 ++ tiny_tf/genpy/dynamic.py | 197 ++++ tiny_tf/genpy/generate_initpy.py | 83 ++ tiny_tf/genpy/generate_numpy.py | 71 ++ tiny_tf/genpy/generate_struct.py | 152 +++ tiny_tf/genpy/generator.py | 1014 +++++++++++++++++ tiny_tf/genpy/genpy_main.py | 87 ++ tiny_tf/genpy/message.py | 655 +++++++++++ tiny_tf/genpy/rostime.py | 442 +++++++ .../geometry_msgs}/__init__.py | 0 .../geometry_msgs}/msg/_Accel.py | 0 .../geometry_msgs}/msg/_AccelStamped.py | 0 .../msg/_AccelWithCovariance.py | 0 .../msg/_AccelWithCovarianceStamped.py | 0 .../geometry_msgs}/msg/_Inertia.py | 0 .../geometry_msgs}/msg/_InertiaStamped.py | 0 .../geometry_msgs}/msg/_Point.py | 0 .../geometry_msgs}/msg/_Point32.py | 0 .../geometry_msgs}/msg/_PointStamped.py | 0 .../geometry_msgs}/msg/_Polygon.py | 0 .../geometry_msgs}/msg/_PolygonStamped.py | 0 .../geometry_msgs}/msg/_Pose.py | 0 .../geometry_msgs}/msg/_Pose2D.py | 0 .../geometry_msgs}/msg/_PoseArray.py | 0 .../geometry_msgs}/msg/_PoseStamped.py | 0 .../geometry_msgs}/msg/_PoseWithCovariance.py | 0 .../msg/_PoseWithCovarianceStamped.py | 0 .../geometry_msgs}/msg/_Quaternion.py | 0 .../geometry_msgs}/msg/_QuaternionStamped.py | 0 .../geometry_msgs}/msg/_Transform.py | 0 .../geometry_msgs}/msg/_TransformStamped.py | 0 .../geometry_msgs}/msg/_Twist.py | 0 .../geometry_msgs}/msg/_TwistStamped.py | 0 .../msg/_TwistWithCovariance.py | 0 .../msg/_TwistWithCovarianceStamped.py | 0 .../geometry_msgs}/msg/_Vector3.py | 0 .../geometry_msgs}/msg/_Vector3Stamped.py | 0 .../geometry_msgs}/msg/_Wrench.py | 0 .../geometry_msgs}/msg/_WrenchStamped.py | 0 .../geometry_msgs}/msg/__init__.py | 0 tiny_tf/std_msgs/__init__.py | 0 tiny_tf/std_msgs/msg/_Bool.py | 43 + tiny_tf/std_msgs/msg/_Byte.py | 44 + tiny_tf/std_msgs/msg/_ByteMultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Char.py | 43 + tiny_tf/std_msgs/msg/_ColorRGBA.py | 56 + tiny_tf/std_msgs/msg/_Duration.py | 45 + tiny_tf/std_msgs/msg/_Empty.py | 38 + tiny_tf/std_msgs/msg/_Float32.py | 43 + tiny_tf/std_msgs/msg/_Float32MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Float64.py | 43 + tiny_tf/std_msgs/msg/_Float64MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Header.py | 63 + tiny_tf/std_msgs/msg/_Int16.py | 44 + tiny_tf/std_msgs/msg/_Int16MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Int32.py | 43 + tiny_tf/std_msgs/msg/_Int32MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Int64.py | 43 + tiny_tf/std_msgs/msg/_Int64MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_Int8.py | 44 + tiny_tf/std_msgs/msg/_Int8MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_MultiArrayDimension.py | 51 + tiny_tf/std_msgs/msg/_MultiArrayLayout.py | 78 ++ tiny_tf/std_msgs/msg/_String.py | 44 + tiny_tf/std_msgs/msg/_Time.py | 45 + tiny_tf/std_msgs/msg/_UInt16.py | 44 + tiny_tf/std_msgs/msg/_UInt16MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_UInt32.py | 43 + tiny_tf/std_msgs/msg/_UInt32MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_UInt64.py | 43 + tiny_tf/std_msgs/msg/_UInt64MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/_UInt8.py | 44 + tiny_tf/std_msgs/msg/_UInt8MultiArray.py | 87 ++ tiny_tf/std_msgs/msg/__init__.py | 32 + 85 files changed, 6479 insertions(+) create mode 100644 tiny_tf/genmsg/__init__.py create mode 100644 tiny_tf/genmsg/base.py create mode 100644 tiny_tf/genmsg/command_line.py create mode 100644 tiny_tf/genmsg/deps.py create mode 100644 tiny_tf/genmsg/gentools.py create mode 100644 tiny_tf/genmsg/msg_loader.py create mode 100644 tiny_tf/genmsg/msgs.py create mode 100644 tiny_tf/genmsg/names.py create mode 100644 tiny_tf/genmsg/srvs.py create mode 100644 tiny_tf/genmsg/template_tools.py create mode 100644 tiny_tf/genpy/__init__.py create mode 100644 tiny_tf/genpy/base.py create mode 100644 tiny_tf/genpy/dynamic.py create mode 100644 tiny_tf/genpy/generate_initpy.py create mode 100644 tiny_tf/genpy/generate_numpy.py create mode 100644 tiny_tf/genpy/generate_struct.py create mode 100644 tiny_tf/genpy/generator.py create mode 100644 tiny_tf/genpy/genpy_main.py create mode 100644 tiny_tf/genpy/message.py create mode 100644 tiny_tf/genpy/rostime.py rename {geometry_msgs => tiny_tf/geometry_msgs}/__init__.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Accel.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_AccelStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_AccelWithCovariance.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_AccelWithCovarianceStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Inertia.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_InertiaStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Point.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Point32.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PointStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Polygon.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PolygonStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Pose.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Pose2D.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PoseArray.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PoseStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PoseWithCovariance.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_PoseWithCovarianceStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Quaternion.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_QuaternionStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Transform.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_TransformStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Twist.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_TwistStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_TwistWithCovariance.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_TwistWithCovarianceStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Vector3.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Vector3Stamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_Wrench.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/_WrenchStamped.py (100%) rename {geometry_msgs => tiny_tf/geometry_msgs}/msg/__init__.py (100%) create mode 100644 tiny_tf/std_msgs/__init__.py create mode 100644 tiny_tf/std_msgs/msg/_Bool.py create mode 100644 tiny_tf/std_msgs/msg/_Byte.py create mode 100644 tiny_tf/std_msgs/msg/_ByteMultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Char.py create mode 100644 tiny_tf/std_msgs/msg/_ColorRGBA.py create mode 100644 tiny_tf/std_msgs/msg/_Duration.py create mode 100644 tiny_tf/std_msgs/msg/_Empty.py create mode 100644 tiny_tf/std_msgs/msg/_Float32.py create mode 100644 tiny_tf/std_msgs/msg/_Float32MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Float64.py create mode 100644 tiny_tf/std_msgs/msg/_Float64MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Header.py create mode 100644 tiny_tf/std_msgs/msg/_Int16.py create mode 100644 tiny_tf/std_msgs/msg/_Int16MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Int32.py create mode 100644 tiny_tf/std_msgs/msg/_Int32MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Int64.py create mode 100644 tiny_tf/std_msgs/msg/_Int64MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_Int8.py create mode 100644 tiny_tf/std_msgs/msg/_Int8MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_MultiArrayDimension.py create mode 100644 tiny_tf/std_msgs/msg/_MultiArrayLayout.py create mode 100644 tiny_tf/std_msgs/msg/_String.py create mode 100644 tiny_tf/std_msgs/msg/_Time.py create mode 100644 tiny_tf/std_msgs/msg/_UInt16.py create mode 100644 tiny_tf/std_msgs/msg/_UInt16MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_UInt32.py create mode 100644 tiny_tf/std_msgs/msg/_UInt32MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_UInt64.py create mode 100644 tiny_tf/std_msgs/msg/_UInt64MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/_UInt8.py create mode 100644 tiny_tf/std_msgs/msg/_UInt8MultiArray.py create mode 100644 tiny_tf/std_msgs/msg/__init__.py diff --git a/tiny_tf/genmsg/__init__.py b/tiny_tf/genmsg/__init__.py new file mode 100644 index 0000000..bd500a1 --- /dev/null +++ b/tiny_tf/genmsg/__init__.py @@ -0,0 +1,40 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from . base import MSG_DIR, SRV_DIR, EXT_MSG, EXT_SRV, SEP, log, plog, InvalidMsgSpec, log_verbose, MsgGenerationException +from . gentools import compute_md5, compute_full_text, compute_md5_text +from . names import resource_name_base, package_resource_name, is_legal_resource_base_name, \ + resource_name_package, resource_name, is_legal_resource_name +from . msgs import HEADER, TIME, DURATION, MsgSpec, Constant, Field +from . msg_loader import MsgNotFound, MsgContext, load_depends, load_msg_by_type, load_srv_by_type +from . srvs import SrvSpec + diff --git a/tiny_tf/genmsg/base.py b/tiny_tf/genmsg/base.py new file mode 100644 index 0000000..b09d89e --- /dev/null +++ b/tiny_tf/genmsg/base.py @@ -0,0 +1,75 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function +import os, sys + +SEP = '/' + +MSG_DIR = 'msg' +SRV_DIR = 'srv' + +EXT_MSG = '.msg' +EXT_SRV = '.srv' + +## character that designates a constant assignment rather than a field +CONSTCHAR = '=' +COMMENTCHAR = '#' +IODELIM = '---' + + +verbose = False + +import inspect, pprint + +def log_verbose(value): + global verbose + verbose = value + +def log(*args): + global verbose + if verbose: + print("%s:%d" % inspect.stack()[1][1:3], file=sys.stderr) + print(' '.join([str(x) for x in args]), file=sys.stderr) + +def plog(msg, obj): + if verbose: + print("%s:%d" % inspect.stack()[1][1:3], file=sys.stderr) + print(msg, " ", file=sys.stderr) + pprint.pprint(obj, file=sys.stderr) + +class InvalidMsgSpec(Exception): + pass + +class MsgGenerationException(Exception): + pass + diff --git a/tiny_tf/genmsg/command_line.py b/tiny_tf/genmsg/command_line.py new file mode 100644 index 0000000..c44be0d --- /dev/null +++ b/tiny_tf/genmsg/command_line.py @@ -0,0 +1,41 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +def includepath_to_dict(includepath): + search_path = {} + if includepath: + for path in includepath: + key = path[:path.find(':')] + value = path[path.find(':')+1:] + if value: + search_path.setdefault(key, []).append(value) + return search_path diff --git a/tiny_tf/genmsg/deps.py b/tiny_tf/genmsg/deps.py new file mode 100644 index 0000000..372c1df --- /dev/null +++ b/tiny_tf/genmsg/deps.py @@ -0,0 +1,94 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import os +import genmsg.msg_loader +import genmsg + +# pkg_name - string +# msg_file - string full path +# search_paths - dict of {'pkg':'msg_dir'} +def find_msg_dependencies_with_type(pkg_name, msg_file, search_paths): + + # Read and parse the source msg file + msg_context = genmsg.msg_loader.MsgContext.create_default() + full_type_name = genmsg.gentools.compute_full_type_name(pkg_name, os.path.basename(msg_file)) + spec = genmsg.msg_loader.load_msg_from_file(msg_context, msg_file, full_type_name) + + try: + genmsg.msg_loader.load_depends(msg_context, spec, search_paths) + except genmsg.InvalidMsgSpec as e: + raise genmsg.MsgGenerationException("Cannot read .msg for %s: %s"%(full_type_name, str(e))) + + deps = set() + for dep_type_name in msg_context.get_all_depends(full_type_name): + deps.add((dep_type_name, msg_context.get_file(dep_type_name))) + + return list(deps) + + +def find_msg_dependencies(pkg_name, msg_file, search_paths): + deps = find_msg_dependencies_with_type(pkg_name, msg_file, search_paths) + return [d[1] for d in deps] + + +def find_srv_dependencies_with_type(pkg_name, msg_file, search_paths): + + # Read and parse the source msg file + msg_context = genmsg.msg_loader.MsgContext.create_default() + full_type_name = genmsg.gentools.compute_full_type_name(pkg_name, os.path.basename(msg_file)) + + spec = genmsg.msg_loader.load_srv_from_file(msg_context, msg_file, full_type_name) + + try: + genmsg.msg_loader.load_depends(msg_context, spec, search_paths) + except genmsg.InvalidMsgSpec as e: + raise genmsg.MsgGenerationException("Cannot read .msg for %s: %s"%(full_type_name, str(e))) + + deps = set() + + for dep_type_name in msg_context.get_all_depends(spec.request.full_name): + deps.add((dep_type_name, msg_context.get_file(dep_type_name))) + + for dep_type_name in msg_context.get_all_depends(spec.response.full_name): + deps.add((dep_type_name, msg_context.get_file(dep_type_name))) + + return list(deps) + + +def find_srv_dependencies(pkg_name, msg_file, search_paths): + deps = find_srv_dependencies_with_type(pkg_name, msg_file, search_paths) + return [d[1] for d in deps] + +#paths = {'std_msgs':'/u/mkjargaard/repositories/mkjargaard/dist-sandbox/std_msgs/msg'} +#file = '/u/mkjargaard/repositories/mkjargaard/dist-sandbox/quux_msgs/msg/QuuxString.msg' +#find_msg_dependencies('quux_msgs', file, paths) diff --git a/tiny_tf/genmsg/gentools.py b/tiny_tf/genmsg/gentools.py new file mode 100644 index 0000000..6f3e23d --- /dev/null +++ b/tiny_tf/genmsg/gentools.py @@ -0,0 +1,175 @@ +#! /usr/bin/env python +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Library for supporting message and service generation for all ROS +client libraries. This is mainly responsible for calculating the +md5sums and message definitions of classes. +""" + +# NOTE: this should not contain any rospy-specific code. The rospy +# generator library is rospy.genpy. + +import sys +import hashlib + +try: + from cStringIO import StringIO # Python 2.x +except ImportError: + from io import StringIO # Python 3.x + +from . import msgs + +from .msgs import InvalidMsgSpec, MsgSpec, bare_msg_type, is_builtin +from .msg_loader import load_depends +from .srvs import SrvSpec +from . import names +from . import base + +def compute_md5_text(msg_context, spec): + """ + Compute the text used for md5 calculation. MD5 spec states that we + removes comments and non-meaningful whitespace. We also strip + packages names from type names. For convenience sake, constants are + reordered ahead of other declarations, in the order that they were + originally defined. + + :returns: text for ROS MD5-processing, ``str`` + """ + package = spec.package + + buff = StringIO() + + for c in spec.constants: + buff.write("%s %s=%s\n"%(c.type, c.name, c.val_text)) + for type_, name in zip(spec.types, spec.names): + msg_type = bare_msg_type(type_) + # md5 spec strips package names + if is_builtin(msg_type): + buff.write("%s %s\n"%(type_, name)) + else: + # recursively generate md5 for subtype. have to build up + # dependency representation for subtype in order to + # generate md5 + sub_pkg, _ = names.package_resource_name(msg_type) + sub_pkg = sub_pkg or package + sub_spec = msg_context.get_registered(msg_type) + sub_md5 = compute_md5(msg_context, sub_spec) + buff.write("%s %s\n"%(sub_md5, name)) + + return buff.getvalue().strip() # remove trailing new line + +def _compute_hash(msg_context, spec, hash): + """ + subroutine of compute_md5() + + :param msg_context: :class:`MsgContext` instance to load dependencies into/from. + :param spec: :class:`MsgSpec` to compute hash for. + :param hash: hash instance + """ + # accumulate the hash + # - root file + if isinstance(spec, MsgSpec): + hash.update(compute_md5_text(msg_context, spec).encode()) + elif isinstance(spec, SrvSpec): + hash.update(compute_md5_text(msg_context, spec.request).encode()) + hash.update(compute_md5_text(msg_context, spec.response).encode()) + else: + raise Exception("[%s] is not a message or service"%spec) + return hash.hexdigest() + +def compute_md5(msg_context, spec): + """ + Compute md5 hash for message/service + + :param msg_context: :class:`MsgContext` instance to load dependencies into/from. + :param spec: :class:`MsgSpec` to compute md5 for. + :returns: md5 hash, ``str`` + """ + return _compute_hash(msg_context, spec, hashlib.md5()) + +## alias +compute_md5_v2 = compute_md5 + +def _unique_deps(dep_list): + uniques = [] + for d in dep_list: + if d not in uniques: + uniques.append(d) + return uniques + +def compute_full_text(msg_context, spec): + """ + Compute full text of message/service, including text of embedded + types. The text of the main msg/srv is listed first. Embedded + msg/srv files are denoted first by an 80-character '=' separator, + followed by a type declaration line,'MSG: pkg/type', followed by + the text of the embedded type. + + :param msg_context: :class:`MsgContext` instance to load dependencies into/from. + :param spec: :class:`MsgSpec` to compute full text for. + :returns: concatenated text for msg/srv file and embedded msg/srv types, ``str`` + """ + buff = StringIO() + sep = '='*80+'\n' + + # write the text of the top-level type + buff.write(spec.text) + buff.write('\n') + # append the text of the dependencies (embedded types). Can't use set() as we have to preserve order. + for d in _unique_deps(msg_context.get_all_depends(spec.full_name)): + buff.write(sep) + buff.write("MSG: %s\n"%d) + buff.write(msg_context.get_registered(d).text) + buff.write('\n') + # #1168: remove the trailing \n separator that is added by the concatenation logic + return buff.getvalue()[:-1] + +def compute_full_type_name(package_name, file_name): + """ + Compute the full type name of message/service 'pkg/type'. + + :param package_name: name of package file is in, ``str`` + :file_name: name of the msg or srv file, ``str`` + :returns: typename in format 'pkg/type' + :raises: :exc:`MsgGenerationException` if file_name ends with an unknown file extension + """ + # strip extension + for ext in (base.EXT_MSG, base.EXT_SRV): + if file_name.endswith(ext): + short_name = file_name[:-len(ext)] + break + else: + raise base.MsgGenerationException("Processing file: '%s' - unknown file extension"% (file_name)) + return "%s/%s"%(package_name, short_name) + diff --git a/tiny_tf/genmsg/msg_loader.py b/tiny_tf/genmsg/msg_loader.py new file mode 100644 index 0000000..7425fbf --- /dev/null +++ b/tiny_tf/genmsg/msg_loader.py @@ -0,0 +1,489 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +""" +Loader for messages and :class:`MsgContext` that assumes a +dictionary-based search path scheme (keys are the package/namespace, +values are the paths). Compatible with ROS package system and other +possible layouts. +""" + +import ast +import os +import sys + +try: + from cStringIO import StringIO # Python 2.x +except ImportError: + from io import StringIO # Python 3.x + +from . base import InvalidMsgSpec, log, SEP, COMMENTCHAR, CONSTCHAR, IODELIM, EXT_MSG, EXT_SRV +from . msgs import MsgSpec, TIME, TIME_MSG, DURATION, DURATION_MSG, HEADER, HEADER_FULL_NAME, \ + is_builtin, is_valid_msg_field_name, is_valid_msg_type, bare_msg_type, is_valid_constant_type, \ + Field, Constant, resolve_type +from . names import normalize_package_context, package_resource_name +from . srvs import SrvSpec + +class MsgNotFound(Exception): + + def __init__(self, message, base_type=None, package=None, search_path=None): + super(MsgNotFound, self).__init__(message) + self.base_type = base_type + self.package = package + self.search_path = search_path + +def get_msg_file(package, base_type, search_path, ext=EXT_MSG): + """ + Determine the file system path for the specified ``.msg`` on + *search_path*. + + :param package: name of package file is in, ``str`` + :param base_type: type name of message, e.g. 'Point2DFloat32', ``str`` + :param search_path: dictionary mapping message namespaces to a directory locations + :param ext: msg file extension. Override with EXT_SRV to search for services instead. + + :returns: filesystem path of requested file, ``str`` + :raises: :exc:`MsgNotFound` If message cannot be located. + """ + log("msg_file(%s, %s, %s)" % (package, base_type, str(search_path))) + if not isinstance(search_path, dict): + raise ValueError("search_path must be a dictionary of {namespace: dirpath}") + if not package in search_path: + raise MsgNotFound("Cannot locate message [%s]: unknown package [%s] on search path [%s]" \ + % (base_type, package, search_path), base_type, package, search_path) + else: + for path_tmp in search_path[package]: + path = os.path.join(path_tmp, "%s%s"%(base_type, ext)) + if os.path.isfile(path): + return path + raise MsgNotFound("Cannot locate message [%s] in package [%s] with paths [%s]"% + (base_type, package, str(search_path[package])), base_type, package, search_path) + +def get_srv_file(package, base_type, search_path): + """ + Determine the file system path for the specified .srv on path. + + :param package: name of package ``.srv`` file is in, ``str`` + :param base_type: type name of service, e.g. 'Empty', ``str`` + :param search_path: dictionary mapping message namespaces to a directory locations + + :returns: file path of ``.srv`` file in specified package, ``str`` + :raises: :exc:`MsgNotFound` If service file cannot be located. + """ + return get_msg_file(package, base_type, search_path, ext=EXT_SRV) + +def load_msg_by_type(msg_context, msg_type, search_path): + """ + Load message specification for specified type. + + NOTE: this will register the message in the *msg_context*. + + :param msg_context: :class:`MsgContext` for finding loaded dependencies + :param msg_type: relative or full message type. + :param search_path: dictionary mapping message namespaces to a directory locations + + :returns: :class:`MsgSpec` instance, ``(str, MsgSpec)`` + :raises: :exc:`MsgNotFound` If message cannot be located. + """ + log("load_msg_by_type(%s, %s)" % (msg_type, str(search_path))) + if not isinstance(search_path, dict): + raise ValueError("search_path must be a dictionary of {namespace: dirpath}") + if msg_type == HEADER: + msg_type = HEADER_FULL_NAME + package_name, base_type = package_resource_name(msg_type) + file_path = get_msg_file(package_name, base_type, search_path) + log("file_path", file_path) + + spec = load_msg_from_file(msg_context, file_path, msg_type) + msg_context.set_file(msg_type, file_path) + return spec + +def load_srv_by_type(msg_context, srv_type, search_path): + """ + Load service specification for specified type. + + NOTE: services are *never* registered in a :class:`MsgContext`. + + :param msg_context: :class:`MsgContext` for finding loaded dependencies + :param srv_type: relative or full message type. + :param search_path: dictionary mapping message namespaces to a directory locations + + :returns: :class:`MsgSpec` instance, ``(str, MsgSpec)`` + :raises: :exc:`MsgNotFound` If message cannot be located. + """ + log("load_srv_by_type(%s, %s)" % (srv_type, str(search_path))) + if not isinstance(search_path, dict): + raise ValueError("search_path must be a dictionary of {namespace: dirpath}") + package_name, base_type = package_resource_name(srv_type) + file_path = get_srv_file(package_name, base_type, search_path) + log("file_path", file_path) + return load_srv_from_file(msg_context, file_path, srv_type) + +def convert_constant_value(field_type, val): + """ + Convert constant value declaration to python value. Does not do + type-checking, so ValueError or other exceptions may be raised. + + :param field_type: ROS field type, ``str`` + :param val: string representation of constant, ``str`` + :raises: :exc:`ValueError` If unable to convert to python representation + :raises: :exc:`InvalidMsgSpec` If value exceeds specified integer width + """ + if field_type in ['float32','float64']: + return float(val) + elif field_type in ['string']: + return val.strip() #string constants are always stripped + elif field_type in ['int8', 'uint8', 'int16','uint16','int32','uint32','int64','uint64', 'char', 'byte']: + # bounds checking + bits = [('int8', 8), ('uint8', 8), ('int16', 16),('uint16', 16),\ + ('int32', 32),('uint32', 32), ('int64', 64),('uint64', 64),\ + ('byte', 8), ('char', 8)] + b = [b for t, b in bits if t == field_type][0] + import math + if field_type[0] == 'u' or field_type == 'char': + lower = 0 + upper = int(math.pow(2, b)-1) + else: + upper = int(math.pow(2, b-1)-1) + lower = -upper - 1 #two's complement min + val = int(val) #python will autocast to long if necessary + if val > upper or val < lower: + raise InvalidMsgSpec("cannot coerce [%s] to %s (out of bounds)"%(val, field_type)) + return val + elif field_type == 'bool': + return True if ast.literal_eval(val) else False + raise InvalidMsgSpec("invalid constant type: [%s]"%field_type) + +def _load_constant_line(orig_line): + """ + :raises: :exc:`InvalidMsgSpec` + """ + clean_line = _strip_comments(orig_line) + line_splits = [s for s in [x.strip() for x in clean_line.split(" ")] if s] #split type/name, filter out empties + field_type = line_splits[0] + if not is_valid_constant_type(field_type): + raise InvalidMsgSpec("%s is not a legal constant type"%field_type) + + if field_type == 'string': + # strings contain anything to the right of the equals sign, there are no comments allowed + idx = orig_line.find(CONSTCHAR) + name = orig_line[orig_line.find(' ')+1:idx] + val = orig_line[idx+1:] + else: + line_splits = [x.strip() for x in ' '.join(line_splits[1:]).split(CONSTCHAR)] #resplit on '=' + if len(line_splits) != 2: + raise InvalidMsgSpec("Invalid constant declaration: %s"%orig_line) + name = line_splits[0] + val = line_splits[1] + + try: + val_converted = convert_constant_value(field_type, val) + except Exception as e: + raise InvalidMsgSpec("Invalid constant value: %s"%e) + return Constant(field_type, name, val_converted, val.strip()) + +def _load_field_line(orig_line, package_context): + """ + :returns: (field_type, name) tuple, ``(str, str)`` + :raises: :exc:`InvalidMsgSpec` + """ + #log("_load_field_line", orig_line, package_context) + clean_line = _strip_comments(orig_line) + line_splits = [s for s in [x.strip() for x in clean_line.split(" ")] if s] #split type/name, filter out empties + if len(line_splits) != 2: + raise InvalidMsgSpec("Invalid declaration: %s"%(orig_line)) + field_type, name = line_splits + if not is_valid_msg_field_name(name): + raise InvalidMsgSpec("%s is not a legal message field name"%name) + if not is_valid_msg_type(field_type): + raise InvalidMsgSpec("%s is not a legal message field type"%field_type) + if package_context and not SEP in field_type: + if field_type == HEADER: + field_type = HEADER_FULL_NAME + elif not is_builtin(bare_msg_type(field_type)): + field_type = "%s/%s"%(package_context, field_type) + elif field_type == HEADER: + field_type = HEADER_FULL_NAME + return field_type, name + +def _strip_comments(line): + return line.split(COMMENTCHAR)[0].strip() #strip comments + +def load_msg_from_string(msg_context, text, full_name): + """ + Load message specification from a string. + + NOTE: this will register the message in the *msg_context*. + + :param msg_context: :class:`MsgContext` for finding loaded dependencies + :param text: .msg text , ``str`` + :returns: :class:`MsgSpec` specification + :raises: :exc:`InvalidMsgSpec` If syntax errors or other problems are detected in file + """ + log("load_msg_from_string", full_name) + package_name, short_name = package_resource_name(full_name) + types = [] + names = [] + constants = [] + for orig_line in text.split('\n'): + clean_line = _strip_comments(orig_line) + if not clean_line: + continue #ignore empty lines + if CONSTCHAR in clean_line: + constants.append(_load_constant_line(orig_line)) + else: + field_type, name = _load_field_line(orig_line, package_name) + types.append(field_type) + names.append(name) + spec = MsgSpec(types, names, constants, text, full_name, package_name) + msg_context.register(full_name, spec) + return spec + +def load_msg_from_file(msg_context, file_path, full_name): + """ + Convert the .msg representation in the file to a :class:`MsgSpec` instance. + + NOTE: this will register the message in the *msg_context*. + + :param file_path: path of file to load from, ``str`` + :returns: :class:`MsgSpec` instance + :raises: :exc:`InvalidMsgSpec`: if syntax errors or other problems are detected in file + """ + log("Load spec from", file_path) + with open(file_path, 'r') as f: + text = f.read() + try: + return load_msg_from_string(msg_context, text, full_name) + except InvalidMsgSpec as e: + raise InvalidMsgSpec('%s: %s'%(file_path, e)) + +def load_msg_depends(msg_context, spec, search_path): + """ + Add the list of message types that spec depends on to depends. + + :param msg_context: :class:`MsgContext` instance to load dependencies into/from. + :param spec: message to compute dependencies for, :class:`MsgSpec`/:class:`SrvSpec` + :param search_path: dictionary mapping message namespaces to a directory locations + :param deps: for recursion use only, do not set + + :returns: list of dependency names, ``[str]`` + :raises: :exc:`MsgNotFound` If dependency cannot be located. + """ + package_context = spec.package + log("load_msg_depends ", spec.full_name, package_context) + depends = [] + # Iterate over each field, loading as necessary + for unresolved_type in spec.types: + bare_type = bare_msg_type(unresolved_type) + resolved_type = resolve_type(bare_type, package_context) + if is_builtin(resolved_type): + continue + + # Retrieve the MsgSpec instance of the field + if msg_context.is_registered(resolved_type): + depspec = msg_context.get_registered(resolved_type) + else: + # load and register on demand + depspec = load_msg_by_type(msg_context, resolved_type, search_path) + msg_context.register(resolved_type, depspec) + + # Update dependencies + depends.append(resolved_type) + # - check to see if we have compute dependencies of field + dep_dependencies = msg_context.get_depends(resolved_type) + if dep_dependencies is None: + load_msg_depends(msg_context, depspec, search_path) + + assert spec.full_name, "MsgSpec must have a properly set full name" + msg_context.set_depends(spec.full_name, depends) + # have to copy array in order to prevent inadvertent mutation (we've stored this list in set_dependencies) + return depends[:] + +def load_depends(msg_context, spec, msg_search_path): + """ + Compute dependencies of *spec* and load their MsgSpec dependencies + into *msg_context*. + + NOTE: *msg_search_path* is only for finding .msg files. ``.srv`` + files have a separate and distinct search path. As services + cannot depend on other services, it is not necessary to provide + the srv search path here. + + :param msg_context: :class:`MsgContext` instance to load dependencies into/from. + :param spec: :class:`MsgSpec` or :class:`SrvSpec` instance to load dependencies for. + :param msg_search_path: dictionary mapping message namespaces to a directory locations. + :raises: :exc:`MsgNotFound` If dependency cannot be located. + """ + if isinstance(spec, MsgSpec): + return load_msg_depends(msg_context, spec, msg_search_path) + elif isinstance(spec, SrvSpec): + depends = load_msg_depends(msg_context, spec.request, msg_search_path) + depends.extend(load_msg_depends(msg_context, spec.response, msg_search_path)) + return depends + else: + raise ValueError("spec does not appear to be a message or service") + +class MsgContext(object): + """ + Context object for storing :class:`MsgSpec` instances and related + metadata. + + NOTE: All APIs work on :class:`MsgSpec` instance information. + Thus, for services, there is information for the request and + response messages, but there is no direct information about the + :class:`SrvSpec` instance. + """ + + def __init__(self): + self._registered_packages = {} + self._files = {} + self._dependencies = {} + + def set_file(self, full_msg_type, file_path): + self._files[full_msg_type] = file_path + + def get_file(self, full_msg_type): + return self._files.get(full_msg_type, None) + + def set_depends(self, full_msg_type, dependencies): + """ + :param dependencies: direct first order + dependencies for *full_msg_type* + """ + log("set_depends", full_msg_type, dependencies) + self._dependencies[full_msg_type] = dependencies + + def get_depends(self, full_msg_type): + """ + :returns: List of dependencies for *full_msg_type*, + only first order dependencies + """ + return self._dependencies.get(full_msg_type, None) + + def get_all_depends(self, full_msg_type): + all_deps = [] + depends = self.get_depends(full_msg_type) + if depends is None: + raise KeyError(full_msg_type) + for d in depends: + all_deps.extend([d]) + all_deps.extend(self.get_all_depends(d)) + return all_deps + + @staticmethod + def create_default(): + msg_context = MsgContext() + # register builtins (needed for serialization). builtins have no package. + load_msg_from_string(msg_context, TIME_MSG, TIME) + load_msg_from_string(msg_context, DURATION_MSG, DURATION) + return msg_context + + def register(self, full_msg_type, msgspec): + full_msg_type = bare_msg_type(full_msg_type) + package, base_type = package_resource_name(full_msg_type) + if package not in self._registered_packages: + self._registered_packages[package] = {} + self._registered_packages[package][base_type] = msgspec + + def is_registered(self, full_msg_type): + """ + :param full_msg_type: Fully resolve message type + :param default_package: default package namespace to resolve + in. May be ignored by special types (e.g. time/duration). + + :returns: ``True`` if :class:`MsgSpec` instance has been loaded for the requested type. + """ + full_msg_type = bare_msg_type(full_msg_type) + package, base_type = package_resource_name(full_msg_type) + if package in self._registered_packages: + return base_type in self._registered_packages[package] + else: + return False + + def get_registered(self, full_msg_type): + """ + :raises: :exc:`KeyError` If not registered + """ + full_msg_type = bare_msg_type(full_msg_type) + if self.is_registered(full_msg_type): + package, base_type = package_resource_name(full_msg_type) + return self._registered_packages[package][base_type] + else: + raise KeyError(full_msg_type) + + def __str__(self): + return str(self._registered_packages) + +def load_srv_from_string(msg_context, text, full_name): + """ + Load :class:`SrvSpec` from the .srv file. + + :param msg_context: :class:`MsgContext` instance to load request/response messages into. + :param text: .msg text , ``str`` + :param package_name: context to use for msg type name, i.e. the package name, + or '' to use local naming convention. ``str`` + :returns: :class:`SrvSpec` instance + :raises :exc:`InvalidMsgSpec` If syntax errors or other problems are detected in file + """ + text_in = StringIO() + text_out = StringIO() + accum = text_in + for l in text.split('\n'): + l = l.split(COMMENTCHAR)[0].strip() #strip comments + if l.startswith(IODELIM): #lenient, by request + accum = text_out + else: + accum.write(l+'\n') + + # create separate MsgSpec objects for each half of file + msg_in = load_msg_from_string(msg_context, text_in.getvalue(), '%sRequest'%(full_name)) + msg_out = load_msg_from_string(msg_context, text_out.getvalue(), '%sResponse'%(full_name)) + return SrvSpec(msg_in, msg_out, text, full_name) + +def load_srv_from_file(msg_context, file_path, full_name): + """ + Convert the .srv representation in the file to a :class:`SrvSpec` instance. + + :param msg_context: :class:`MsgContext` instance to load request/response messages into. + :param file_name: name of file to load from, ``str`` + :returns: :class:`SrvSpec` instance + :raise: :exc:`InvalidMsgSpec` If syntax errors or other problems are detected in file + """ + log("Load spec from %s %s\n"%(file_path, full_name)) + with open(file_path, 'r') as f: + text = f.read() + spec = load_srv_from_string(msg_context, text, full_name) + msg_context.set_file('%sRequest'%(full_name), file_path) + msg_context.set_file('%sResponse'%(full_name), file_path) + return spec diff --git a/tiny_tf/genmsg/msgs.py b/tiny_tf/genmsg/msgs.py new file mode 100644 index 0000000..1468aa0 --- /dev/null +++ b/tiny_tf/genmsg/msgs.py @@ -0,0 +1,349 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +""" +ROS msg library for Python + +Implements: U{http://ros.org/wiki/msg} +""" + +import os +import sys + +from . base import InvalidMsgSpec, EXT_MSG, MSG_DIR, SEP, log +from . names import is_legal_resource_name, is_legal_resource_base_name, package_resource_name, resource_name + +#TODOXXX: unit test +def bare_msg_type(msg_type): + """ + Compute the bare data type, e.g. for arrays, get the underlying array item type + + :param msg_type: ROS msg type (e.g. 'std_msgs/String'), ``str`` + :returns: base type, ``str`` + """ + if msg_type is None: + return None + if '[' in msg_type: + return msg_type[:msg_type.find('[')] + return msg_type + +def resolve_type(msg_type, package_context): + """ + Resolve type name based on current package context. + + NOTE: in ROS Diamondback, 'Header' resolves to + 'std_msgs/Header'. In previous releases, it resolves to + 'roslib/Header' (REP 100). + + e.g.:: + resolve_type('String', 'std_msgs') -> 'std_msgs/String' + resolve_type('String[]', 'std_msgs') -> 'std_msgs/String[]' + resolve_type('std_msgs/String', 'foo') -> 'std_msgs/String' + resolve_type('uint16', 'std_msgs') -> 'uint16' + resolve_type('uint16[]', 'std_msgs') -> 'uint16[]' + """ + bt = bare_msg_type(msg_type) + if bt in BUILTIN_TYPES: + return msg_type + elif bt == HEADER: + return HEADER_FULL_NAME + elif SEP in msg_type: + return msg_type + else: + return "%s%s%s"%(package_context, SEP, msg_type) + +#NOTE: this assumes that we aren't going to support multi-dimensional + +def parse_type(msg_type): + """ + Parse ROS message field type + :param msg_type: ROS field type, ``str`` + :returns: base_type, is_array, array_length, ``(str, bool, int)`` + :raises: :exc:`ValueError` If *msg_type* cannot be parsed + """ + if not msg_type: + raise ValueError("Invalid empty type") + if '[' in msg_type: + var_length = msg_type.endswith('[]') + splits = msg_type.split('[') + if len(splits) > 2: + raise ValueError("Currently only support 1-dimensional array types: %s"%msg_type) + if var_length: + return msg_type[:-2], True, None + else: + try: + length = int(splits[1][:-1]) + return splits[0], True, length + except ValueError: + raise ValueError("Invalid array dimension: [%s]"%splits[1][:-1]) + else: + return msg_type, False, None + +################################################################################ +# name validation + +def is_valid_msg_type(x): + """ + :returns: True if the name is a syntatically legal message type name, ``bool`` + """ + if not x or len(x) != len(x.strip()): + return False + base = bare_msg_type(x) + if not is_legal_resource_name(base): + return False + #parse array indicies + x = x[len(base):] + state = 0 + i = 0 + for c in x: + if state == 0: + if c != '[': + return False + state = 1 #open + elif state == 1: + if c == ']': + state = 0 #closed + else: + try: + int(c) + except: + return False + return state == 0 + +def is_valid_constant_type(x): + """ + :returns: ``True`` if the name is a legal constant type. Only simple types are allowed, ``bool`` + """ + return x in PRIMITIVE_TYPES + +def is_valid_msg_field_name(x): + """ + :returns: ``True`` if the name is a syntatically legal message field name, ``bool`` + """ + return is_legal_resource_base_name(x) + +# msg spec representation ########################################## + +class Constant(object): + """ + Container class for holding a Constant declaration + + Attributes: + + - ``type`` + - ``name`` + - ``val`` + - ``val_text`` + """ + __slots__ = ['type', 'name', 'val', 'val_text'] + + def __init__(self, type_, name, val, val_text): + """ + :param type_: constant type, ``str`` + :param name: constant name, ``str`` + :param val: constant value, ``str`` + :param val_text: Original text definition of *val*, ``str`` + """ + if type is None or name is None or val is None or val_text is None: + raise ValueError('Constant must have non-None parameters') + self.type = type_ + self.name = name.strip() #names are always stripped of whitespace + self.val = val + self.val_text = val_text + + def __eq__(self, other): + if not isinstance(other, Constant): + return False + return self.type == other.type and self.name == other.name and self.val == other.val + + def __repr__(self): + return "%s %s=%s"%(self.type, self.name, self.val) + + def __str__(self): + return "%s %s=%s"%(self.type, self.name, self.val) + +class Field(object): + """ + Container class for storing information about a single field in a MsgSpec + + Attributes: + + - ``name`` + - ``type`` + - ``base_type`` + - ``is_array`` + - ``array_len`` + - ``is_builtin`` + - ``is_header`` + """ + + def __init__(self, name, type): + self.name = name + self.type = type + (self.base_type, self.is_array, self.array_len) = parse_type(type) + self.is_header = is_header_type(self.type) + self.is_builtin = is_builtin(self.base_type) + + def __eq__(self, other): + if not isinstance(other, Field): + return False + else: + return self.name == other.name and \ + self.type == other.type + + def __repr__(self): + return "[%s, %s, %s, %s, %s]"%(self.name, self.type, self.base_type, self.is_array, self.array_len) + +class MsgSpec(object): + """ + Container class for storing loaded msg description files. Field + types and names are stored in separate lists with 1-to-1 + correspondence. MsgSpec can also return an md5 of the source text. + """ + + def __init__(self, types, names, constants, text, full_name, package = '', short_name = ''): + """ + :param types: list of field types, in order of declaration, ``[str]`` + :param names: list of field names, in order of declaration, ``[str]`` + :param constants: List of :class:`Constant` declarations, ``[Constant]`` + :param text: text of declaration, ``str`` + :raises: :exc:`InvalidMsgSpec` If spec is invalid (e.g. fields with the same name) + """ + alt_package, alt_short_name = package_resource_name(full_name) + if not package: + package = alt_package + if not short_name: + short_name = alt_short_name + + self.types = types + if len(set(names)) != len(names): + raise InvalidMsgSpec("Duplicate field names in message: %s"%names) + self.names = names + self.constants = constants + assert len(self.types) == len(self.names), "len(%s) != len(%s)"%(self.types, self.names) + #Header.msg support + if (len(self.types)): + self.header_present = self.types[0] == HEADER_FULL_NAME and self.names[0] == 'header' + else: + self.header_present = False + self.text = text + self.full_name = full_name + self.short_name = short_name + self.package = package + try: + self._parsed_fields = [Field(name, type) for (name, type) in zip(self.names, self.types)] + except ValueError as e: + raise InvalidMsgSpec("invalid field: %s"%(e)) + + def fields(self): + """ + :returns: zip list of types and names (e.g. [('int32', 'x'), ('int32', 'y')], ``[(str,str),]`` + """ + return list(zip(self.types, self.names)) #py3k + + def parsed_fields(self): + """ + :returns: list of :class:`Field` classes, ``[Field,]`` + """ + return self._parsed_fields + + def has_header(self): + """ + :returns: ``True`` if msg decription contains a 'Header header' + declaration at the beginning, ``bool`` + """ + return self.header_present + + def __eq__(self, other): + if not other or not isinstance(other, MsgSpec): + return False + return self.types == other.types and self.names == other.names and \ + self.constants == other.constants and self.text == other.text and \ + self.full_name == other.full_name and self.short_name == other.short_name and \ + self.package == other.package + + def __ne__(self, other): + if not other or not isinstance(other, MsgSpec): + return True + return not self.__eq__(other) + + def __repr__(self): + if self.constants: + return "MsgSpec[%s, %s, %s]"%(repr(self.constants), repr(self.types), repr(self.names)) + else: + return "MsgSpec[%s, %s]"%(repr(self.types), repr(self.names)) + + def __str__(self): + return self.text + +# .msg file routines ############################################################## + +# adjustable constants, in case we change our minds +HEADER = 'Header' +TIME = 'time' +DURATION = 'duration' +HEADER_FULL_NAME = 'std_msgs/Header' + +def is_header_type(msg_type): + """ + :param msg_type: message type name, ``str`` + :returns: ``True`` if *msg_type* refers to the ROS Header type, ``bool`` + """ + # for backwards compatibility, include roslib/Header. REP 100 + return msg_type in [HEADER, HEADER_FULL_NAME, 'roslib/Header'] + +# time and duration types are represented as aggregate data structures +# for the purposes of serialization from the perspective of +# roslib.msgs. genmsg_py will do additional special handling is required +# to convert them into rospy.msg.Time/Duration instances. + +## time as msg spec. time is unsigned +TIME_MSG = "uint32 secs\nuint32 nsecs" +## duration as msg spec. duration is just like time except signed +DURATION_MSG = "int32 secs\nint32 nsecs" + +## primitive types are those for which we allow constants, i.e. have primitive representation +PRIMITIVE_TYPES = ['int8','uint8','int16','uint16','int32','uint32','int64','uint64','float32','float64', + 'string', + 'bool', + # deprecated: + 'char','byte'] +BUILTIN_TYPES = PRIMITIVE_TYPES + [TIME, DURATION] + +def is_builtin(msg_type_name): + """ + :param msg_type_name: name of message type, ``str`` + :returns: True if msg_type_name is a builtin/primitive type, ``bool`` + """ + return msg_type_name in BUILTIN_TYPES diff --git a/tiny_tf/genmsg/names.py b/tiny_tf/genmsg/names.py new file mode 100644 index 0000000..c0f3ef5 --- /dev/null +++ b/tiny_tf/genmsg/names.py @@ -0,0 +1,145 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +PRN_SEPARATOR = '/' + +import re + +def normalize_package_context(package_context): + package_context = package_context.strip() + while package_context.endswith(PRN_SEPARATOR): + package_context = package_context[:-1] + return package_context + +####################################################################### +# RESOURCE NAMES +# resource names refer to entities in a file system + +def resource_name(res_pkg_name, name, my_pkg=None): + """ + Convert package name + resource into a fully qualified resource name + + @param res_pkg_name: name of package resource is located in + @type res_pkg_name: str + @param name: resource base name + @type name: str + @param my_pkg: name of package resource is being referred to + in. If specified, name will be returned in local form if + res_pkg_name is my_pkg + @type my_pkg: str + @return: name for resource + @rtype: str + """ + if res_pkg_name != my_pkg: + return res_pkg_name+PRN_SEPARATOR+name + return name + +def resource_name_base(name): + """ + pkg/typeName -> typeName, typeName -> typeName + + Convert fully qualified resource name into the package-less resource name + @param name: package resource name, e.g. 'std_msgs/String' + @type name: str + @return: resource name sans package-name scope + @rtype: str + """ + + return name[name.rfind(PRN_SEPARATOR)+1:] + +def resource_name_package(name): + """ + pkg/typeName -> pkg, typeName -> None + + @param name: package resource name, e.g. 'std_msgs/String' + @type name: str + @return: package name of resource + @rtype: str + """ + + if not PRN_SEPARATOR in name: + return None + return name[:name.find(PRN_SEPARATOR)] + +def package_resource_name(name): + """ + Split a name into its package and resource name parts, e.g. 'std_msgs/String -> std_msgs, String' + + @param name: package resource name, e.g. 'std_msgs/String' + @type name: str + @return: package name, resource name + @rtype: str + @raise ValueError: if name is invalid + """ + if PRN_SEPARATOR in name: + val = tuple(name.split(PRN_SEPARATOR)) + if len(val) != 2: + raise ValueError("invalid name [%s]"%name) + else: + return val + else: + return '', name + +################################################################################ +# NAME VALIDATORS + +#ascii char followed by (alphanumeric, _, /) +RESOURCE_NAME_LEGAL_CHARS_P = re.compile('^[A-Za-z][\w_\/]*$') +def is_legal_resource_name(name): + """ + Check if name is a legal ROS name for filesystem resources + (alphabetical character followed by alphanumeric, underscore, or + forward slashes). This constraint is currently not being enforced, + but may start getting enforced in later versions of ROS. + + @param name: Name + @type name: str + """ + # resource names can be unicode due to filesystem + if name is None: + return False + m = RESOURCE_NAME_LEGAL_CHARS_P.match(name) + # '//' check makes sure there isn't double-slashes + return m is not None and m.group(0) == name and not '//' in name + +BASE_RESOURCE_NAME_LEGAL_CHARS_P = re.compile('^[A-Za-z][\w_]*$') #ascii char followed by (alphanumeric, _) +def is_legal_resource_base_name(name): + """ + Validates that name is a legal resource base name. A base name has + no package context, e.g. "String". + """ + # resource names can be unicode due to filesystem + if name is None: + return False + m = BASE_RESOURCE_NAME_LEGAL_CHARS_P.match(name) + return m is not None and m.group(0) == name + diff --git a/tiny_tf/genmsg/srvs.py b/tiny_tf/genmsg/srvs.py new file mode 100644 index 0000000..faaaddf --- /dev/null +++ b/tiny_tf/genmsg/srvs.py @@ -0,0 +1,78 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +ROS Service Description Language Spec +Implements http://ros.org/wiki/srv +""" + +import os +import sys + +from . names import is_legal_resource_name, is_legal_resource_base_name, package_resource_name, resource_name + +class SrvSpec(object): + + def __init__(self, request, response, text, full_name = '', short_name = '', package = ''): + + alt_package, alt_short_name = package_resource_name(full_name) + if not package: + package = alt_package + if not short_name: + short_name = alt_short_name + + self.request = request + self.response = response + self.text = text + self.full_name = full_name + self.short_name = short_name + self.package = package + + + def __eq__(self, other): + if not other or not isinstance(other, SrvSpec): + return False + return self.request == other.request and \ + self.response == other.response and \ + self.text == other.text and \ + self.full_name == other.full_name and \ + self.short_name == other.short_name and \ + self.package == other.package + + def __ne__(self, other): + if not other or not isinstance(other, SrvSpec): + return True + return not self.__eq__(other) + + def __repr__(self): + return "SrvSpec[%s, %s]"%(repr(self.request), repr(self.response)) + diff --git a/tiny_tf/genmsg/template_tools.py b/tiny_tf/genmsg/template_tools.py new file mode 100644 index 0000000..8f1e9c4 --- /dev/null +++ b/tiny_tf/genmsg/template_tools.py @@ -0,0 +1,217 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +## ROS Message generatation +## +## + +import sys +import os +import em +import errno +import genmsg.command_line +import genmsg.msgs +import genmsg.msg_loader +import genmsg.gentools + +# generate msg or srv files from a template file +# template_map of the form { 'template_file':'output_file'} output_file can contain @NAME@ which will be replaced by the message/service name +def _generate_from_spec(input_file, output_dir, template_dir, msg_context, spec, template_map, search_path): + + md5sum = genmsg.gentools.compute_md5(msg_context, spec) + + # precompute msg definition once + if isinstance(spec, genmsg.msgs.MsgSpec): + msg_definition = genmsg.gentools.compute_full_text(msg_context, spec) + + # Loop over all files to generate + for template_file_name, output_file_name in template_map.items(): + template_file = os.path.join(template_dir, template_file_name) + output_file = os.path.join(output_dir, output_file_name.replace("@NAME@", spec.short_name)) + + #print "generate_from_template %s %s %s" % (input_file, template_file, output_file) + + ofile = open(output_file, 'w') #todo try + + # Set dictionary for the generator interpreter + g = { + "file_name_in": input_file, + "spec": spec, + "md5sum": md5sum, + "search_path": search_path, + "msg_context": msg_context + } + if isinstance(spec, genmsg.msgs.MsgSpec): + g['msg_definition'] = msg_definition + + # todo, reuse interpreter + interpreter = em.Interpreter(output=ofile, globals=g, options={em.RAW_OPT:True,em.BUFFERED_OPT:True}) + if not os.path.isfile(template_file): + ofile.close() + os.remove(output_file) + raise RuntimeError("Template file %s not found in template dir %s" % (template_file_name, template_dir)) + interpreter.file(open(template_file)) #todo try + interpreter.shutdown() + +def _generate_msg_from_file(input_file, output_dir, template_dir, search_path, package_name, msg_template_dict): + # Read MsgSpec from .msg file + msg_context = genmsg.msg_loader.MsgContext.create_default() + full_type_name = genmsg.gentools.compute_full_type_name(package_name, os.path.basename(input_file)) + spec = genmsg.msg_loader.load_msg_from_file(msg_context, input_file, full_type_name) + # Load the dependencies + genmsg.msg_loader.load_depends(msg_context, spec, search_path) + # Generate the language dependent msg file + _generate_from_spec(input_file, + output_dir, + template_dir, + msg_context, + spec, + msg_template_dict, + search_path) + +def _generate_srv_from_file(input_file, output_dir, template_dir, search_path, package_name, srv_template_dict, msg_template_dict): + # Read MsgSpec from .srv.file + msg_context = genmsg.msg_loader.MsgContext.create_default() + full_type_name = genmsg.gentools.compute_full_type_name(package_name, os.path.basename(input_file)) + spec = genmsg.msg_loader.load_srv_from_file(msg_context, input_file, full_type_name) + # Load the dependencies + genmsg.msg_loader.load_depends(msg_context, spec, search_path) + # Generate the language dependent srv file + _generate_from_spec(input_file, + output_dir, + template_dir, + msg_context, + spec, + srv_template_dict, + search_path) + # Generate the language dependent msg file for the srv request + _generate_from_spec(input_file, + output_dir, + template_dir, + msg_context, + spec.request, + msg_template_dict, + search_path) + # Generate the language dependent msg file for the srv response + _generate_from_spec(input_file, + output_dir, + template_dir, + msg_context, + spec.response, + msg_template_dict, + search_path) + +# uniform interface for genering either srv or msg files +def generate_from_file(input_file, package_name, output_dir, template_dir, include_path, msg_template_dict, srv_template_dict): + # Normalize paths + input_file = os.path.abspath(input_file) + output_dir = os.path.abspath(output_dir) + + # Create output dir + try: + os.makedirs(output_dir) + except OSError as e: + if e.errno != errno.EEXIST: # ignore file exists error + raise + + # Parse include path dictionary + if( include_path ): + search_path = genmsg.command_line.includepath_to_dict(include_path) + else: + search_path = {} + + # Generate the file(s) + if input_file.endswith(".msg"): + _generate_msg_from_file(input_file, output_dir, template_dir, search_path, package_name, msg_template_dict) + elif input_file.endswith(".srv"): + _generate_srv_from_file(input_file, output_dir, template_dir, search_path, package_name, srv_template_dict, msg_template_dict) + else: + assert False, "Uknown file extension for %s"%input_file + +def generate_module(package_name, output_dir, template_dir, template_dict): + # Locate generate msg files + files = os.listdir(output_dir) + + # Loop over all files to generate + for template_file_name, output_file_name in template_dict.items(): + template_file = os.path.join(template_dir, template_file_name) + output_file = os.path.join(output_dir, output_file_name) + + ofile = open(output_file, 'w') #todo try + + # Set dictionary for the generator intepreter + g = dict(files=files, + package=package_name) + + # todo, reuse interpreter + interpreter = em.Interpreter(output=ofile, options={em.RAW_OPT:True,em.BUFFERED_OPT:True}) + interpreter.updateGlobals(g) + if not os.path.isfile(template_file): + ofile.close() + os.remove(output_file) + raise RuntimeError("Template file %s not found in template dir %s" % (template_file_name, template_dir)) + interpreter.file(open(template_file)) #todo try + interpreter.shutdown() + +# Uniform interface to support the standard command line options +def generate_from_command_line_options(argv, msg_template_dict, srv_template_dict, module_template_dict = {}): + from optparse import OptionParser + parser = OptionParser("[options] ") + parser.add_option("-p", dest='package', + help="ros package the generated msg/srv files belongs to") + parser.add_option("-o", dest='outdir', + help="directory in which to place output files") + parser.add_option("-I", dest='includepath', + help="include path to search for messages", + action="append") + parser.add_option("-m", dest='module', + help="write the module file", + action='store_true', default=False) + parser.add_option("-e", dest='emdir', + help="directory containing template files", + default=sys.path[0]) + + (options, argv) = parser.parse_args(argv) + + if( not options.package or not options.outdir or not options.emdir): + parser.print_help() + exit(-1) + + if( options.module ): + generate_module(options.package, options.outdir, options.emdir, module_template_dict) + else: + if len(argv) > 1: + generate_from_file(argv[1], options.package, options.outdir, options.emdir, options.includepath, msg_template_dict, srv_template_dict) + else: + parser.print_help() + exit(-1) + diff --git a/tiny_tf/genpy/__init__.py b/tiny_tf/genpy/__init__.py new file mode 100644 index 0000000..b5d9079 --- /dev/null +++ b/tiny_tf/genpy/__init__.py @@ -0,0 +1,37 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from . rostime import Time, Duration, TVal +from . message import Message, SerializationError, DeserializationError, MessageException, struct_I + +__all__ = ['Time', 'Duration', 'TVal', + 'Message', 'SerializationError', 'DeserializationError', 'MessageException', 'struct_I'] diff --git a/tiny_tf/genpy/base.py b/tiny_tf/genpy/base.py new file mode 100644 index 0000000..46f54f9 --- /dev/null +++ b/tiny_tf/genpy/base.py @@ -0,0 +1,65 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +################################################################################ +# Primitive type handling for ROS builtin types + +SIMPLE_TYPES_DICT = { #see python module struct + 'int8': 'b', + 'uint8': 'B', + # Python 2.6 adds in '?' for C99 _Bool, which appears equivalent to an uint8, + # thus, we use uint8 + 'bool': 'B', + 'int16' : 'h', + 'uint16' : 'H', + 'int32' : 'i', + 'uint32' : 'I', + 'int64' : 'q', + 'uint64' : 'Q', + 'float32': 'f', + 'float64': 'd', + # deprecated + 'char' : 'B', #unsigned + 'byte' : 'b', #signed + } + +## Simple types are primitives with fixed-serialization length +SIMPLE_TYPES = list(SIMPLE_TYPES_DICT.keys()) #py3k + +def is_simple(type_): + """ + :returns: ``True`` if type is a 'simple' type, i.e. is of + fixed/known serialization length. This is effectively all primitive + types except for string, ``bool`` + """ + return type_ in SIMPLE_TYPES + diff --git a/tiny_tf/genpy/dynamic.py b/tiny_tf/genpy/dynamic.py new file mode 100644 index 0000000..fb3e9bb --- /dev/null +++ b/tiny_tf/genpy/dynamic.py @@ -0,0 +1,197 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +dynamic generation of deserializer +""" + +from __future__ import print_function + +try: + from cStringIO import StringIO # Python 2.x +except ImportError: + from io import StringIO # Python 3.x + +import atexit +import os +import re +import shutil +import sys +import tempfile + +import genmsg +import genmsg.msg_loader +from genmsg import MsgContext, MsgGenerationException + +from . generator import msg_generator + +def _generate_dynamic_specs(msg_context, specs, dep_msg): + """ + :param dep_msg: text of dependent .msg definition, ``str`` + :returns: type name, message spec, ``str, MsgSpec`` + :raises: MsgGenerationException If dep_msg is improperly formatted + """ + line1 = dep_msg.find('\n') + msg_line = dep_msg[:line1] + if not msg_line.startswith("MSG: "): + raise MsgGenerationException("invalid input to generate_dynamic: dependent type is missing 'MSG:' type declaration header") + dep_type = msg_line[5:].strip() + dep_pkg, dep_base_type = genmsg.package_resource_name(dep_type) + dep_spec = genmsg.msg_loader.load_msg_from_string(msg_context, dep_msg[line1+1:], dep_type) + return dep_type, dep_spec + +def _gen_dyn_name(pkg, base_type): + """ + Modify pkg/base_type name so that it can safely co-exist with + statically generated files. + + :returns: name to use for pkg/base_type for dynamically generated message class. + @rtype: str + """ + return "_%s__%s"%(pkg, base_type) + +def _gen_dyn_modify_references(py_text, current_type, types): + """ + Modify the generated code to rewrite names such that the code can + safely co-exist with messages of the same name. + + :param py_text: genmsg_py-generated Python source code, ``str`` + :returns: updated text, ``str`` + """ + for t in types: + pkg, base_type = genmsg.package_resource_name(t) + gen_name = _gen_dyn_name(pkg, base_type) + + # Several things we have to rewrite: + # - remove any import statements + py_text = py_text.replace("import %s.msg"%pkg, '') + # - rewrite any references to class + py_text = re.sub("(? 1: + new_pattern = new_pattern + str(count) + prev + else: + new_pattern = new_pattern + prev + prev = c + count = 1 + if count > 1: + new_pattern = new_pattern + str(count) + c + else: + new_pattern = new_pattern + prev + return new_pattern + +## :param expr str: string python expression that is evaluated for serialization +## :returns str: python call to write value returned by expr to serialization buffer +def serialize(expr): + return "buff.write(%s)"%expr + +# int32 is very common due to length serialization, so it is special cased +def int32_pack(var): + """ + :param var: variable name, ``str`` + :returns: struct packing code for an int32 + """ + return serialize('_struct_I.pack(%s)'%var) + +# int32 is very common due to length serialization, so it is special cased +def int32_unpack(var, buff): + """ + :param var: variable name, ``str`` + :returns: struct unpacking code for an int32 + """ + return '(%s,) = _struct_I.unpack(%s)'%(var, buff) + +#NOTE: '<' = little endian +def pack(pattern, vars): + """ + create struct.pack call for when pattern is a string pattern + :param pattern: pattern for pack, ``str`` + :param vars: name of variables to pack, ``str`` + """ + # - store pattern in context + pattern = reduce_pattern(pattern) + add_pattern(pattern) + return serialize("_get_struct_%s().pack(%s)"%(pattern, vars)) +def pack2(pattern, vars): + """ + create struct.pack call for when pattern is the name of a variable + :param pattern: name of variable storing string pattern, ``struct`` + :param vars: name of variables to pack, ``str`` + """ + return serialize("struct.pack(%s, %s)"%(pattern, vars)) + +def unpack(var, pattern, buff): + """ + create struct.unpack call for when pattern is a string pattern + :param var: name of variable to unpack, ``str`` + :param pattern: pattern for pack, ``str`` + :param buff: buffer to unpack from, ``str`` + """ + # - store pattern in context + pattern = reduce_pattern(pattern) + add_pattern(pattern) + return var + " = _get_struct_%s().unpack(%s)"%(pattern, buff) + +def unpack2(var, pattern, buff): + """ + Create struct.unpack call for when pattern refers to variable + :param var: variable the stores the result of unpack call, ``str`` + :param pattern: name of variable that unpack will read from, ``str`` + :param buff: buffer that the unpack reads from, ``StringIO`` + """ + return "%s = struct.unpack(%s, %s)"%(var, pattern, buff) + diff --git a/tiny_tf/genpy/generator.py b/tiny_tf/genpy/generator.py new file mode 100644 index 0000000..21ee0ad --- /dev/null +++ b/tiny_tf/genpy/generator.py @@ -0,0 +1,1014 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Library for Python message generation. + +The structure of the serialization descends several levels of serializers: + - msg_generator: generator for an individual msg file + - serialize_fn_generator: generator for msg.serialize() + - serializer_generator + - field-type-specific serializers + raise MsgGenerationException("unknown file extension: %s"%f) + + - deserialize_fn_generator: generator for msg.deserialize() + - serializer_generator + - field-type-specific serializers +""" + +from __future__ import print_function + +import errno +import os +import keyword +import itertools +import sys +import traceback +import struct + +import genmsg +import genmsg.msgs +import genmsg.msg_loader +import genmsg.gentools + +from genmsg import InvalidMsgSpec, MsgContext, MsgSpec, MsgGenerationException +from genmsg.base import log + +from . base import is_simple, SIMPLE_TYPES, SIMPLE_TYPES_DICT +from . generate_numpy import unpack_numpy, pack_numpy, NUMPY_DTYPE +from . generate_struct import reduce_pattern, serialize, \ + int32_pack, int32_unpack, pack, pack2, unpack, unpack2, compute_struct_pattern, \ + clear_patterns, add_pattern, get_patterns + +# indent width +INDENT = ' ' + +def get_registered_ex(msg_context, type_): + """ + wrapper for get_registered that wraps unknown types with a MsgGenerationException + :param type_: ROS message type, ``str`` + """ + try: + return msg_context.get_registered(type_) + except: + raise MsgGenerationException("Unknown type [%s]. Please check that the manifest.xml correctly declares dependencies."%type_) + +################################################################################ +# Special type handling for ROS builtin types that are not primitives + +class Special: + + def __init__(self, constructor, post_deserialize, import_str): + """ + :param constructor: expression to instantiate new type instance for deserialization, ``str`` + :param post_Deserialize: format string for expression to evaluate on type instance after deserialization is complete., ``str`` + variable name will be passed in as the single argument to format string. + :param import_str: import to include if type is present, ``str`` + """ + self.constructor = constructor + self.post_deserialize = post_deserialize + self.import_str = import_str + + def get_post_deserialize(self, varname): + """ + :returns: Post-deserialization code to executed (unindented) or + ``None`` if no post-deserialization is required, ``str`` + """ + if self.post_deserialize: + return self.post_deserialize%varname + else: + return None + +_SPECIAL_TYPES = { + genmsg.HEADER: Special('std_msgs.msg._Header.Header()', None, 'import std_msgs.msg'), + genmsg.TIME: Special('genpy.Time()', '%s.canon()', 'import genpy'), + genmsg.DURATION: Special('genpy.Duration()', '%s.canon()', 'import genpy'), + } + +def is_special(type_): + """ + :returns: ``True` if *type_* is a special type (i.e. builtin represented as a class instead of a primitive), ``bool`` + """ + return type_ in _SPECIAL_TYPES + +def get_special(type_): + """ + :returns: special type handler for *type_* or ``None``, ``Special`` + """ + return _SPECIAL_TYPES.get(type_, None) + +################################################################################ +# utilities + +# #671 +def default_value(msg_context, field_type, default_package): + """ + Compute default value for field_type + + :param default_package: default package, ``str`` + :param field_type: ROS .msg field type, ``str`` + :returns: default value encoded in Python string representation, ``str`` + """ + if field_type in ['byte', 'int8', 'int16', 'int32', 'int64',\ + 'char', 'uint8', 'uint16', 'uint32', 'uint64']: + return '0' + elif field_type in ['float32', 'float64']: + return '0.' + elif field_type == 'string': + return "''" + elif field_type == 'bool': + return 'False' + elif field_type.endswith(']'): # array type + base_type, is_array, array_len = genmsg.msgs.parse_type(field_type) + if base_type in ['char', 'uint8']: + # strings, char[], and uint8s are all optimized to be strings + if array_len is not None: + return r"b'\0'*%s"%array_len + else: + return "b''" + elif array_len is None: #var-length + return '[]' + else: + # fixed-length + def_val = default_value(msg_context, base_type, default_package) + if base_type in [ + 'byte', 'int8', 'int16', 'int32', 'int64', 'uint16', 'uint32', + 'uint64', 'float32', 'float64', 'string', 'bool' + ]: # fill primitive values + return '[' + def_val + '] * ' + str(array_len) + else: # fill values with distinct instances + def_val = default_value(msg_context, base_type, default_package) + return '[' + def_val + ' for _ in range(' + str(array_len) + ')]' + else: + return compute_constructor(msg_context, default_package, field_type) + +def flatten(msg_context, msg): + """ + Flattens the msg spec so that embedded message fields become + direct references. The resulting MsgSpec isn't a true/legal + :class:`MsgSpec` and should only be used for serializer generation. + :param msg: MsgSpec to flatten + :returns: flattened MsgSpec message + """ + new_types = [] + new_names = [] + for t, n in zip(msg.types, msg.names): + # Parse type to make sure we don't flatten an array + msg_type, is_array, _ = genmsg.msgs.parse_type(t) + #flatten embedded types - note: bug #59 + if not is_array and msg_context.is_registered(t): + msg_spec = flatten(msg_context, msg_context.get_registered(t)) + new_types.extend(msg_spec.types) + for n2 in msg_spec.names: + new_names.append(n+'.'+n2) + else: + #I'm not sure if it's a performance win to flatten fixed-length arrays + #as you get n __getitems__ method calls vs. a single *array call + new_types.append(t) + new_names.append(n) + return MsgSpec(new_types, new_names, msg.constants, msg.text, msg.full_name) + +def make_python_safe(spec): + """ + Remap field/constant names in spec to avoid collision with Python reserved words. + + :param spec: msg spec to map to new, python-safe field names, ``MsgSpec`` + :returns: python-safe message specification, ``MsgSpec`` + """ + new_c = [genmsg.Constant(c.type, _remap_reserved(c.name), c.val, c.val_text) for c in spec.constants] + return MsgSpec(spec.types, [_remap_reserved(n) for n in spec.names], new_c, spec.text, spec.full_name) + +def _remap_reserved(field_name): + """ + Map field_name to a python-safe representation, if necessary + :param field_name: msg field name, ``str`` + :returns: remapped name, ``str`` + """ + # include 'self' as well because we are within a class instance + idx = field_name.rfind('.') + if idx > 0: + prefix = field_name[:idx+1] + sub_field_name = field_name[idx+1:] + else: + prefix = '' + sub_field_name = field_name + + if sub_field_name in keyword.kwlist + ['self']: + sub_field_name = sub_field_name + "_" + return prefix + sub_field_name + +################################################################################ +# (de)serialization routines + +def compute_post_deserialize(type_, varname): + """ + Compute post-deserialization code for type_, if necessary + :returns: code to execute post-deserialization (unindented), or None if not necessary. ``str`` + """ + s = get_special(type_) + if s is not None: + return s.get_post_deserialize(varname) + +def compute_constructor(msg_context, package, type_): + """ + Compute python constructor expression for specified message type implementation + :param package str: package that type is being imported into. Used + to resolve type_ if package is not specified. ``str`` + :param type_: message type, ``str`` + """ + if is_special(type_): + return get_special(type_).constructor + elif genmsg.msgs.bare_msg_type(type_) != type_: + # array or other weird type + return None + else: + base_pkg, base_type_ = compute_pkg_type(package, type_) + if not msg_context.is_registered("%s/%s"%(base_pkg,base_type_)): + return None + else: + return '%s.msg.%s()'%(base_pkg, base_type_) + +def compute_pkg_type(package, type_): + """ + :param package: package that type is being imported into, ``str`` + :param type: message type (package resource name), ``str`` + :returns: python package and type name, ``(str, str)`` + """ + splits = type_.split(genmsg.SEP) + if len(splits) == 1: + return package, splits[0] + elif len(splits) == 2: + return tuple(splits) + else: + raise MsgGenerationException("illegal message type: %s"%type_) + +def compute_import(msg_context, package, type_): + """ + Compute python import statement for specified message type implementation + :param package: package that type is being imported into, ``str`` + :param type_: message type (package resource name), ``str`` + :returns: list of import statements (no newline) required to use type_ from package, ``[str]`` + """ + # orig_base_type is the unresolved type + orig_base_type = genmsg.msgs.bare_msg_type(type_) # strip array-suffix + # resolve orig_base_type based on the current package context. + # base_type is the resolved type stripped of any package name. + # pkg is the actual package of type_. + pkg, base_type = compute_pkg_type(package, orig_base_type) + full_msg_type = "%s/%s"%(pkg, base_type) # compute fully-qualified type + # important: have to do is_builtin check first. We do this check + # against the unresolved type builtins/specials are never + # relative. This requires some special handling for Header, which has + # two names (Header and std_msgs/Header). + if genmsg.msgs.is_builtin(orig_base_type) or \ + genmsg.msgs.is_header_type(orig_base_type): + # of the builtin types, only special types require import + # handling. we switch to base_type as special types do not + # include package names. + if is_special(base_type): + retval = [get_special(base_type).import_str] + else: + retval = [] + elif not msg_context.is_registered(full_msg_type): + retval = [] + else: + retval = ['import %s.msg'%pkg] + iter_types = get_registered_ex(msg_context, full_msg_type).types + for t in iter_types: + assert t != full_msg_type, "msg [%s] has circular self-dependencies"%(full_msg_type) + full_sub_type = "%s/%s"%(package, t) + log("compute_import", full_msg_type, package, t) + sub = compute_import(msg_context, package, t) + retval.extend([x for x in sub if not x in retval]) + return retval + +def compute_full_text_escaped(msg_context, spec): + """ + Same as genmsg.compute_full_text, except that the + resulting text is escaped to be safe for Python's triple-quote string + quoting + + :param get_deps_dict: dictionary returned by load_dependencies call, ``dict`` + :returns: concatenated text for msg/srv file and embedded msg/srv types. Text will be escaped for triple-quote, ``str`` + """ + msg_definition = genmsg.compute_full_text(msg_context, spec) + msg_definition = msg_definition.replace('"""', r'\"\"\"') + return msg_definition + +################################################################################ +# (De)serialization generators + +_serial_context = '' +_context_stack = [] + +_counter = 0 +def next_var(): + # we could optimize this by reusing vars once the context is popped + global _counter + _counter += 1 + return '_v%s'%_counter + +def reset_var(): + global _counter + _counter = 0 + +def push_context(context): + """ + Push new variable context onto context stack. The context stack + manages field-reference context for serialization, e.g. 'self.foo' + vs. 'self.bar.foo' vs. 'var.foo' + """ + global _serial_context, _context_stack + _context_stack.append(_serial_context) + _serial_context = context + +def pop_context(): + """ + Pop variable context from context stack. The context stack manages + field-reference context for serialization, e.g. 'self.foo' + vs. 'self.bar.foo' vs. 'var.foo' + """ + global _serial_context + _serial_context = _context_stack.pop() + +# These are the workhorses of the message generation. The generators +# are implemented as iterators, where each iteration value is a line +# of Python code. The generators will invoke underlying generators, +# using the context stack to manage any changes in variable-naming, so +# that code can be reused as much as possible. + +def len_serializer_generator(var, is_string, serialize): + """ + Generator for array-length serialization (32-bit, little-endian unsigned integer) + :param var: variable name, ``str`` + :param is_string: if True, variable is a string type, ``bool`` + :param serialize bool: if True, generate code for + serialization. Other, generate code for deserialization, ``bool`` + """ + if serialize: + yield "length = len(%s)"%var + # NOTE: it's more difficult to save a call to struct.pack with + # the array length as we are already using *array_val to pass + # into struct.pack as *args. Although it's possible that + # Python is not optimizing it, it is potentially worse for + # performance to attempt to combine + if not is_string: + yield int32_pack("length") + else: + yield "start = end" + yield "end += 4" + yield int32_unpack('length', 'str[start:end]') #4 = struct.calcsize(' 1 and _serial_context.endswith('.'): + yield '_x = '+_serial_context[:-1] + vars_ = '_x.' + (', _x.').join(spec.names[start:end]) + else: + vars_ = _serial_context + (', '+_serial_context).join(spec.names[start:end]) + + pattern = compute_struct_pattern(spec.types[start:end]) + if serialize: + yield pack(pattern, vars_) + else: + yield "start = end" + yield "end += %s"%struct.calcsize('<%s'%reduce_pattern(pattern)) + yield unpack('(%s,)'%vars_, pattern, 'str[start:end]') + + # convert uint8 to bool. this doesn't add much value as Python + # equality test on a field will return that True == 1, but I + # want to be consistent with bool + bool_vars = [(f, t) for f, t in zip(spec.names[start:end], spec.types[start:end]) if t == 'bool'] + for f, t in bool_vars: + #TODO: could optimize this as well + var = _serial_context+f + yield "%s = bool(%s)"%(var, var) + +def serializer_generator(msg_context, spec, serialize, is_numpy): + """ + Python generator that yields un-indented python code for + (de)serializing MsgSpec. The code this yields is meant to be + included in a class method and cannot be used + standalone. serialize_fn_generator and deserialize_fn_generator + wrap method to provide appropriate class field initializations. + + :param serialize: if True, yield serialization + code. Otherwise, yield deserialization code. ``bool`` + :param is_numpy: if True, generate serializer code for numpy datatypes instead of Python lists. ``bool`` + """ + # Break spec into chunks of simple (primitives) vs. complex (arrays, etc...) + # Simple types are batch serialized using the python struct module. + # Complex types are individually serialized + if spec is None: + raise MsgGenerationException("spec is none") + names, types = spec.names, spec.types + if serialize and not len(names): #Empty + yield "pass" + return + + _max_chunk = 255 + # iterate through types. whenever we encounter a non-simple type, + # yield serializer for any simple types we've encountered until + # then, then yield the complex type serializer + curr = 0 + for (i, full_type) in enumerate(types): + if not is_simple(full_type): + if i != curr: #yield chunk of simples + for _start in range(curr, i, _max_chunk): + _end = min(_start + _max_chunk, i) + for y in simple_serializer_generator(msg_context, spec, _start, _end, serialize): + yield y + curr = i+1 + for y in complex_serializer_generator(msg_context, spec.package, full_type, names[i], serialize, is_numpy): + yield y + if curr < len(types): #yield rest of simples + for _start in range(curr, len(types), _max_chunk): + _end = min(_start + _max_chunk, len(types)) + for y in simple_serializer_generator(msg_context, spec, _start, _end, serialize): + yield y + +def serialize_fn_generator(msg_context, spec, is_numpy=False): + """ + generator for body of serialize() function + :param is_numpy: if True, generate serializer code for numpy + datatypes instead of Python lists, ``bool`` + """ + # method-var context ######### + yield "try:" + push_context('self.') + #NOTE: we flatten the spec for optimal serialization + # #3741: make sure to have sub-messages python safe + flattened = make_python_safe(flatten(msg_context, spec)) + for y in serializer_generator(msg_context, flattened, True, is_numpy): + yield " "+y + pop_context() + yield "except struct.error as se: self._check_types(struct.error(\"%s: '%s' when writing '%s'\" % (type(se), str(se), str(locals().get('_x', self)))))" + yield "except TypeError as te: self._check_types(ValueError(\"%s: '%s' when writing '%s'\" % (type(te), str(te), str(locals().get('_x', self)))))" + # done w/ method-var context # + +def deserialize_fn_generator(msg_context, spec, is_numpy=False): + """ + generator for body of deserialize() function + :param is_numpy: if True, generate serializer code for numpy + datatypes instead of Python lists, ``bool`` + """ + yield "try:" + package = spec.package + #Instantiate embedded type classes + for type_, name in spec.fields(): + if msg_context.is_registered(type_): + yield " if self.%s is None:"%name + yield " self.%s = %s"%(name, compute_constructor(msg_context, package, type_)) + yield " end = 0" #initialize var + + # method-var context ######### + push_context('self.') + #NOTE: we flatten the spec for optimal serialization + # #3741: make sure to have sub-messages python safe + flattened = make_python_safe(flatten(msg_context, spec)) + for y in serializer_generator(msg_context, flattened, False, is_numpy): + yield " "+y + pop_context() + # done w/ method-var context # + + # generate post-deserialization code + for type_, name in spec.fields(): + code = compute_post_deserialize(type_, "self.%s"%name) + if code: + yield " %s"%code + + yield " return self" + yield "except struct.error as e:" + yield " raise genpy.DeserializationError(e) #most likely buffer underfill" + +def msg_generator(msg_context, spec, search_path): + """ + Python code generator for .msg files. Generates a Python from a + :class:`genmsg.MsgSpec`. + + :param spec: parsed .msg :class:`genmsg.MsgSpec` instance + :param search_path: dictionary mapping message namespaces to a directory locations + """ + + # #2990: have to compute md5sum before any calls to make_python_safe + + # generate dependencies dictionary. omit files calculation as we + # rely on in-memory MsgSpecs instead so that we can generate code + # for older versions of msg files + try: + genmsg.msg_loader.load_depends(msg_context, spec, search_path) + except InvalidMsgSpec as e: + raise MsgGenerationException("Cannot generate .msg for %s/%s: %s"%(package, name, str(e))) + md5sum = genmsg.compute_md5(msg_context, spec) + + # remap spec names to be Python-safe + spec = make_python_safe(spec) + spec_names = spec.names + + # #1807 : this will be much cleaner when msggenerator library is + # rewritten to not use globals + clear_patterns() + + yield '# This Python file uses the following encoding: utf-8' + yield '"""autogenerated by genpy from %s.msg. Do not edit."""'%spec.full_name + yield 'import sys' + yield 'python3 = True if sys.hexversion > 0x03000000 else False' + yield 'import genpy\nimport struct\n' + import_strs = [] + for t in spec.types: + import_strs.extend(compute_import(msg_context, spec.package, t)) + import_strs = set(import_strs) + for i in import_strs: + if i: + yield i + + yield '' + + fulltype = spec.full_name + name = spec.short_name + + #Yield data class first, e.g. Point2D + yield 'class %s(genpy.Message):'%spec.short_name + yield ' _md5sum = "%s"'%(md5sum) + yield ' _type = "%s"'%(fulltype) + yield ' _has_header = %s #flag to mark the presence of a Header object'%spec.has_header() + + full_text = compute_full_text_escaped(msg_context, spec) + # escape trailing double-quote, unless already escaped, before wrapping in """ + if full_text.endswith('"') and not full_text.endswith(r'\"'): + full_text = full_text[:-1] + r'\"' + yield ' _full_text = """%s"""'%full_text + + if spec.constants: + yield ' # Pseudo-constants' + for c in spec.constants: + if c.type == 'string': + val = c.val + if '"' in val and "'" in val: + # crude escaping of \ and " + escaped = c.val.replace('\\', '\\\\') + escaped = escaped.replace('\"', '\\"') + yield ' %s = "%s"'%(c.name, escaped) + elif '"' in val: #use raw encoding for prettiness + yield " %s = r'%s'"%(c.name, val) + elif "'" in val: #use raw encoding for prettiness + yield ' %s = r"%s"'%(c.name, val) + else: + yield " %s = '%s'"%(c.name, val) + else: + yield ' %s = %s'%(c.name, c.val) + yield '' + + if len(spec_names): + yield " __slots__ = ['"+"','".join(spec_names)+"']" + yield " _slot_types = ['"+"','".join(spec.types)+"']" + else: + yield " __slots__ = []" + yield " _slot_types = []" + + yield """ + def __init__(self, *args, **kwds): + \"\"\" + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + %s + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + \"\"\" + if args or kwds: + super(%s, self).__init__(*args, **kwds)"""%(','.join(spec_names), name) + + if len(spec_names): + yield " #message fields cannot be None, assign default values for those that are" + for (t, s) in zip(spec.types, spec_names): + yield " if self.%s is None:"%s + yield " self.%s = %s"%(s, default_value(msg_context, t, spec.package)) + if len(spec_names) > 0: + yield " else:" + for (t, s) in zip(spec.types, spec_names): + yield " self.%s = %s"%(s, default_value(msg_context, t, spec.package)) + + yield """ + def _get_types(self): + \"\"\" + internal API method + \"\"\" + return self._slot_types + + def serialize(self, buff): + \"\"\" + serialize message into buffer + :param buff: buffer, ``StringIO`` + \"\"\"""" + for y in serialize_fn_generator(msg_context, spec): + yield " "+ y + yield """ + def deserialize(self, str): + \"\"\" + unpack serialized message in str into this message instance + :param str: byte array of serialized message, ``str`` + \"\"\"""" + for y in deserialize_fn_generator(msg_context, spec): + yield " " + y + yield "" + + yield """ + def serialize_numpy(self, buff, numpy): + \"\"\" + serialize message with numpy array types into buffer + :param buff: buffer, ``StringIO`` + :param numpy: numpy python module + \"\"\"""" + for y in serialize_fn_generator(msg_context, spec, is_numpy=True): + yield " "+ y + yield """ + def deserialize_numpy(self, str, numpy): + \"\"\" + unpack serialized message in str into this message instance using numpy for array types + :param str: byte array of serialized message, ``str`` + :param numpy: numpy python module + \"\"\"""" + for y in deserialize_fn_generator(msg_context, spec, is_numpy=True): + yield " " + y + yield "" + + + # #1807 : this will be much cleaner when msggenerator library is + # rewritten to not use globals + yield '_struct_I = genpy.struct_I' + yield 'def _get_struct_I():' + yield ' global _struct_I' + yield ' return _struct_I' + patterns = get_patterns() + for p in set(patterns): + # I patterns are already optimized + if p == 'I': + continue + var_name = '_struct_%s'%(p.replace('<','')) + yield '%s = None' % var_name + yield 'def _get%s():' % var_name + yield ' global %s' % var_name + yield ' if %s is None:' % var_name + yield ' %s = struct.Struct("<%s")' % (var_name, p) + yield ' return %s' % var_name + clear_patterns() + +def srv_generator(msg_context, spec, search_path): + for mspec in (spec.request, spec.response): + for l in msg_generator(msg_context, mspec, search_path): + yield l + + name = spec.short_name + req, resp = ["%s%s"%(name, suff) for suff in ['Request', 'Response']] + + fulltype = spec.full_name + + genmsg.msg_loader.load_depends(msg_context, spec, search_path) + md5 = genmsg.compute_md5(msg_context, spec) + + yield "class %s(object):"%name + yield " _type = '%s'"%fulltype + yield " _md5sum = '%s'"%md5 + yield " _request_class = %s"%req + yield " _response_class = %s"%resp + +def _module_name(type_name): + """ + :param type_name str: Name of message type sans package, + e.g. 'String' + :returns str: name of python module for auto-generated code + """ + return "_"+type_name + +def compute_resource_name(filename, ext): + """ + Convert resource filename to ROS resource name + :param filename str: path to .msg/.srv file + :returns str: name of ROS resource + """ + return os.path.basename(filename)[:-len(ext)] + +def compute_outfile_name(outdir, infile_name, ext): + """ + :param outdir str: path to directory that files are generated to + :returns str: output file path based on input file name and output directory + """ + # Use leading _ so that module name does not collide with message name. It also + # makes it more clear that the .py file should not be imported directly + return os.path.join(outdir, _module_name(compute_resource_name(infile_name, ext))+".py") + +class Generator(object): + + def __init__(self, what, ext, spec_loader_fn, generator_fn): + self.what = what + self.ext = ext + self.spec_loader_fn = spec_loader_fn + self.generator_fn = generator_fn + + def generate(self, msg_context, full_type, f, outdir, search_path): + try: + # you can't just check first... race condition + os.makedirs(outdir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + # generate message files for request/response + spec = self.spec_loader_fn(msg_context, f, full_type) + outfile = compute_outfile_name(outdir, os.path.basename(f), self.ext) + with open(outfile, 'w') as f: + for l in self.generator_fn(msg_context, spec, search_path): + f.write(l+'\n') + return outfile + + def generate_messages(self, package, package_files, outdir, search_path): + """ + :returns: return code, ``int`` + """ + if not genmsg.is_legal_resource_base_name(package): + raise MsgGenerationException("\nERROR: package name '%s' is illegal and cannot be used in message generation.\nPlease see http://ros.org/wiki/Names"%(package)) + + # package/src/package/msg for messages, packages/src/package/srv for services + msg_context = MsgContext.create_default() + retcode = 0 + for f in package_files: + try: + f = os.path.abspath(f) + infile_name = os.path.basename(f) + full_type = genmsg.gentools.compute_full_type_name(package, infile_name); + outfile = self.generate(msg_context, full_type, f, outdir, search_path) #actual generation + except Exception as e: + if not isinstance(e, MsgGenerationException) and not isinstance(e, genmsg.msgs.InvalidMsgSpec): + traceback.print_exc() + print("\nERROR: Unable to generate %s for package '%s': while processing '%s': %s\n"%(self.what, package, f, e), file=sys.stderr) + retcode = 1 #flag error + return retcode + +class SrvGenerator(Generator): + + def __init__(self): + super(SrvGenerator, self).__init__('services', genmsg.EXT_SRV, + genmsg.msg_loader.load_srv_from_file, + srv_generator) + +class MsgGenerator(Generator): + """ + Generates Python message code for all messages in a + package. See genutil.Generator. In order to generator code for a + single .msg file, see msg_generator. + """ + def __init__(self): + super(MsgGenerator, self).__init__('messages', genmsg.EXT_MSG, + genmsg.msg_loader.load_msg_from_file, + msg_generator) + diff --git a/tiny_tf/genpy/genpy_main.py b/tiny_tf/genpy/genpy_main.py new file mode 100644 index 0000000..bee2c3d --- /dev/null +++ b/tiny_tf/genpy/genpy_main.py @@ -0,0 +1,87 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +from optparse import OptionParser + +import os +import sys +import traceback +import genmsg +import genmsg.command_line + +from genmsg import MsgGenerationException +from . generate_initpy import write_modules + +def usage(progname): + print("%(progname)s file(s)"%vars()) + +def genmain(argv, progname, gen): + parser = OptionParser("%s file"%(progname)) + parser.add_option('--initpy', dest='initpy', action='store_true', + default=False) + parser.add_option('-p', dest='package') + parser.add_option('-o', dest='outdir') + parser.add_option('-I', dest='includepath', action='append') + options, args = parser.parse_args(argv) + try: + if options.initpy: + if options.outdir: + retcode = write_modules(options.outdir) + else: + parser.error("Missing args") + else: + if len(args) < 2: + parser.error("please specify args") + if not os.path.exists(options.outdir): + # This script can be run multiple times in parallel. We + # don't mind if the makedirs call fails because somebody + # else snuck in and created the directory before us. + try: + os.makedirs(options.outdir) + except OSError as e: + if not os.path.exists(options.outdir): + raise + search_path = genmsg.command_line.includepath_to_dict(options.includepath) + retcode = gen.generate_messages(options.package, args[1:], options.outdir, search_path) + except genmsg.InvalidMsgSpec as e: + print("ERROR: ", e, file=sys.stderr) + retcode = 1 + except MsgGenerationException as e: + print("ERROR: ", e, file=sys.stderr) + retcode = 2 + except Exception as e: + traceback.print_exc() + print("ERROR: ",e) + retcode = 3 + sys.exit(retcode or 0) diff --git a/tiny_tf/genpy/message.py b/tiny_tf/genpy/message.py new file mode 100644 index 0000000..f4345b1 --- /dev/null +++ b/tiny_tf/genpy/message.py @@ -0,0 +1,655 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +Support library for Python autogenerated message files. This defines +the Message base class used by genpy as well as support +libraries for type checking and retrieving message classes by type +name. +""" + +import math +import itertools +import struct +import sys +import yaml + +import genmsg + +from .base import is_simple +from .rostime import Time, Duration, TVal + +try: + reload # Python 2 +except NameError: # Python 3 + from importlib import reload + +# common struct pattern singletons for msgs to use. Although this +# would better placed in a generator-specific module, we don't want to +# add another import to messages (which incurs higher import cost) + +if sys.version > '3': + long = int + +struct_I = struct.Struct('iter(str)`` + :returns: string (YAML) representation of message, ``str`` + """ + + type_ = type(val) + if type_ in (int, long, float) and fixed_numeric_width is not None: + if type_ is float: + num_str = ('%.' + str(fixed_numeric_width) + 'f') % val + return num_str[:max(num_str.find('.'), fixed_numeric_width)] + else: + return ('%' + str(fixed_numeric_width) + 'd') % val + elif type_ in (int, long, float, bool): + return str(val) + elif isstring(val): + if not val: + return "''" + # escape strings for use in yaml file using yaml dump with default style to avoid trailing "...\n" + return yaml.dump(val, default_style='"').rstrip('\n') + elif isinstance(val, TVal): + + if time_offset is not None and isinstance(val, Time): + val = val-time_offset + + if fixed_numeric_width is not None: + format_str = '%' + str(fixed_numeric_width) + 'd' + sec_str = '\n%ssecs: ' % indent + (format_str % val.secs) + nsec_str = '\n%snsecs: ' % indent + (format_str % val.nsecs) + return sec_str + nsec_str + else: + return '\n%ssecs: %s\n%snsecs: %9d'%(indent, val.secs, indent, val.nsecs) + + elif type_ in (list, tuple): + if len(val) == 0: + return "[]" + val0 = val[0] + if type(val0) in (int, float) and fixed_numeric_width is not None: + list_str = '[' + ''.join(strify_message(v, indent, time_offset, current_time, field_filter, fixed_numeric_width) + ', ' for v in val).rstrip(', ') + ']' + return list_str + elif isstring(val0): + # escape list of strings for use in yaml file using yaml dump + return yaml.dump(val).rstrip('\n') + elif type(val0) in (int, float, bool): + return str(list(val)) + else: + pref = indent + '- ' + indent = indent + ' ' + return '\n'+'\n'.join([pref+strify_message(v, indent, time_offset, current_time, field_filter, fixed_numeric_width) for v in val]) + elif isinstance(val, Message): + # allow caller to select which fields of message are strified + if field_filter is not None: + fields = list(field_filter(val)) + else: + fields = val.__slots__ + + p = '%s%%s: %%s'%(indent) + ni = ' '+indent + if sys.hexversion > 0x03000000: #Python3 + vals = '\n'.join([p%(f, + strify_message(_convert_getattr(val, f, t), ni, time_offset, current_time, field_filter, fixed_numeric_width)) for f,t in zip(val.__slots__, val._slot_types) if f in fields]) + else: #Python2 + vals = '\n'.join([p%(f, + strify_message(_convert_getattr(val, f, t), ni, time_offset, current_time, field_filter, fixed_numeric_width)) for f,t in itertools.izip(val.__slots__, val._slot_types) if f in fields]) + if indent: + return '\n'+vals + else: + return vals + + else: + return str(val) #punt + +def _convert_getattr(val, f, t): + """ + Convert atttribute types on the fly, if necessary. This is mainly + to convert uint8[] fields back to an array type. + """ + attr = getattr(val, f) + if isstring(attr) and 'uint8[' in t: + return [ord(x) for x in attr] + elif isinstance(attr, bytes) and 'uint8[' in t: + return list(attr) + else: + return attr + +# check_type mildly violates some abstraction boundaries between .msg +# representation and the python Message representation. The +# alternative is to have the message generator map .msg types to +# python types beforehand, but that would make it harder to do +# width/signed checks. + +_widths = { + 'byte': 8, 'char': 8, 'int8': 8, 'uint8': 8, + 'int16': 16, 'uint16': 16, + 'int32': 32, 'uint32': 32, + 'int64': 64, 'uint64': 64, +} + +def check_type(field_name, field_type, field_val): + """ + Dynamic type checker that maps ROS .msg types to python types and + verifies the python value. check_type() is not designed to be + fast and is targeted at error diagnosis. This type checker is not + designed to run fast and is meant only for error diagnosis. + + :param field_name: ROS .msg field name, ``str`` + :param field_type: ROS .msg field type, ``str`` + :param field_val: field value, ``Any`` + :raises: :exc:`SerializationError` If typecheck fails + """ + if is_simple(field_type): + # check sign and width + if field_type in ['byte', 'int8', 'int16', 'int32', 'int64']: + if type(field_val) not in [long, int]: + raise SerializationError('field %s must be an integer type'%field_name) + maxval = int(math.pow(2, _widths[field_type]-1)) + if field_val >= maxval or field_val <= -maxval: + raise SerializationError('field %s exceeds specified width [%s]'%(field_name, field_type)) + elif field_type in ['char', 'uint8', 'uint16', 'uint32', 'uint64']: + if type(field_val) not in [long, int] or field_val < 0: + raise SerializationError('field %s must be unsigned integer type'%field_name) + maxval = int(math.pow(2, _widths[field_type])) + if field_val >= maxval: + raise SerializationError('field %s exceeds specified width [%s]'%(field_name, field_type)) + elif field_type == 'bool': + if field_val not in [True, False, 0, 1]: + raise SerializationError('field %s is not a bool'%(field_name)) + elif field_type == 'string': + if sys.hexversion > 0x03000000: + if type(field_val) == str: + try: + field_val.encode('ascii') + except UnicodeEncodeError: + raise SerializationError('field %s is a non-ascii string'%field_name) + elif not type(field_val) == bytes: + raise SerializationError('field %s must be of type bytes or an ascii string'%field_name) + else: + if type(field_val) == unicode: # noqa: F821 + raise SerializationError('field %s is a unicode string instead of an ascii string'%field_name) + elif not isstring(field_val): + raise SerializationError('field %s must be of type str'%field_name) + elif field_type == 'time': + if not isinstance(field_val, Time): + raise SerializationError('field %s must be of type Time'%field_name) + elif field_type == 'duration': + if not isinstance(field_val, Duration): + raise SerializationError('field %s must be of type Duration'%field_name) + + elif field_type.endswith(']'): # array type + # use index to generate error if '[' not present + base_type = field_type[:field_type.index('[')] + + if type(field_val) == str: + if not base_type in ['char', 'uint8']: + raise SerializationError('field %s must be a list or tuple type. Only uint8[] can be a string' % field_name); + else: + #It's a string so its already in byte format and we + #don't need to check the individual bytes in the + #string. + return + + if not type(field_val) in [list, tuple]: + raise SerializationError('field %s must be a list or tuple type'%field_name) + for v in field_val: + check_type(field_name+"[]", base_type, v) + else: + if isinstance(field_val, Message): + # roslib/Header is the old location of Header. We check it for backwards compat + if field_val._type in ['std_msgs/Header', 'roslib/Header']: + if field_type not in ['Header', 'std_msgs/Header', 'roslib/Header']: + raise SerializationError("field %s must be a Header instead of a %s"%(field_name, field_val._type)) + elif field_val._type != field_type: + raise SerializationError("field %s must be of type %s instead of %s"%(field_name, field_type, field_val._type)) + for n, t in zip(field_val.__slots__, field_val._get_types()): + check_type("%s.%s"%(field_name,n), t, getattr(field_val, n)) + else: + raise SerializationError("field %s must be of type [%s]"%(field_name, field_type)) + + #TODO: dynamically load message class and do instance compare + +class Message(object): + """Base class of Message data classes auto-generated from msg files. """ + + # slots is explicitly both for data representation and + # performance. Higher-level code assumes that there is a 1-to-1 + # mapping between __slots__ and message fields. In terms of + # performance, explicitly settings slots eliminates dictionary for + # new-style object. + __slots__ = ['_connection_header'] + + def __init__(self, *args, **kwds): + """ + Create a new Message instance. There are multiple ways of + initializing Message instances, either using a 1-to-1 + correspondence between constructor arguments and message + fields (*args), or using Python "keyword" arguments (**kwds) to initialize named field + and leave the rest with default values. + """ + if args and kwds: + raise TypeError("Message constructor may only use args OR keywords, not both") + if args: + if len(args) != len(self.__slots__): + raise TypeError("Invalid number of arguments, args should be %s"%str(self.__slots__)+" args are"+str(args)) + for i, k in enumerate(self.__slots__): + setattr(self, k, args[i]) + else: + # validate kwds + for k,v in kwds.items(): + if not k in self.__slots__: + raise AttributeError("%s is not an attribute of %s"%(k, self.__class__.__name__)) + # iterate through slots so all fields are initialized. + # this is important so that subclasses don't reference an + # uninitialized field and raise an AttributeError. + for k in self.__slots__: + if k in kwds: + setattr(self, k, kwds[k]) + else: + setattr(self, k, None) + + def __getstate__(self): + """ + support for Python pickling + """ + return [getattr(self, x) for x in self.__slots__] + + def __setstate__(self, state): + """ + support for Python pickling + """ + for x, val in zip(self.__slots__, state): + setattr(self, x, val) + + def _get_types(self): + raise Exception("must be overriden") + def _check_types(self, exc=None): + """ + Perform dynamic type-checking of Message fields. This is performance intensive + and is meant for post-error diagnosis + :param exc: underlying exception that gave cause for type check, ``Exception`` + :raises: exc:`genpy.SerializationError` If typecheck fails + """ + for n, t in zip(self.__slots__, self._get_types()): + check_type(n, t, getattr(self, n)) + if exc: # if exc is set and check_type could not diagnose, raise wrapped error + raise SerializationError(str(exc)) + + def serialize(self, buff): + """ + Serialize data into buffer + :param buff: buffer, ``StringIO`` + """ + pass + def deserialize(self, str): + """ + Deserialize data in str into this instance + :param str: serialized data, ``str`` + """ + pass + def __repr__(self): + return strify_message(self) + def __str__(self): + return strify_message(self) + # TODO: unit test + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + for f in self.__slots__: + try: + v1 = getattr(self, f) + v2 = getattr(other, f) + if type(v1) in (list, tuple) and type(v2) in (list, tuple): + # we treat tuples and lists as equivalent + if tuple(v1) != tuple(v2): + return False + elif not v1 == v2: + return False + except AttributeError: + return False + return True + def __ne__(self, other): + return not self == other + + +def get_printable_message_args(msg, buff=None, prefix=''): + """ + Get string representation of msg arguments + :param msg: msg message to fill, ``Message`` + :param prefix: field name prefix (for verbose printing), ``str`` + :returns: printable representation of msg args, ``str`` + """ + try: + from cStringIO import StringIO # Python 2.x + python3 = 0 + except ImportError: + from io import BytesIO # Python 3.x + python3 = 1 + + if buff is None: + if python3 == 1: + buff = BytesIO() + else: + buff = StringIO() + for f in msg.__slots__: + if isinstance(getattr(msg, f), Message): + get_printable_message_args(getattr(msg, f), buff=buff, prefix=(prefix+f+'.')) + else: + buff.write(prefix+f+' ') + return buff.getvalue().rstrip() + +def _fill_val(msg, f, v, keys, prefix): + """ + Subroutine of L{_fill_message_args()}. Sets a particular field on a message + :param f: field name, ``str`` + :param v: field value + :param keys: keys to use as substitute values for messages and timestamps, ``dict`` + :raises: exc:`MessageException` + """ + if not f in msg.__slots__: + raise MessageException("No field name [%s%s]"%(prefix, f)) + def_val = getattr(msg, f) + if isinstance(def_val, Message) or isinstance(def_val, TVal): + # check for substitution key, e.g. 'now' + if type(v) == str: + if v in keys: + setattr(msg, f, keys[v]) + else: + raise MessageException("No key named [%s]"%(v)) + elif isinstance(def_val, TVal) and type(v) in (int, long): + #special case to handle time value represented as a single number + #TODO: this is a lossy conversion + if isinstance(def_val, Time): + setattr(msg, f, Time.from_sec(v/1e9)) + elif isinstance(def_val, Duration): + setattr(msg, f, Duration.from_sec(v/1e9)) + else: + raise MessageException("Cannot create time values of type [%s]"%(type(def_val))) + else: + _fill_message_args(def_val, v, keys, prefix=(prefix+f+'.')) + elif type(def_val) == list: + if not type(v) in [list, tuple]: + raise MessageException("Field [%s%s] must be a list or tuple instead of: %s"%(prefix, f, type(v).__name__)) + # determine base_type of field by looking at _slot_types + idx = msg.__slots__.index(f) + t = msg._slot_types[idx] + base_type, is_array, length = genmsg.msgs.parse_type(t) + # - for primitives, we just directly set (we don't + # type-check. we rely on serialization type checker) + if base_type in genmsg.msgs.PRIMITIVE_TYPES: + # 3785 + if length is not None and len(v) != length: + raise MessageException("Field [%s%s] has incorrect number of elements: %s != %s"%(prefix, f, len(v), length)) + setattr(msg, f, v) + + # - for complex types, we have to iteratively append to def_val + else: + # 3785 + if length is not None and len(v) != length: + raise MessageException("Field [%s%s] has incorrect number of elements: %s != %s"%(prefix, f, len(v), length)) + list_msg_class = get_message_class(base_type) + if list_msg_class is None: + raise MessageException("Cannot instantiate messages for field [%s%s] : cannot load class %s"%(prefix, f, base_type)) + del def_val[:] + for el in v: + inner_msg = list_msg_class() + if isinstance(inner_msg, TVal) and type(el) in (int, long): + #special case to handle time value represented as a single number + #TODO: this is a lossy conversion + if isinstance(inner_msg, Time): + inner_msg = Time.from_sec(el/1e9) + elif isinstance(inner_msg, Duration): + inner_msg = Duration.from_sec(el/1e9) + else: + raise MessageException("Cannot create time values of type [%s]"%(type(inner_msg))) + else: + _fill_message_args(inner_msg, el, keys, prefix) + def_val.append(inner_msg) + else: + setattr(msg, f, v) + + +def _fill_message_args(msg, msg_args, keys, prefix=''): + """ + Populate message with specified args. + + :param msg: message to fill, ``Message`` + :param msg_args: list of arguments to set fields to, ``[args]`` + :param keys: keys to use as substitute values for messages and timestamps. ``dict`` + :param prefix: field name prefix (for verbose printing), ``str`` + :returns: unused/leftover message arguments. ``[args]`` + :raise :exc:`MessageException` If not enough message arguments to fill message + :raises: :exc:`ValueError` If msg or msg_args is not of correct type + """ + if not isinstance(msg, (Message, TVal)): + raise ValueError("msg must be a Message instance: %s"%msg) + + if type(msg_args) == dict: + + #print "DICT ARGS", msg_args + #print "ACTIVE SLOTS",msg.__slots__ + + for f, v in msg_args.items(): + # assume that an empty key is actually an empty string + if v == None: + v = '' + _fill_val(msg, f, v, keys, prefix) + elif type(msg_args) == list: + + #print "LIST ARGS", msg_args + #print "ACTIVE SLOTS",msg.__slots__ + + if len(msg_args) > len(msg.__slots__): + raise MessageException("Too many arguments:\n * Given: %s\n * Expected: %s"%(msg_args, msg.__slots__)) + elif len(msg_args) < len(msg.__slots__): + raise MessageException("Not enough arguments:\n * Given: %s\n * Expected: %s"%(msg_args, msg.__slots__)) + + for f, v in zip(msg.__slots__, msg_args): + _fill_val(msg, f, v, keys, prefix) + else: + raise ValueError("invalid msg_args type: %s"%str(msg_args)) + +def fill_message_args(msg, msg_args, keys={}): + """ + Populate message with specified args. Args are assumed to be a + list of arguments from a command-line YAML parser. See + http://www.ros.org/wiki/ROS/YAMLCommandLine for specification on + how messages are filled. + + fill_message_args also takes in an optional 'keys' dictionary + which contain substitute values for message and time types. These + values must be of the correct instance type, i.e. a Message, Time, + or Duration. In a string key is encountered with these types, the + value from the keys dictionary will be used instead. This is + mainly used to provide values for the 'now' timestamp. + + :param msg: message to fill, ``Message`` + :param msg_args: list of arguments to set fields to, or + If None, msg_args will be made an empty list., ``[args]`` + :param keys: keys to use as substitute values for messages and timestamps, ``dict`` + :raises: :exc:`MessageException` If not enough/too many message arguments to fill message + """ + # a list of arguments is similar to python's + # *args, whereas dictionaries are like **kwds. + + # empty messages serialize as a None, which we make equivalent to + # an empty message + if msg_args is None: + msg_args = [] + + # msg_args is always a list, due to the fact it is parsed from a + # command-line argument list. We have to special-case handle a + # list with a single dictionary, which has precedence over the + # general list representation. We offer this precedence as there + # is no other way to do kwd assignments into the outer message. + if len(msg_args) == 1 and type(msg_args[0]) == dict: + # according to spec, if we only get one msg_arg and it's a dictionary, we + # use it directly + _fill_message_args(msg, msg_args[0], keys, '') + else: + _fill_message_args(msg, msg_args, keys, '') + +def _get_message_or_service_class(type_str, message_type, reload_on_error=False): + """ + Utility for retrieving message/service class instances. Used by + get_message_class and get_service_class. + :param type_str: 'msg' or 'srv', ``str`` + :param message_type: type name of message/service, ``str`` + :returns: Message/Service for message/service type or None, ``class`` + :raises: :exc:`ValueError` If message_type is invalidly specified + """ + if message_type == 'time': + return Time + if message_type == 'duration': + return Duration + ## parse package and local type name for import + package, base_type = genmsg.package_resource_name(message_type) + if not package: + if base_type == 'Header': + package = 'std_msgs' + else: + raise ValueError("message type is missing package name: %s"%str(message_type)) + pypkg = val = None + try: + # import the package + pypkg = __import__('%s.%s' % (package, type_str)) + except ImportError: + # try importing from dry package if available + try: + from roslib import load_manifest + from rospkg import ResourceNotFound + try: + load_manifest(package) + try: + pypkg = __import__('%s.%s' % (package, type_str)) + except ImportError: + pass + except ResourceNotFound: + pass + except ImportError: + pass + if pypkg: + try: + val = getattr(getattr(pypkg, type_str), base_type) + except AttributeError: + pass + + # this logic is mainly to support rosh, so that a user doesn't + # have to exit a shell just because a message wasn't built yet + if val is None and reload_on_error: + try: + if pypkg: + reload(pypkg) + val = getattr(getattr(pypkg, type_str), base_type) + except: + val = None + return val + +## cache for get_message_class +_message_class_cache = {} + +def get_message_class(message_type, reload_on_error=False): + """ + Get the message class. NOTE: this function maintains a + local cache of results to improve performance. + :param message_type: type name of message, ``str`` + :param reload_on_error: (optional). Attempt to reload the Python + module if unable to load message the first time. Defaults to + False. This is necessary if messages are built after the first load. + :returns: Message class for message/service type, ``Message class`` + :raises :exc:`ValueError`: if message_type is invalidly specified + """ + if message_type in _message_class_cache: + return _message_class_cache[message_type] + cls = _get_message_or_service_class('msg', message_type, reload_on_error=reload_on_error) + if cls: + _message_class_cache[message_type] = cls + return cls + +## cache for get_service_class +_service_class_cache = {} + +def get_service_class(service_type, reload_on_error=False): + """ + Get the service class. NOTE: this function maintains a + local cache of results to improve performance. + :param service_type: type name of service, ``str`` + :param reload_on_error: (optional). Attempt to reload the Python + module if unable to load message the first time. Defaults to + False. This is necessary if messages are built after the first load. + :returns: Service class for service type, ``Service class`` + :raises :exc:`Exception` If service_type is invalidly specified + """ + if service_type in _service_class_cache: + return _service_class_cache[service_type] + cls = _get_message_or_service_class('srv', service_type, reload_on_error=reload_on_error) + _service_class_cache[service_type] = cls + return cls + diff --git a/tiny_tf/genpy/rostime.py b/tiny_tf/genpy/rostime.py new file mode 100644 index 0000000..0ed3c9b --- /dev/null +++ b/tiny_tf/genpy/rostime.py @@ -0,0 +1,442 @@ +# Software License Agreement (BSD License) +# +# Copyright (c) 2008, Willow Garage, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +""" +ROS Time representation, including Duration +""" +from __future__ import division +import numbers +import sys +import warnings + + +def _canon(secs, nsecs): + # canonical form: nsecs is always positive, nsecs < 1 second + secs_over = nsecs // 1000000000 + secs += secs_over + nsecs -= secs_over * 1000000000 + return secs, nsecs + + +class TVal(object): + """ + Base class of :class:`Time` and :class:`Duration` representations. Representation + is secs+nanoseconds since epoch. + """ + + __slots__ = ['secs', 'nsecs'] + + # mimic same API as messages when being introspected + _slot_types = ['int32', 'int32'] + + def __init__(self, secs=0, nsecs=0): + """ + :param secs: seconds. If secs is a float, then nsecs must not be set or 0, + larger seconds will be of type long on 32-bit systems, ``int/long/float`` + :param nsecs: nanoseconds, ``int`` + """ + if not isinstance(secs, numbers.Integral): + # float secs constructor + if nsecs != 0: + raise ValueError("if secs is a float, nsecs cannot be set") + float_secs = secs + secs = int(float_secs) + nsecs = int((float_secs - secs) * 1000000000) + + self.secs, self.nsecs = _canon(secs, nsecs) + + @classmethod + def from_sec(cls, float_secs): + """ + Create new TVal instance using time.time() value (float + seconds) + + :param float_secs: time value in time.time() format, ``float`` + :returns: :class:`TVal` instance for specified time + """ + secs = int(float_secs) + nsecs = int((float_secs - secs) * 1000000000) + return cls(secs, nsecs) + + def is_zero(self): + """ + :returns: ``True`` if time is zero (secs and nsecs are zero), ``bool`` + """ + return self.secs == 0 and self.nsecs == 0 + + def set(self, secs, nsecs): + """ + Set time using separate secs and nsecs values + + :param secs: seconds since epoch, ``int`` + :param nsecs: nanoseconds since seconds, ``int`` + """ + self.secs = secs + self.nsecs = nsecs + + def canon(self): + """ + Canonicalize the field representation in this instance. should + only be used when manually setting secs/nsecs slot values, as + in deserialization. + """ + self.secs, self.nsecs = _canon(self.secs, self.nsecs) + + def to_sec(self): + """ + :returns: time as float seconds (same as time.time() representation), ``float`` + """ + return float(self.secs) + float(self.nsecs) / 1e9 + + def to_nsec(self): + """ + :returns: time as nanoseconds, ``long`` + """ + return self.secs * int(1e9) + self.nsecs + + def __hash__(self): + """ + Time values are hashable. Time values with identical fields have the same hash. + """ + return hash((self.secs, self.nsecs)) + + def __str__(self): + return str(self.to_nsec()) + + def __repr__(self): + return "genpy.TVal[%d]"%self.to_nsec() + + def __nonzero__(self): + """ + Return if time value is not zero + """ + return self.secs != 0 or self.nsecs != 0 + __bool__ = __nonzero__ + + def __lt__(self, other): + """ + < test for time values + """ + try: + return self.__cmp__(other) < 0 + except TypeError: + return NotImplemented + def __le__(self, other): + """ + <= test for time values + """ + try: + return self.__cmp__(other) <= 0 + except TypeError: + return NotImplemented + def __gt__(self, other): + """ + > test for time values + """ + try: + return self.__cmp__(other) > 0 + except TypeError: + return NotImplemented + def __ge__(self, other): + """ + >= test for time values + """ + try: + return self.__cmp__(other) >= 0 + except TypeError: + return NotImplemented + def __ne__(self, other): + return not self.__eq__(other) + def __cmp__(self, other): + if not isinstance(other, TVal): + raise TypeError("Cannot compare to non-TVal") + a = self.to_nsec() + b = other.to_nsec() + return (a > b) - (a < b) + + def __eq__(self, other): + if not isinstance(other, TVal): + return False + return self.to_nsec() == other.to_nsec() + +class Time(TVal): + """ + Time contains the ROS-wide 'time' primitive representation, which + consists of two integers: seconds since epoch and nanoseconds since + seconds. Time instances are mutable. + """ + __slots__ = ['secs', 'nsecs'] + def __init__(self, secs=0, nsecs=0): + """ + Constructor: secs and nsecs are integers. You may prefer to use the static L{from_sec()} factory + method instead. + + :param secs: seconds since epoch, ``int`` + :param nsecs: nanoseconds since seconds (since epoch), ``int`` + """ + super(Time, self).__init__(secs, nsecs) + if self.secs < 0: + raise TypeError("time values must be positive") + + def __getstate__(self): + """ + support for Python pickling + """ + return [self.secs, self.nsecs] + + def __setstate__(self, state): + """ + support for Python pickling + """ + self.secs, self.nsecs = state + + def to_time(self): + """ + Get Time in time.time() format. alias of L{to_sec()} + + :returns: time in floating point secs (time.time() format), ``float`` + """ + return self.to_sec() + + def __hash__(self): + return super(Time, self).__hash__() + + def __repr__(self): + return "genpy.Time[%d]"%self.to_nsec() + + def __add__(self, other): + """ + Add duration to this time + + :param other: :class:`Duration` + """ + if not isinstance(other, Duration): + return NotImplemented + return self.__class__(self.secs + other.secs, self.nsecs + other.nsecs) + + __radd__ = __add__ + + def __sub__(self, other): + """ + Subtract time or duration from this time + :param other: :class:`Duration`/:class:`Time` + :returns: :class:`Duration` if other is a :class:`Time`, :class:`Time` if other is a :class:`Duration` + """ + if isinstance(other, Time): + return Duration(self.secs - other.secs, self.nsecs - other.nsecs) + elif isinstance(other, Duration): + return self.__class__(self.secs - other.secs, self.nsecs - other.nsecs) + else: + return NotImplemented + + def __cmp__(self, other): + """ + Compare to another time + :param other: :class:`Time` + """ + if not isinstance(other, Time): + raise TypeError("cannot compare to non-Time") + a = self.to_nsec() + b = other.to_nsec() + return (a > b) - (a < b) + + def __eq__(self, other): + """ + Equals test for Time. Comparison assumes that both time + instances are in canonical representation; only compares fields. + + :param other: :class:`Time` + """ + if not isinstance(other, Time): + return False + return self.secs == other.secs and self.nsecs == other.nsecs + +class Duration(TVal): + """ + Duration represents the ROS 'duration' primitive, which consists + of two integers: seconds and nanoseconds. The Duration class + allows you to add and subtract Duration instances, including + adding and subtracting from :class:`Time` instances. + """ + __slots__ = ['secs', 'nsecs'] + def __init__(self, secs=0, nsecs=0): + """ + Create new Duration instance. secs and nsecs are integers and correspond to the ROS 'duration' primitive. + + :param secs: seconds, ``int`` + :param nsecs: nanoseconds, ``int`` + """ + super(Duration, self).__init__(secs, nsecs) + + def __getstate__(self): + """ + support for Python pickling + """ + return [self.secs, self.nsecs] + + def __setstate__(self, state): + """ + support for Python pickling + """ + self.secs, self.nsecs = state + + def __hash__(self): + return super(Duration, self).__hash__() + + def __repr__(self): + return "genpy.Duration[%d]"%self.to_nsec() + + def __neg__(self): + """ + :returns: Negative value of this :class:`Duration` + """ + return self.__class__(-self.secs, -self.nsecs) + def __abs__(self): + """ + Absolute value of this duration + :returns: positive :class:`Duration` + """ + if self.secs >= 0: + return self + return self.__neg__() + + def __add__(self, other): + """ + Add duration to this duration, or this duration to a time, creating a new time value as a result. + :param other: duration or time, ``Duration``/``Time`` + :returns: :class:`Duration` if other is a :class:`Duration` + instance, :class:`Time` if other is a :class:`Time` + """ + if isinstance(other, Duration): + return self.__class__(self.secs+other.secs, self.nsecs+other.nsecs) + else: + return NotImplemented + + __radd__ = __add__ + + def __sub__(self, other): + """ + Subtract duration from this duration, returning a new duration + :param other: duration + :returns: :class:`Duration` + """ + if not isinstance(other, Duration): + return NotImplemented + return self.__class__(self.secs-other.secs, self.nsecs-other.nsecs) + + def __mul__(self, val): + """ + Multiply this duration by an integer or float + :param val: multiplication factor, ``int/float`` + :returns: :class:`Duration` multiplied by val + """ + if isinstance(val, numbers.Integral): + return self.__class__(self.secs * val, self.nsecs * val) + elif isinstance(val, numbers.Real): + return self.__class__.from_sec(self.to_sec() * val) + else: + return NotImplemented + + __rmul__ = __mul__ + + def __floordiv__(self, val): + """ + Floor divide this duration by an integer or float + :param val: division factor ``int/float``, or :class:`Duration` to divide by + :returns: :class:`Duration` divided by val - a :class:`Duration` if divided by a number, or a number if divided by a duration + """ + if isinstance(val, numbers.Integral) or isinstance(val, numbers.Real): + return self.__class__.from_sec(self.to_sec() // val) + elif isinstance(val, Duration): + return int(self.to_sec() // val.to_sec()) + else: + return NotImplemented + + def __div__(self, val): + """ + Divide this duration by an integer or float + :param val: division factor ``int/float``, or :class:`Duration` to divide by + :returns: :class:`Duration` divided by val - a :class:`Duration` if divided by a number, or a number if divided by a duration + """ + if isinstance(val, numbers.Integral) or isinstance(val, numbers.Real): + return self.__class__.from_sec(self.to_sec() / val) + elif isinstance(val, Duration): + return self.to_sec() / val.to_sec() + else: + return NotImplemented + + def __truediv__(self, val): + """ + Divide this duration by an integer or float + :param val: division factor ``int/float``, or :class:`Duration` to divide by + :returns: :class:`Duration` divided by val - a :class:`Duration` if divided by a number, or a number if divided by a duration + """ + if isinstance(val, numbers.Real): + return self.__class__.from_sec(self.to_sec() / val) + elif isinstance(val, Duration): + return self.to_sec() / val.to_sec() + else: + return NotImplemented + + def __mod__(self, val): + """ + Find the remainder when dividing this Duration by another Duration + :returns: :class:`Duration` The remaining time after the division + """ + if isinstance(val, Duration): + return self.__class__.from_sec(self.to_sec() % val.to_sec()) + else: + return NotImplemented + + def __divmod__(self, val): + """ + Implements the builtin divmod for a pair of Durations + :returns: ``int`` The floored result of the division + :returns: :class:`Duration` The remaining time after the division + """ + if isinstance(val, Duration): + quotient, remainder = divmod(self.to_sec(), val.to_sec()) + return int(quotient), self.__class__.from_sec(remainder) + else: + return NotImplemented + + def __cmp__(self, other): + if not isinstance(other, Duration): + raise TypeError("Cannot compare to non-Duration") + a = self.to_nsec() + b = other.to_nsec() + return (a > b) - (a < b) + + def __eq__(self, other): + if not isinstance(other, Duration): + return False + return self.secs == other.secs and self.nsecs == other.nsecs diff --git a/geometry_msgs/__init__.py b/tiny_tf/geometry_msgs/__init__.py similarity index 100% rename from geometry_msgs/__init__.py rename to tiny_tf/geometry_msgs/__init__.py diff --git a/geometry_msgs/msg/_Accel.py b/tiny_tf/geometry_msgs/msg/_Accel.py similarity index 100% rename from geometry_msgs/msg/_Accel.py rename to tiny_tf/geometry_msgs/msg/_Accel.py diff --git a/geometry_msgs/msg/_AccelStamped.py b/tiny_tf/geometry_msgs/msg/_AccelStamped.py similarity index 100% rename from geometry_msgs/msg/_AccelStamped.py rename to tiny_tf/geometry_msgs/msg/_AccelStamped.py diff --git a/geometry_msgs/msg/_AccelWithCovariance.py b/tiny_tf/geometry_msgs/msg/_AccelWithCovariance.py similarity index 100% rename from geometry_msgs/msg/_AccelWithCovariance.py rename to tiny_tf/geometry_msgs/msg/_AccelWithCovariance.py diff --git a/geometry_msgs/msg/_AccelWithCovarianceStamped.py b/tiny_tf/geometry_msgs/msg/_AccelWithCovarianceStamped.py similarity index 100% rename from geometry_msgs/msg/_AccelWithCovarianceStamped.py rename to tiny_tf/geometry_msgs/msg/_AccelWithCovarianceStamped.py diff --git a/geometry_msgs/msg/_Inertia.py b/tiny_tf/geometry_msgs/msg/_Inertia.py similarity index 100% rename from geometry_msgs/msg/_Inertia.py rename to tiny_tf/geometry_msgs/msg/_Inertia.py diff --git a/geometry_msgs/msg/_InertiaStamped.py b/tiny_tf/geometry_msgs/msg/_InertiaStamped.py similarity index 100% rename from geometry_msgs/msg/_InertiaStamped.py rename to tiny_tf/geometry_msgs/msg/_InertiaStamped.py diff --git a/geometry_msgs/msg/_Point.py b/tiny_tf/geometry_msgs/msg/_Point.py similarity index 100% rename from geometry_msgs/msg/_Point.py rename to tiny_tf/geometry_msgs/msg/_Point.py diff --git a/geometry_msgs/msg/_Point32.py b/tiny_tf/geometry_msgs/msg/_Point32.py similarity index 100% rename from geometry_msgs/msg/_Point32.py rename to tiny_tf/geometry_msgs/msg/_Point32.py diff --git a/geometry_msgs/msg/_PointStamped.py b/tiny_tf/geometry_msgs/msg/_PointStamped.py similarity index 100% rename from geometry_msgs/msg/_PointStamped.py rename to tiny_tf/geometry_msgs/msg/_PointStamped.py diff --git a/geometry_msgs/msg/_Polygon.py b/tiny_tf/geometry_msgs/msg/_Polygon.py similarity index 100% rename from geometry_msgs/msg/_Polygon.py rename to tiny_tf/geometry_msgs/msg/_Polygon.py diff --git a/geometry_msgs/msg/_PolygonStamped.py b/tiny_tf/geometry_msgs/msg/_PolygonStamped.py similarity index 100% rename from geometry_msgs/msg/_PolygonStamped.py rename to tiny_tf/geometry_msgs/msg/_PolygonStamped.py diff --git a/geometry_msgs/msg/_Pose.py b/tiny_tf/geometry_msgs/msg/_Pose.py similarity index 100% rename from geometry_msgs/msg/_Pose.py rename to tiny_tf/geometry_msgs/msg/_Pose.py diff --git a/geometry_msgs/msg/_Pose2D.py b/tiny_tf/geometry_msgs/msg/_Pose2D.py similarity index 100% rename from geometry_msgs/msg/_Pose2D.py rename to tiny_tf/geometry_msgs/msg/_Pose2D.py diff --git a/geometry_msgs/msg/_PoseArray.py b/tiny_tf/geometry_msgs/msg/_PoseArray.py similarity index 100% rename from geometry_msgs/msg/_PoseArray.py rename to tiny_tf/geometry_msgs/msg/_PoseArray.py diff --git a/geometry_msgs/msg/_PoseStamped.py b/tiny_tf/geometry_msgs/msg/_PoseStamped.py similarity index 100% rename from geometry_msgs/msg/_PoseStamped.py rename to tiny_tf/geometry_msgs/msg/_PoseStamped.py diff --git a/geometry_msgs/msg/_PoseWithCovariance.py b/tiny_tf/geometry_msgs/msg/_PoseWithCovariance.py similarity index 100% rename from geometry_msgs/msg/_PoseWithCovariance.py rename to tiny_tf/geometry_msgs/msg/_PoseWithCovariance.py diff --git a/geometry_msgs/msg/_PoseWithCovarianceStamped.py b/tiny_tf/geometry_msgs/msg/_PoseWithCovarianceStamped.py similarity index 100% rename from geometry_msgs/msg/_PoseWithCovarianceStamped.py rename to tiny_tf/geometry_msgs/msg/_PoseWithCovarianceStamped.py diff --git a/geometry_msgs/msg/_Quaternion.py b/tiny_tf/geometry_msgs/msg/_Quaternion.py similarity index 100% rename from geometry_msgs/msg/_Quaternion.py rename to tiny_tf/geometry_msgs/msg/_Quaternion.py diff --git a/geometry_msgs/msg/_QuaternionStamped.py b/tiny_tf/geometry_msgs/msg/_QuaternionStamped.py similarity index 100% rename from geometry_msgs/msg/_QuaternionStamped.py rename to tiny_tf/geometry_msgs/msg/_QuaternionStamped.py diff --git a/geometry_msgs/msg/_Transform.py b/tiny_tf/geometry_msgs/msg/_Transform.py similarity index 100% rename from geometry_msgs/msg/_Transform.py rename to tiny_tf/geometry_msgs/msg/_Transform.py diff --git a/geometry_msgs/msg/_TransformStamped.py b/tiny_tf/geometry_msgs/msg/_TransformStamped.py similarity index 100% rename from geometry_msgs/msg/_TransformStamped.py rename to tiny_tf/geometry_msgs/msg/_TransformStamped.py diff --git a/geometry_msgs/msg/_Twist.py b/tiny_tf/geometry_msgs/msg/_Twist.py similarity index 100% rename from geometry_msgs/msg/_Twist.py rename to tiny_tf/geometry_msgs/msg/_Twist.py diff --git a/geometry_msgs/msg/_TwistStamped.py b/tiny_tf/geometry_msgs/msg/_TwistStamped.py similarity index 100% rename from geometry_msgs/msg/_TwistStamped.py rename to tiny_tf/geometry_msgs/msg/_TwistStamped.py diff --git a/geometry_msgs/msg/_TwistWithCovariance.py b/tiny_tf/geometry_msgs/msg/_TwistWithCovariance.py similarity index 100% rename from geometry_msgs/msg/_TwistWithCovariance.py rename to tiny_tf/geometry_msgs/msg/_TwistWithCovariance.py diff --git a/geometry_msgs/msg/_TwistWithCovarianceStamped.py b/tiny_tf/geometry_msgs/msg/_TwistWithCovarianceStamped.py similarity index 100% rename from geometry_msgs/msg/_TwistWithCovarianceStamped.py rename to tiny_tf/geometry_msgs/msg/_TwistWithCovarianceStamped.py diff --git a/geometry_msgs/msg/_Vector3.py b/tiny_tf/geometry_msgs/msg/_Vector3.py similarity index 100% rename from geometry_msgs/msg/_Vector3.py rename to tiny_tf/geometry_msgs/msg/_Vector3.py diff --git a/geometry_msgs/msg/_Vector3Stamped.py b/tiny_tf/geometry_msgs/msg/_Vector3Stamped.py similarity index 100% rename from geometry_msgs/msg/_Vector3Stamped.py rename to tiny_tf/geometry_msgs/msg/_Vector3Stamped.py diff --git a/geometry_msgs/msg/_Wrench.py b/tiny_tf/geometry_msgs/msg/_Wrench.py similarity index 100% rename from geometry_msgs/msg/_Wrench.py rename to tiny_tf/geometry_msgs/msg/_Wrench.py diff --git a/geometry_msgs/msg/_WrenchStamped.py b/tiny_tf/geometry_msgs/msg/_WrenchStamped.py similarity index 100% rename from geometry_msgs/msg/_WrenchStamped.py rename to tiny_tf/geometry_msgs/msg/_WrenchStamped.py diff --git a/geometry_msgs/msg/__init__.py b/tiny_tf/geometry_msgs/msg/__init__.py similarity index 100% rename from geometry_msgs/msg/__init__.py rename to tiny_tf/geometry_msgs/msg/__init__.py diff --git a/tiny_tf/std_msgs/__init__.py b/tiny_tf/std_msgs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tiny_tf/std_msgs/msg/_Bool.py b/tiny_tf/std_msgs/msg/_Bool.py new file mode 100644 index 0000000..37887f1 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Bool.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Bool.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Bool(): + _md5sum = "8b94c1b53db61fb6aed406028ad6332a" + _type = "std_msgs/Bool" + _has_header = False #flag to mark the presence of a Header object + _full_text = """bool data""" + __slots__ = ['data'] + _slot_types = ['bool'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Bool, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = False + else: + self.data = False + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Byte.py b/tiny_tf/std_msgs/msg/_Byte.py new file mode 100644 index 0000000..ec80cdf --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Byte.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Byte.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Byte(): + _md5sum = "ad736a2e8818154c487bb80fe42ce43b" + _type = "std_msgs/Byte" + _has_header = False #flag to mark the presence of a Header object + _full_text = """byte data +""" + __slots__ = ['data'] + _slot_types = ['byte'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Byte, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_ByteMultiArray.py b/tiny_tf/std_msgs/msg/_ByteMultiArray.py new file mode 100644 index 0000000..7685318 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_ByteMultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/ByteMultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class ByteMultiArray(): + _md5sum = "70ea476cbcfd65ac2f68f3cda1e891fe" + _type = "std_msgs/ByteMultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +byte[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','byte[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(ByteMultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Char.py b/tiny_tf/std_msgs/msg/_Char.py new file mode 100644 index 0000000..a9c2f4e --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Char.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Char.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Char(): + _md5sum = "1bf77f25acecdedba0e224b162199717" + _type = "std_msgs/Char" + _has_header = False #flag to mark the presence of a Header object + _full_text = """char data""" + __slots__ = ['data'] + _slot_types = ['char'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Char, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_ColorRGBA.py b/tiny_tf/std_msgs/msg/_ColorRGBA.py new file mode 100644 index 0000000..5f709da --- /dev/null +++ b/tiny_tf/std_msgs/msg/_ColorRGBA.py @@ -0,0 +1,56 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/ColorRGBA.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class ColorRGBA(): + _md5sum = "a29a96539573343b1310c73607334b00" + _type = "std_msgs/ColorRGBA" + _has_header = False #flag to mark the presence of a Header object + _full_text = """float32 r +float32 g +float32 b +float32 a +""" + __slots__ = ['r','g','b','a'] + _slot_types = ['float32','float32','float32','float32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + r,g,b,a + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(ColorRGBA, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.r is None: + self.r = 0. + if self.g is None: + self.g = 0. + if self.b is None: + self.b = 0. + if self.a is None: + self.a = 0. + else: + self.r = 0. + self.g = 0. + self.b = 0. + self.a = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Duration.py b/tiny_tf/std_msgs/msg/_Duration.py new file mode 100644 index 0000000..3c4c87c --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Duration.py @@ -0,0 +1,45 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Duration.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + + +class Duration(): + _md5sum = "3e286caf4241d664e55f3ad380e2ae46" + _type = "std_msgs/Duration" + _has_header = False #flag to mark the presence of a Header object + _full_text = """duration data +""" + __slots__ = ['data'] + _slot_types = ['duration'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Duration, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = genpy.Duration() + else: + self.data = genpy.Duration() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Empty.py b/tiny_tf/std_msgs/msg/_Empty.py new file mode 100644 index 0000000..a0fd52f --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Empty.py @@ -0,0 +1,38 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Empty.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Empty(): + _md5sum = "d41d8cd98f00b204e9800998ecf8427e" + _type = "std_msgs/Empty" + _has_header = False #flag to mark the presence of a Header object + _full_text = """""" + __slots__ = [] + _slot_types = [] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Empty, self).__init__(*args, **kwds) + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Float32.py b/tiny_tf/std_msgs/msg/_Float32.py new file mode 100644 index 0000000..cd59c58 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Float32.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Float32.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Float32(): + _md5sum = "73fcbf46b49191e672908e50842a83d4" + _type = "std_msgs/Float32" + _has_header = False #flag to mark the presence of a Header object + _full_text = """float32 data""" + __slots__ = ['data'] + _slot_types = ['float32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Float32, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0. + else: + self.data = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Float32MultiArray.py b/tiny_tf/std_msgs/msg/_Float32MultiArray.py new file mode 100644 index 0000000..3c05495 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Float32MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Float32MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Float32MultiArray(): + _md5sum = "6a40e0ffa6a17a503ac3f8616991b1f6" + _type = "std_msgs/Float32MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +float32[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','float32[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Float32MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Float64.py b/tiny_tf/std_msgs/msg/_Float64.py new file mode 100644 index 0000000..70664b5 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Float64.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Float64.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Float64(): + _md5sum = "fdb28210bfa9d7c91146260178d9a584" + _type = "std_msgs/Float64" + _has_header = False #flag to mark the presence of a Header object + _full_text = """float64 data""" + __slots__ = ['data'] + _slot_types = ['float64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Float64, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0. + else: + self.data = 0. + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Float64MultiArray.py b/tiny_tf/std_msgs/msg/_Float64MultiArray.py new file mode 100644 index 0000000..328f8df --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Float64MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Float64MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Float64MultiArray(): + _md5sum = "4b7d974086d4060e7db4613a7e6c3ba4" + _type = "std_msgs/Float64MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +float64[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','float64[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Float64MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Header.py b/tiny_tf/std_msgs/msg/_Header.py new file mode 100644 index 0000000..857bd94 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Header.py @@ -0,0 +1,63 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Header.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + + +class Header(): + _md5sum = "2176decaecbce78abc3b96ef049fabed" + _type = "std_msgs/Header" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Standard metadata for higher-level stamped data types. +# This is generally used to communicate timestamped data +# in a particular coordinate frame. +# +# sequence ID: consecutively increasing ID +uint32 seq +#Two-integer timestamp that is expressed as: +# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs') +# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs') +# time-handling sugar is provided by the client library +time stamp +#Frame this data is associated with +string frame_id +""" + __slots__ = ['seq','stamp','frame_id'] + _slot_types = ['uint32','time','string'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + seq,stamp,frame_id + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Header, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.seq is None: + self.seq = 0 + if self.stamp is None: + self.stamp = genpy.Time() + if self.frame_id is None: + self.frame_id = '' + else: + self.seq = 0 + self.stamp = genpy.Time() + self.frame_id = '' + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int16.py b/tiny_tf/std_msgs/msg/_Int16.py new file mode 100644 index 0000000..15afccf --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int16.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int16.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Int16(): + _md5sum = "8524586e34fbd7cb1c08c5f5f1ca0e57" + _type = "std_msgs/Int16" + _has_header = False #flag to mark the presence of a Header object + _full_text = """int16 data +""" + __slots__ = ['data'] + _slot_types = ['int16'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int16, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int16MultiArray.py b/tiny_tf/std_msgs/msg/_Int16MultiArray.py new file mode 100644 index 0000000..f740dc3 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int16MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int16MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Int16MultiArray(): + _md5sum = "d9338d7f523fcb692fae9d0a0e9f067c" + _type = "std_msgs/Int16MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +int16[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','int16[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int16MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int32.py b/tiny_tf/std_msgs/msg/_Int32.py new file mode 100644 index 0000000..eabf465 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int32.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int32.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Int32(): + _md5sum = "da5909fbe378aeaf85e547e830cc1bb7" + _type = "std_msgs/Int32" + _has_header = False #flag to mark the presence of a Header object + _full_text = """int32 data""" + __slots__ = ['data'] + _slot_types = ['int32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int32, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int32MultiArray.py b/tiny_tf/std_msgs/msg/_Int32MultiArray.py new file mode 100644 index 0000000..82f40e4 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int32MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int32MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Int32MultiArray(): + _md5sum = "1d99f79f8b325b44fee908053e9c945b" + _type = "std_msgs/Int32MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +int32[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','int32[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int32MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int64.py b/tiny_tf/std_msgs/msg/_Int64.py new file mode 100644 index 0000000..9fd1282 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int64.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int64.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Int64(): + _md5sum = "34add168574510e6e17f5d23ecc077ef" + _type = "std_msgs/Int64" + _has_header = False #flag to mark the presence of a Header object + _full_text = """int64 data""" + __slots__ = ['data'] + _slot_types = ['int64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int64, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int64MultiArray.py b/tiny_tf/std_msgs/msg/_Int64MultiArray.py new file mode 100644 index 0000000..c37e8ce --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int64MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int64MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Int64MultiArray(): + _md5sum = "54865aa6c65be0448113a2afc6a49270" + _type = "std_msgs/Int64MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +int64[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','int64[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int64MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int8.py b/tiny_tf/std_msgs/msg/_Int8.py new file mode 100644 index 0000000..624f0b6 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int8.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int8.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class Int8(): + _md5sum = "27ffa0c9c4b8fb8492252bcad9e5c57b" + _type = "std_msgs/Int8" + _has_header = False #flag to mark the presence of a Header object + _full_text = """int8 data +""" + __slots__ = ['data'] + _slot_types = ['int8'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int8, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Int8MultiArray.py b/tiny_tf/std_msgs/msg/_Int8MultiArray.py new file mode 100644 index 0000000..7db631b --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Int8MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Int8MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class Int8MultiArray(): + _md5sum = "d7c1af35a1b4781bbe79e03dd94b7c13" + _type = "std_msgs/Int8MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +int8[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','int8[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Int8MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_MultiArrayDimension.py b/tiny_tf/std_msgs/msg/_MultiArrayDimension.py new file mode 100644 index 0000000..1825077 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_MultiArrayDimension.py @@ -0,0 +1,51 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/MultiArrayDimension.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class MultiArrayDimension(): + _md5sum = "4cd0c83a8683deae40ecdac60e53bfa8" + _type = "std_msgs/MultiArrayDimension" + _has_header = False #flag to mark the presence of a Header object + _full_text = """string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['label','size','stride'] + _slot_types = ['string','uint32','uint32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + label,size,stride + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(MultiArrayDimension, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.label is None: + self.label = '' + if self.size is None: + self.size = 0 + if self.stride is None: + self.stride = 0 + else: + self.label = '' + self.size = 0 + self.stride = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_MultiArrayLayout.py b/tiny_tf/std_msgs/msg/_MultiArrayLayout.py new file mode 100644 index 0000000..a0022a4 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_MultiArrayLayout.py @@ -0,0 +1,78 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/MultiArrayLayout.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class MultiArrayLayout(): + _md5sum = "0fed2a11c13e11c5571b4e2a995a91a3" + _type = "std_msgs/MultiArrayLayout" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['dim','data_offset'] + _slot_types = ['std_msgs/MultiArrayDimension[]','uint32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + dim,data_offset + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(MultiArrayLayout, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.dim is None: + self.dim = [] + if self.data_offset is None: + self.data_offset = 0 + else: + self.dim = [] + self.data_offset = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_String.py b/tiny_tf/std_msgs/msg/_String.py new file mode 100644 index 0000000..96a04af --- /dev/null +++ b/tiny_tf/std_msgs/msg/_String.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/String.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class String(): + _md5sum = "992ce8a1687cec8c8bd883ec73ca41d1" + _type = "std_msgs/String" + _has_header = False #flag to mark the presence of a Header object + _full_text = """string data +""" + __slots__ = ['data'] + _slot_types = ['string'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(String, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = '' + else: + self.data = '' + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_Time.py b/tiny_tf/std_msgs/msg/_Time.py new file mode 100644 index 0000000..187d749 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_Time.py @@ -0,0 +1,45 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/Time.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + + +class Time(): + _md5sum = "cd7166c74c552c311fbcc2fe5a7bc289" + _type = "std_msgs/Time" + _has_header = False #flag to mark the presence of a Header object + _full_text = """time data +""" + __slots__ = ['data'] + _slot_types = ['time'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(Time, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = genpy.Time() + else: + self.data = genpy.Time() + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt16.py b/tiny_tf/std_msgs/msg/_UInt16.py new file mode 100644 index 0000000..9d960e7 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt16.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt16.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class UInt16(): + _md5sum = "1df79edf208b629fe6b81923a544552d" + _type = "std_msgs/UInt16" + _has_header = False #flag to mark the presence of a Header object + _full_text = """uint16 data +""" + __slots__ = ['data'] + _slot_types = ['uint16'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt16, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt16MultiArray.py b/tiny_tf/std_msgs/msg/_UInt16MultiArray.py new file mode 100644 index 0000000..fa86042 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt16MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt16MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class UInt16MultiArray(): + _md5sum = "52f264f1c973c4b73790d384c6cb4484" + _type = "std_msgs/UInt16MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +uint16[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','uint16[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt16MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt32.py b/tiny_tf/std_msgs/msg/_UInt32.py new file mode 100644 index 0000000..746b507 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt32.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt32.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class UInt32(): + _md5sum = "304a39449588c7f8ce2df6e8001c5fce" + _type = "std_msgs/UInt32" + _has_header = False #flag to mark the presence of a Header object + _full_text = """uint32 data""" + __slots__ = ['data'] + _slot_types = ['uint32'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt32, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt32MultiArray.py b/tiny_tf/std_msgs/msg/_UInt32MultiArray.py new file mode 100644 index 0000000..fc0f781 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt32MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt32MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class UInt32MultiArray(): + _md5sum = "4d6a180abc9be191b96a7eda6c8a233d" + _type = "std_msgs/UInt32MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +uint32[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','uint32[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt32MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt64.py b/tiny_tf/std_msgs/msg/_UInt64.py new file mode 100644 index 0000000..6bbecf9 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt64.py @@ -0,0 +1,43 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt64.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class UInt64(): + _md5sum = "1b2a79973e8bf53d7b53acb71299cb57" + _type = "std_msgs/UInt64" + _has_header = False #flag to mark the presence of a Header object + _full_text = """uint64 data""" + __slots__ = ['data'] + _slot_types = ['uint64'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt64, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt64MultiArray.py b/tiny_tf/std_msgs/msg/_UInt64MultiArray.py new file mode 100644 index 0000000..9b66cc0 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt64MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt64MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class UInt64MultiArray(): + _md5sum = "6088f127afb1d6c72927aa1247e945af" + _type = "std_msgs/UInt64MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +uint64[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','uint64[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt64MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = [] + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = [] + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt8.py b/tiny_tf/std_msgs/msg/_UInt8.py new file mode 100644 index 0000000..5e07e02 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt8.py @@ -0,0 +1,44 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt8.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + + +class UInt8(): + _md5sum = "7c8164229e7d2c17eb95e9231617fdee" + _type = "std_msgs/UInt8" + _has_header = False #flag to mark the presence of a Header object + _full_text = """uint8 data +""" + __slots__ = ['data'] + _slot_types = ['uint8'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt8, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.data is None: + self.data = 0 + else: + self.data = 0 + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/_UInt8MultiArray.py b/tiny_tf/std_msgs/msg/_UInt8MultiArray.py new file mode 100644 index 0000000..4477bc7 --- /dev/null +++ b/tiny_tf/std_msgs/msg/_UInt8MultiArray.py @@ -0,0 +1,87 @@ +# This Python file uses the following encoding: utf-8 +"""Based on a ROS-generated file from std_msgs/UInt8MultiArray.msg. Do not edit.""" +import sys +python3 = True if sys.hexversion > 0x03000000 else False + +import struct + +import std_msgs.msg + +class UInt8MultiArray(): + _md5sum = "82373f1612381bb6ee473b5cd6f5d89c" + _type = "std_msgs/UInt8MultiArray" + _has_header = False #flag to mark the presence of a Header object + _full_text = """# Please look at the MultiArrayLayout message definition for +# documentation on all multiarrays. + +MultiArrayLayout layout # specification of data layout +uint8[] data # array of data + + +================================================================================ +MSG: std_msgs/MultiArrayLayout +# The multiarray declares a generic multi-dimensional array of a +# particular data type. Dimensions are ordered from outer most +# to inner most. + +MultiArrayDimension[] dim # Array of dimension properties +uint32 data_offset # padding elements at front of data + +# Accessors should ALWAYS be written in terms of dimension stride +# and specified outer-most dimension first. +# +# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k] +# +# A standard, 3-channel 640x480 image with interleaved color channels +# would be specified as: +# +# dim[0].label = "height" +# dim[0].size = 480 +# dim[0].stride = 3*640*480 = 921600 (note dim[0] stride is just size of image) +# dim[1].label = "width" +# dim[1].size = 640 +# dim[1].stride = 3*640 = 1920 +# dim[2].label = "channel" +# dim[2].size = 3 +# dim[2].stride = 3 +# +# multiarray(i,j,k) refers to the ith row, jth column, and kth channel. + +================================================================================ +MSG: std_msgs/MultiArrayDimension +string label # label of given dimension +uint32 size # size of given dimension (in type units) +uint32 stride # stride of given dimension""" + __slots__ = ['layout','data'] + _slot_types = ['std_msgs/MultiArrayLayout','uint8[]'] + + def __init__(self, *args, **kwds): + """ + Constructor. Any message fields that are implicitly/explicitly + set to None will be assigned a default value. The recommend + use is keyword arguments as this is more robust to future message + changes. You cannot mix in-order arguments and keyword arguments. + + The available fields are: + layout,data + + :param args: complete set of field values, in .msg order + :param kwds: use keyword arguments corresponding to message field names + to set specific fields. + """ + if args or kwds: + super(UInt8MultiArray, self).__init__(*args, **kwds) + #message fields cannot be None, assign default values for those that are + if self.layout is None: + self.layout = std_msgs.msg.MultiArrayLayout() + if self.data is None: + self.data = b'' + else: + self.layout = std_msgs.msg.MultiArrayLayout() + self.data = b'' + + def _get_types(self): + """ + internal API method + """ + return self._slot_types \ No newline at end of file diff --git a/tiny_tf/std_msgs/msg/__init__.py b/tiny_tf/std_msgs/msg/__init__.py new file mode 100644 index 0000000..71b6daa --- /dev/null +++ b/tiny_tf/std_msgs/msg/__init__.py @@ -0,0 +1,32 @@ +from ._Bool import * +from ._Byte import * +from ._ByteMultiArray import * +from ._Char import * +from ._ColorRGBA import * +from ._Duration import * +from ._Empty import * +from ._Float32 import * +from ._Float32MultiArray import * +from ._Float64 import * +from ._Float64MultiArray import * +from ._Header import * +from ._Int16 import * +from ._Int16MultiArray import * +from ._Int32 import * +from ._Int32MultiArray import * +from ._Int64 import * +from ._Int64MultiArray import * +from ._Int8 import * +from ._Int8MultiArray import * +from ._MultiArrayDimension import * +from ._MultiArrayLayout import * +from ._String import * +from ._Time import * +from ._UInt16 import * +from ._UInt16MultiArray import * +from ._UInt32 import * +from ._UInt32MultiArray import * +from ._UInt64 import * +from ._UInt64MultiArray import * +from ._UInt8 import * +from ._UInt8MultiArray import * From 1b366290c058c7a4ea339351b1a5dac749f1fa6e Mon Sep 17 00:00:00 2001 From: Felix von Drigalski Date: Wed, 1 May 2019 15:38:39 +0900 Subject: [PATCH 11/11] Remove ROS Time() --- tiny_tf/std_msgs/msg/_Header.py | 4 ++-- tiny_tf/std_msgs/msg/_Time.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tiny_tf/std_msgs/msg/_Header.py b/tiny_tf/std_msgs/msg/_Header.py index 857bd94..1ab22aa 100644 --- a/tiny_tf/std_msgs/msg/_Header.py +++ b/tiny_tf/std_msgs/msg/_Header.py @@ -48,12 +48,12 @@ def __init__(self, *args, **kwds): if self.seq is None: self.seq = 0 if self.stamp is None: - self.stamp = genpy.Time() + self.stamp = 0 # Time is unused in tiny_tf if self.frame_id is None: self.frame_id = '' else: self.seq = 0 - self.stamp = genpy.Time() + self.stamp = 0 # Time is unused in tiny_tf self.frame_id = '' def _get_types(self): diff --git a/tiny_tf/std_msgs/msg/_Time.py b/tiny_tf/std_msgs/msg/_Time.py index 187d749..ab26f8f 100644 --- a/tiny_tf/std_msgs/msg/_Time.py +++ b/tiny_tf/std_msgs/msg/_Time.py @@ -34,9 +34,9 @@ def __init__(self, *args, **kwds): super(Time, self).__init__(*args, **kwds) #message fields cannot be None, assign default values for those that are if self.data is None: - self.data = genpy.Time() + self.data = 0 # Time is unused in tiny_tf else: - self.data = genpy.Time() + self.data = 0 # Time is unused in tiny_tf def _get_types(self): """