_StoreCloudActionGoal.py
Go to the documentation of this file.
00001 """autogenerated by genpy from point_cloud_server/StoreCloudActionGoal.msg. Do not edit."""
00002 import sys
00003 python3 = True if sys.hexversion > 0x03000000 else False
00004 import genpy
00005 import struct
00006 
00007 import sensor_msgs.msg
00008 import point_cloud_server.msg
00009 import genpy
00010 import actionlib_msgs.msg
00011 import std_msgs.msg
00012 
00013 class StoreCloudActionGoal(genpy.Message):
00014   _md5sum = "dd766e3b05af6403935d6aed4100baca"
00015   _type = "point_cloud_server/StoreCloudActionGoal"
00016   _has_header = True #flag to mark the presence of a Header object
00017   _full_text = """# ====== DO NOT MODIFY! AUTOGENERATED FROM AN ACTION DEFINITION ======
00018 
00019 Header header
00020 actionlib_msgs/GoalID goal_id
00021 StoreCloudGoal goal
00022 
00023 ================================================================================
00024 MSG: std_msgs/Header
00025 # Standard metadata for higher-level stamped data types.
00026 # This is generally used to communicate timestamped data 
00027 # in a particular coordinate frame.
00028 # 
00029 # sequence ID: consecutively increasing ID 
00030 uint32 seq
00031 #Two-integer timestamp that is expressed as:
00032 # * stamp.secs: seconds (stamp_secs) since epoch
00033 # * stamp.nsecs: nanoseconds since stamp_secs
00034 # time-handling sugar is provided by the client library
00035 time stamp
00036 #Frame this data is associated with
00037 # 0: no frame
00038 # 1: global frame
00039 string frame_id
00040 
00041 ================================================================================
00042 MSG: actionlib_msgs/GoalID
00043 # The stamp should store the time at which this goal was requested.
00044 # It is used by an action server when it tries to preempt all
00045 # goals that were requested before a certain time
00046 time stamp
00047 
00048 # The id provides a way to associate feedback and
00049 # result message with specific goal requests. The id
00050 # specified must be unique.
00051 string id
00052 
00053 
00054 ================================================================================
00055 MSG: point_cloud_server/StoreCloudGoal
00056 # ====== DO NOT MODIFY! AUTOGENERATED FROM AN ACTION DEFINITION ======
00057 # The storage name of the point cloud.
00058 string name
00059 
00060 # The topic on which to capture a point cloud message. 
00061 # If this is empty, then 'cloud' will be used instead.
00062 string topic
00063 
00064 # A point cloud to store.
00065 sensor_msgs/PointCloud2 cloud
00066 
00067 # If not empty, transforms the cloud to this frame before storing.
00068 string storage_frame_id
00069 
00070 # If not empty, transforms the cloud to this frame in the return result.
00071 string result_frame_id
00072 
00073 # A flag to determine whether to reply with the cloud.
00074 int32 action
00075 
00076 # Will get a message on topic, or store cloud.
00077 int32 STORE=0
00078 
00079 # Will get a message on a topic if it is provided, save, and return it;
00080 # otherwise just returns the existing cloud.
00081 int32 GET=1
00082 
00083 # Topic and cloud are ignored, just removes cloud from the server.
00084 int32 CLEAR=2
00085 
00086 
00087 ================================================================================
00088 MSG: sensor_msgs/PointCloud2
00089 # This message holds a collection of N-dimensional points, which may
00090 # contain additional information such as normals, intensity, etc. The
00091 # point data is stored as a binary blob, its layout described by the
00092 # contents of the "fields" array.
00093 
00094 # The point cloud data may be organized 2d (image-like) or 1d
00095 # (unordered). Point clouds organized as 2d images may be produced by
00096 # camera depth sensors such as stereo or time-of-flight.
00097 
00098 # Time of sensor data acquisition, and the coordinate frame ID (for 3d
00099 # points).
00100 Header header
00101 
00102 # 2D structure of the point cloud. If the cloud is unordered, height is
00103 # 1 and width is the length of the point cloud.
00104 uint32 height
00105 uint32 width
00106 
00107 # Describes the channels and their layout in the binary data blob.
00108 PointField[] fields
00109 
00110 bool    is_bigendian # Is this data bigendian?
00111 uint32  point_step   # Length of a point in bytes
00112 uint32  row_step     # Length of a row in bytes
00113 uint8[] data         # Actual point data, size is (row_step*height)
00114 
00115 bool is_dense        # True if there are no invalid points
00116 
00117 ================================================================================
00118 MSG: sensor_msgs/PointField
00119 # This message holds the description of one point entry in the
00120 # PointCloud2 message format.
00121 uint8 INT8    = 1
00122 uint8 UINT8   = 2
00123 uint8 INT16   = 3
00124 uint8 UINT16  = 4
00125 uint8 INT32   = 5
00126 uint8 UINT32  = 6
00127 uint8 FLOAT32 = 7
00128 uint8 FLOAT64 = 8
00129 
00130 string name      # Name of field
00131 uint32 offset    # Offset from start of point struct
00132 uint8  datatype  # Datatype enumeration, see above
00133 uint32 count     # How many elements in the field
00134 
00135 """
00136   __slots__ = ['header','goal_id','goal']
00137   _slot_types = ['std_msgs/Header','actionlib_msgs/GoalID','point_cloud_server/StoreCloudGoal']
00138 
00139   def __init__(self, *args, **kwds):
00140     """
00141     Constructor. Any message fields that are implicitly/explicitly
00142     set to None will be assigned a default value. The recommend
00143     use is keyword arguments as this is more robust to future message
00144     changes.  You cannot mix in-order arguments and keyword arguments.
00145 
00146     The available fields are:
00147        header,goal_id,goal
00148 
00149     :param args: complete set of field values, in .msg order
00150     :param kwds: use keyword arguments corresponding to message field names
00151     to set specific fields.
00152     """
00153     if args or kwds:
00154       super(StoreCloudActionGoal, self).__init__(*args, **kwds)
00155       #message fields cannot be None, assign default values for those that are
00156       if self.header is None:
00157         self.header = std_msgs.msg.Header()
00158       if self.goal_id is None:
00159         self.goal_id = actionlib_msgs.msg.GoalID()
00160       if self.goal is None:
00161         self.goal = point_cloud_server.msg.StoreCloudGoal()
00162     else:
00163       self.header = std_msgs.msg.Header()
00164       self.goal_id = actionlib_msgs.msg.GoalID()
00165       self.goal = point_cloud_server.msg.StoreCloudGoal()
00166 
00167   def _get_types(self):
00168     """
00169     internal API method
00170     """
00171     return self._slot_types
00172 
00173   def serialize(self, buff):
00174     """
00175     serialize message into buffer
00176     :param buff: buffer, ``StringIO``
00177     """
00178     try:
00179       _x = self
00180       buff.write(_struct_3I.pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs))
00181       _x = self.header.frame_id
00182       length = len(_x)
00183       if python3 or type(_x) == unicode:
00184         _x = _x.encode('utf-8')
00185         length = len(_x)
00186       buff.write(struct.pack('<I%ss'%length, length, _x))
00187       _x = self
00188       buff.write(_struct_2I.pack(_x.goal_id.stamp.secs, _x.goal_id.stamp.nsecs))
00189       _x = self.goal_id.id
00190       length = len(_x)
00191       if python3 or type(_x) == unicode:
00192         _x = _x.encode('utf-8')
00193         length = len(_x)
00194       buff.write(struct.pack('<I%ss'%length, length, _x))
00195       _x = self.goal.name
00196       length = len(_x)
00197       if python3 or type(_x) == unicode:
00198         _x = _x.encode('utf-8')
00199         length = len(_x)
00200       buff.write(struct.pack('<I%ss'%length, length, _x))
00201       _x = self.goal.topic
00202       length = len(_x)
00203       if python3 or type(_x) == unicode:
00204         _x = _x.encode('utf-8')
00205         length = len(_x)
00206       buff.write(struct.pack('<I%ss'%length, length, _x))
00207       _x = self
00208       buff.write(_struct_3I.pack(_x.goal.cloud.header.seq, _x.goal.cloud.header.stamp.secs, _x.goal.cloud.header.stamp.nsecs))
00209       _x = self.goal.cloud.header.frame_id
00210       length = len(_x)
00211       if python3 or type(_x) == unicode:
00212         _x = _x.encode('utf-8')
00213         length = len(_x)
00214       buff.write(struct.pack('<I%ss'%length, length, _x))
00215       _x = self
00216       buff.write(_struct_2I.pack(_x.goal.cloud.height, _x.goal.cloud.width))
00217       length = len(self.goal.cloud.fields)
00218       buff.write(_struct_I.pack(length))
00219       for val1 in self.goal.cloud.fields:
00220         _x = val1.name
00221         length = len(_x)
00222         if python3 or type(_x) == unicode:
00223           _x = _x.encode('utf-8')
00224           length = len(_x)
00225         buff.write(struct.pack('<I%ss'%length, length, _x))
00226         _x = val1
00227         buff.write(_struct_IBI.pack(_x.offset, _x.datatype, _x.count))
00228       _x = self
00229       buff.write(_struct_B2I.pack(_x.goal.cloud.is_bigendian, _x.goal.cloud.point_step, _x.goal.cloud.row_step))
00230       _x = self.goal.cloud.data
00231       length = len(_x)
00232       # - if encoded as a list instead, serialize as bytes instead of string
00233       if type(_x) in [list, tuple]:
00234         buff.write(struct.pack('<I%sB'%length, length, *_x))
00235       else:
00236         buff.write(struct.pack('<I%ss'%length, length, _x))
00237       buff.write(_struct_B.pack(self.goal.cloud.is_dense))
00238       _x = self.goal.storage_frame_id
00239       length = len(_x)
00240       if python3 or type(_x) == unicode:
00241         _x = _x.encode('utf-8')
00242         length = len(_x)
00243       buff.write(struct.pack('<I%ss'%length, length, _x))
00244       _x = self.goal.result_frame_id
00245       length = len(_x)
00246       if python3 or type(_x) == unicode:
00247         _x = _x.encode('utf-8')
00248         length = len(_x)
00249       buff.write(struct.pack('<I%ss'%length, length, _x))
00250       buff.write(_struct_i.pack(self.goal.action))
00251     except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(_x))))
00252     except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(_x))))
00253 
00254   def deserialize(self, str):
00255     """
00256     unpack serialized message in str into this message instance
00257     :param str: byte array of serialized message, ``str``
00258     """
00259     try:
00260       if self.header is None:
00261         self.header = std_msgs.msg.Header()
00262       if self.goal_id is None:
00263         self.goal_id = actionlib_msgs.msg.GoalID()
00264       if self.goal is None:
00265         self.goal = point_cloud_server.msg.StoreCloudGoal()
00266       end = 0
00267       _x = self
00268       start = end
00269       end += 12
00270       (_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs,) = _struct_3I.unpack(str[start:end])
00271       start = end
00272       end += 4
00273       (length,) = _struct_I.unpack(str[start:end])
00274       start = end
00275       end += length
00276       if python3:
00277         self.header.frame_id = str[start:end].decode('utf-8')
00278       else:
00279         self.header.frame_id = str[start:end]
00280       _x = self
00281       start = end
00282       end += 8
00283       (_x.goal_id.stamp.secs, _x.goal_id.stamp.nsecs,) = _struct_2I.unpack(str[start:end])
00284       start = end
00285       end += 4
00286       (length,) = _struct_I.unpack(str[start:end])
00287       start = end
00288       end += length
00289       if python3:
00290         self.goal_id.id = str[start:end].decode('utf-8')
00291       else:
00292         self.goal_id.id = str[start:end]
00293       start = end
00294       end += 4
00295       (length,) = _struct_I.unpack(str[start:end])
00296       start = end
00297       end += length
00298       if python3:
00299         self.goal.name = str[start:end].decode('utf-8')
00300       else:
00301         self.goal.name = str[start:end]
00302       start = end
00303       end += 4
00304       (length,) = _struct_I.unpack(str[start:end])
00305       start = end
00306       end += length
00307       if python3:
00308         self.goal.topic = str[start:end].decode('utf-8')
00309       else:
00310         self.goal.topic = str[start:end]
00311       _x = self
00312       start = end
00313       end += 12
00314       (_x.goal.cloud.header.seq, _x.goal.cloud.header.stamp.secs, _x.goal.cloud.header.stamp.nsecs,) = _struct_3I.unpack(str[start:end])
00315       start = end
00316       end += 4
00317       (length,) = _struct_I.unpack(str[start:end])
00318       start = end
00319       end += length
00320       if python3:
00321         self.goal.cloud.header.frame_id = str[start:end].decode('utf-8')
00322       else:
00323         self.goal.cloud.header.frame_id = str[start:end]
00324       _x = self
00325       start = end
00326       end += 8
00327       (_x.goal.cloud.height, _x.goal.cloud.width,) = _struct_2I.unpack(str[start:end])
00328       start = end
00329       end += 4
00330       (length,) = _struct_I.unpack(str[start:end])
00331       self.goal.cloud.fields = []
00332       for i in range(0, length):
00333         val1 = sensor_msgs.msg.PointField()
00334         start = end
00335         end += 4
00336         (length,) = _struct_I.unpack(str[start:end])
00337         start = end
00338         end += length
00339         if python3:
00340           val1.name = str[start:end].decode('utf-8')
00341         else:
00342           val1.name = str[start:end]
00343         _x = val1
00344         start = end
00345         end += 9
00346         (_x.offset, _x.datatype, _x.count,) = _struct_IBI.unpack(str[start:end])
00347         self.goal.cloud.fields.append(val1)
00348       _x = self
00349       start = end
00350       end += 9
00351       (_x.goal.cloud.is_bigendian, _x.goal.cloud.point_step, _x.goal.cloud.row_step,) = _struct_B2I.unpack(str[start:end])
00352       self.goal.cloud.is_bigendian = bool(self.goal.cloud.is_bigendian)
00353       start = end
00354       end += 4
00355       (length,) = _struct_I.unpack(str[start:end])
00356       start = end
00357       end += length
00358       self.goal.cloud.data = str[start:end]
00359       start = end
00360       end += 1
00361       (self.goal.cloud.is_dense,) = _struct_B.unpack(str[start:end])
00362       self.goal.cloud.is_dense = bool(self.goal.cloud.is_dense)
00363       start = end
00364       end += 4
00365       (length,) = _struct_I.unpack(str[start:end])
00366       start = end
00367       end += length
00368       if python3:
00369         self.goal.storage_frame_id = str[start:end].decode('utf-8')
00370       else:
00371         self.goal.storage_frame_id = str[start:end]
00372       start = end
00373       end += 4
00374       (length,) = _struct_I.unpack(str[start:end])
00375       start = end
00376       end += length
00377       if python3:
00378         self.goal.result_frame_id = str[start:end].decode('utf-8')
00379       else:
00380         self.goal.result_frame_id = str[start:end]
00381       start = end
00382       end += 4
00383       (self.goal.action,) = _struct_i.unpack(str[start:end])
00384       return self
00385     except struct.error as e:
00386       raise genpy.DeserializationError(e) #most likely buffer underfill
00387 
00388 
00389   def serialize_numpy(self, buff, numpy):
00390     """
00391     serialize message with numpy array types into buffer
00392     :param buff: buffer, ``StringIO``
00393     :param numpy: numpy python module
00394     """
00395     try:
00396       _x = self
00397       buff.write(_struct_3I.pack(_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs))
00398       _x = self.header.frame_id
00399       length = len(_x)
00400       if python3 or type(_x) == unicode:
00401         _x = _x.encode('utf-8')
00402         length = len(_x)
00403       buff.write(struct.pack('<I%ss'%length, length, _x))
00404       _x = self
00405       buff.write(_struct_2I.pack(_x.goal_id.stamp.secs, _x.goal_id.stamp.nsecs))
00406       _x = self.goal_id.id
00407       length = len(_x)
00408       if python3 or type(_x) == unicode:
00409         _x = _x.encode('utf-8')
00410         length = len(_x)
00411       buff.write(struct.pack('<I%ss'%length, length, _x))
00412       _x = self.goal.name
00413       length = len(_x)
00414       if python3 or type(_x) == unicode:
00415         _x = _x.encode('utf-8')
00416         length = len(_x)
00417       buff.write(struct.pack('<I%ss'%length, length, _x))
00418       _x = self.goal.topic
00419       length = len(_x)
00420       if python3 or type(_x) == unicode:
00421         _x = _x.encode('utf-8')
00422         length = len(_x)
00423       buff.write(struct.pack('<I%ss'%length, length, _x))
00424       _x = self
00425       buff.write(_struct_3I.pack(_x.goal.cloud.header.seq, _x.goal.cloud.header.stamp.secs, _x.goal.cloud.header.stamp.nsecs))
00426       _x = self.goal.cloud.header.frame_id
00427       length = len(_x)
00428       if python3 or type(_x) == unicode:
00429         _x = _x.encode('utf-8')
00430         length = len(_x)
00431       buff.write(struct.pack('<I%ss'%length, length, _x))
00432       _x = self
00433       buff.write(_struct_2I.pack(_x.goal.cloud.height, _x.goal.cloud.width))
00434       length = len(self.goal.cloud.fields)
00435       buff.write(_struct_I.pack(length))
00436       for val1 in self.goal.cloud.fields:
00437         _x = val1.name
00438         length = len(_x)
00439         if python3 or type(_x) == unicode:
00440           _x = _x.encode('utf-8')
00441           length = len(_x)
00442         buff.write(struct.pack('<I%ss'%length, length, _x))
00443         _x = val1
00444         buff.write(_struct_IBI.pack(_x.offset, _x.datatype, _x.count))
00445       _x = self
00446       buff.write(_struct_B2I.pack(_x.goal.cloud.is_bigendian, _x.goal.cloud.point_step, _x.goal.cloud.row_step))
00447       _x = self.goal.cloud.data
00448       length = len(_x)
00449       # - if encoded as a list instead, serialize as bytes instead of string
00450       if type(_x) in [list, tuple]:
00451         buff.write(struct.pack('<I%sB'%length, length, *_x))
00452       else:
00453         buff.write(struct.pack('<I%ss'%length, length, _x))
00454       buff.write(_struct_B.pack(self.goal.cloud.is_dense))
00455       _x = self.goal.storage_frame_id
00456       length = len(_x)
00457       if python3 or type(_x) == unicode:
00458         _x = _x.encode('utf-8')
00459         length = len(_x)
00460       buff.write(struct.pack('<I%ss'%length, length, _x))
00461       _x = self.goal.result_frame_id
00462       length = len(_x)
00463       if python3 or type(_x) == unicode:
00464         _x = _x.encode('utf-8')
00465         length = len(_x)
00466       buff.write(struct.pack('<I%ss'%length, length, _x))
00467       buff.write(_struct_i.pack(self.goal.action))
00468     except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(_x))))
00469     except TypeError as te: self._check_types(ValueError("%s: '%s' when writing '%s'" % (type(te), str(te), str(_x))))
00470 
00471   def deserialize_numpy(self, str, numpy):
00472     """
00473     unpack serialized message in str into this message instance using numpy for array types
00474     :param str: byte array of serialized message, ``str``
00475     :param numpy: numpy python module
00476     """
00477     try:
00478       if self.header is None:
00479         self.header = std_msgs.msg.Header()
00480       if self.goal_id is None:
00481         self.goal_id = actionlib_msgs.msg.GoalID()
00482       if self.goal is None:
00483         self.goal = point_cloud_server.msg.StoreCloudGoal()
00484       end = 0
00485       _x = self
00486       start = end
00487       end += 12
00488       (_x.header.seq, _x.header.stamp.secs, _x.header.stamp.nsecs,) = _struct_3I.unpack(str[start:end])
00489       start = end
00490       end += 4
00491       (length,) = _struct_I.unpack(str[start:end])
00492       start = end
00493       end += length
00494       if python3:
00495         self.header.frame_id = str[start:end].decode('utf-8')
00496       else:
00497         self.header.frame_id = str[start:end]
00498       _x = self
00499       start = end
00500       end += 8
00501       (_x.goal_id.stamp.secs, _x.goal_id.stamp.nsecs,) = _struct_2I.unpack(str[start:end])
00502       start = end
00503       end += 4
00504       (length,) = _struct_I.unpack(str[start:end])
00505       start = end
00506       end += length
00507       if python3:
00508         self.goal_id.id = str[start:end].decode('utf-8')
00509       else:
00510         self.goal_id.id = str[start:end]
00511       start = end
00512       end += 4
00513       (length,) = _struct_I.unpack(str[start:end])
00514       start = end
00515       end += length
00516       if python3:
00517         self.goal.name = str[start:end].decode('utf-8')
00518       else:
00519         self.goal.name = str[start:end]
00520       start = end
00521       end += 4
00522       (length,) = _struct_I.unpack(str[start:end])
00523       start = end
00524       end += length
00525       if python3:
00526         self.goal.topic = str[start:end].decode('utf-8')
00527       else:
00528         self.goal.topic = str[start:end]
00529       _x = self
00530       start = end
00531       end += 12
00532       (_x.goal.cloud.header.seq, _x.goal.cloud.header.stamp.secs, _x.goal.cloud.header.stamp.nsecs,) = _struct_3I.unpack(str[start:end])
00533       start = end
00534       end += 4
00535       (length,) = _struct_I.unpack(str[start:end])
00536       start = end
00537       end += length
00538       if python3:
00539         self.goal.cloud.header.frame_id = str[start:end].decode('utf-8')
00540       else:
00541         self.goal.cloud.header.frame_id = str[start:end]
00542       _x = self
00543       start = end
00544       end += 8
00545       (_x.goal.cloud.height, _x.goal.cloud.width,) = _struct_2I.unpack(str[start:end])
00546       start = end
00547       end += 4
00548       (length,) = _struct_I.unpack(str[start:end])
00549       self.goal.cloud.fields = []
00550       for i in range(0, length):
00551         val1 = sensor_msgs.msg.PointField()
00552         start = end
00553         end += 4
00554         (length,) = _struct_I.unpack(str[start:end])
00555         start = end
00556         end += length
00557         if python3:
00558           val1.name = str[start:end].decode('utf-8')
00559         else:
00560           val1.name = str[start:end]
00561         _x = val1
00562         start = end
00563         end += 9
00564         (_x.offset, _x.datatype, _x.count,) = _struct_IBI.unpack(str[start:end])
00565         self.goal.cloud.fields.append(val1)
00566       _x = self
00567       start = end
00568       end += 9
00569       (_x.goal.cloud.is_bigendian, _x.goal.cloud.point_step, _x.goal.cloud.row_step,) = _struct_B2I.unpack(str[start:end])
00570       self.goal.cloud.is_bigendian = bool(self.goal.cloud.is_bigendian)
00571       start = end
00572       end += 4
00573       (length,) = _struct_I.unpack(str[start:end])
00574       start = end
00575       end += length
00576       self.goal.cloud.data = str[start:end]
00577       start = end
00578       end += 1
00579       (self.goal.cloud.is_dense,) = _struct_B.unpack(str[start:end])
00580       self.goal.cloud.is_dense = bool(self.goal.cloud.is_dense)
00581       start = end
00582       end += 4
00583       (length,) = _struct_I.unpack(str[start:end])
00584       start = end
00585       end += length
00586       if python3:
00587         self.goal.storage_frame_id = str[start:end].decode('utf-8')
00588       else:
00589         self.goal.storage_frame_id = str[start:end]
00590       start = end
00591       end += 4
00592       (length,) = _struct_I.unpack(str[start:end])
00593       start = end
00594       end += length
00595       if python3:
00596         self.goal.result_frame_id = str[start:end].decode('utf-8')
00597       else:
00598         self.goal.result_frame_id = str[start:end]
00599       start = end
00600       end += 4
00601       (self.goal.action,) = _struct_i.unpack(str[start:end])
00602       return self
00603     except struct.error as e:
00604       raise genpy.DeserializationError(e) #most likely buffer underfill
00605 
00606 _struct_I = genpy.struct_I
00607 _struct_IBI = struct.Struct("<IBI")
00608 _struct_B = struct.Struct("<B")
00609 _struct_i = struct.Struct("<i")
00610 _struct_3I = struct.Struct("<3I")
00611 _struct_B2I = struct.Struct("<B2I")
00612 _struct_2I = struct.Struct("<2I")


point_cloud_server
Author(s): Adam Leeper
autogenerated on Mon Oct 6 2014 03:01:14