00001 // ***************************************************************************** 00002 // 00003 // Copyright (c) 2016, Southwest Research Institute® (SwRI®) 00004 // All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // * Redistributions of source code must retain the above copyright 00009 // notice, this list of conditions and the following disclaimer. 00010 // * Redistributions in binary form must reproduce the above copyright 00011 // notice, this list of conditions and the following disclaimer in the 00012 // documentation and/or other materials provided with the distribution. 00013 // * Neither the name of Southwest Research Institute® (SwRI®) nor the 00014 // names of its contributors may be used to endorse or promote products 00015 // derived from this software without specific prior written permission. 00016 // 00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY 00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 // 00028 // ***************************************************************************** 00029 #ifndef SWRI_ROUTE_UTIL_ROUTE_H_ 00030 #define SWRI_ROUTE_UTIL_ROUTE_H_ 00031 00032 #include <string> 00033 #include <map> 00034 #include <vector> 00035 00036 #include <boost/lexical_cast.hpp> 00037 00038 #include <marti_nav_msgs/Route.h> 00039 #include <swri_route_util/route_point.h> 00040 00041 namespace swri_route_util 00042 { 00043 // The Route class provides a more friendly interface for working with 00044 // the marti_nav_msgs::Route message. It provides native access to 00045 // known properties and supports fast lookups of points by their ids. 00046 // 00047 // This class is optimized for a combination of simplicity, nice 00048 // syntax, and performance for standard use cases. This means that 00049 // some tradeoffs were made for less common use cases. 00050 // 00051 // In particular, findPointId() may take a long time when called with 00052 // ids that do not exist in the route because of the behind-the-scenes 00053 // caching. If this is an important use case and you are ABSOLUTELY 00054 // sure that the points list has not been modified since the class was 00055 // created from a message, you can avoid this performance hit by 00056 // calling findPointIdConst() instead. 00057 class Route 00058 { 00059 public: 00060 // Create a new empty route. 00061 Route(); 00062 00063 // Create a route from an existing marti_nav_msgs::Route message. 00064 // Warning: If a route or a specific route point contains properties 00065 // with duplicate keys, only one will be kept; the others are 00066 // silently discarded. Don't use non-unique property keys. 00067 Route(const marti_nav_msgs::Route &msg); 00068 00069 // Create a marti_nav_msgs::Route from the route, in place version. 00070 void toMsg(marti_nav_msgs::Route &msg) const; 00071 // Create a marti_nav_msgs::Route from the route, returned as a 00072 // shared pointer. 00073 marti_nav_msgs::RoutePtr toMsgPtr() const; 00074 00075 // The header of the route. This is exposed as field to be 00076 // consistent with typical ROS style. 00077 std_msgs::Header header; 00078 00079 // The points of the route. This is exposed as a field because it's 00080 // much simpler (for me to write and you to use) than trying to 00081 // replicate the entire vector interface. 00082 std::vector<RoutePoint> points; 00083 00084 // A route is considered invalid if it has no points. 00085 bool valid() const; 00086 00087 // Find a point index by its ID. For the common use case of looking 00088 // up valid ids in a static route, this will be very fast. For less 00089 // common cases like looking up valid ids in a route that has been 00090 // modified, it may be slower. It is the slowest when looking up 00091 // many invalid ids in any route. If there are multiple points with 00092 // the requested key, it will return one of the points, but which 00093 // one is undefined. Don't use non-unqiue ids. 00094 bool findPointId(size_t &index, const std::string &id) const; 00095 00096 // Find a point index by its ID, the less safe version. This 00097 // version should only be used on Routes with a valid internal index 00098 // (rebuildPointIndex() was called and points were never added, 00099 // removed, reordered, or changed ids). This version will not 00100 // rebuild the internal point index if an id is not found, so it is 00101 // much faster for repeated invalid lookups. If the "static" 00102 // assumption is violated, this version may incorrectly miss a valid 00103 // id. It will never return a point with a different id than 00104 // requested. Be sure you know what you're doing if you want to use 00105 // this. 00106 bool findPointIdConst(size_t &index, const std::string &id) const; 00107 00108 // Rebuilds the internal point index. This is handled internally 00109 // and exposed for very special use cases, which you probably do not 00110 // need. Be sure you know what you're doing if you want to use this. 00111 void rebuildPointIndex() const; 00112 00113 // Native access to the route "name" property, which is required to 00114 // exist. 00115 std::string name() const; 00116 void setName(const std::string &name); 00117 00118 // Native access to the route "guid" property, which is required to 00119 // exist. 00120 std::string guid() const; 00121 void setGuid(const std::string &guid); 00122 00123 // The following methods provide general purpose access to route 00124 // properties. They will also correctly map to properties that are 00125 // exposed natively. Native methods (e.g. name(), guid()) are 00126 // generally faster and safer and should be preferred when 00127 // available. 00128 00129 // Get a list of all the properties defined for this route, 00130 // including native properties. 00131 std::vector<std::string> getPropertyNames() const; 00132 00133 // Get the value of a property. Returns an empty string if the 00134 // property does not exist. 00135 std::string getProperty(const std::string &name) const; 00136 template <typename T> 00137 00138 // Get the value of a property, lexically cast to a known type. 00139 // Returns the lexical cast of an empty string if the property does 00140 // not exist.. 00141 T getTypedProperty(const std::string &name) const; 00142 00143 // Determine if the specified property is defined for the route. 00144 bool hasProperty(const std::string &name) const; 00145 00146 // Set the value of a property. If the property doesn't exist, it 00147 // is added. 00148 void setProperty(const std::string &name, const std::string &value); 00149 00150 // Delete a property. If the property doesn't exist or is not 00151 // deletable (e.g. name, guid), this method does nothing. 00152 void deleteProperty(const std::string &name); 00153 00154 public: 00155 // The point index maps point ids to their index in the points 00156 // vector. It is mutable because we want to support fast look ups 00157 // on const Routes. 00158 mutable std::map<std::string, size_t> point_index_; 00159 00160 // Map containing generic properties. 00161 std::map<std::string, std::string> properties_; 00162 00163 // Storage for native properties. 00164 std::string guid_; 00165 std::string name_; 00166 }; // class Route 00167 00168 // Typedef shared pointers to make migrating from the message types to 00169 // this interface more convenient. 00170 typedef boost::shared_ptr<Route> RoutePtr; 00171 typedef boost::shared_ptr<Route const> RouteConstPtr; 00172 00173 template<typename T> 00174 inline 00175 T Route::getTypedProperty(const std::string &name) const 00176 { 00177 return boost::lexical_cast<T>(getProperty(name)); 00178 } 00179 } // namespace swri_route_util 00180 00181 #include "route_serializer.h" 00182 00183 #endif // SWRI_ROUTE_UTIL_ROUTE_H_