Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef NAV_2D_UTILS_PLUGIN_MUX_H
00036 #define NAV_2D_UTILS_PLUGIN_MUX_H
00037
00038 #include <ros/ros.h>
00039 #include <pluginlib/class_loader.h>
00040 #include <std_msgs/String.h>
00041 #include <nav_2d_msgs/SwitchPlugin.h>
00042 #include <map>
00043 #include <string>
00044 #include <vector>
00045
00046 namespace nav_2d_utils
00047 {
00058 template<class T>
00059 class PluginMux
00060 {
00061 public:
00072 PluginMux(const std::string& plugin_package, const std::string& plugin_class,
00073 const std::string& parameter_name, const std::string& default_value,
00074 const std::string& ros_name = "current_plugin", const std::string& switch_service_name = "switch_plugin");
00075
00081 void addPlugin(const std::string& plugin_name, const std::string& plugin_class_name);
00082
00089 bool usePlugin(const std::string& name)
00090 {
00091
00092 if (plugins_.count(name) == 0) return false;
00093
00094 if (switch_callback_)
00095 {
00096 switch_callback_(current_plugin_, name);
00097 }
00098
00099
00100 current_plugin_ = name;
00101
00102
00103 std_msgs::String str_msg;
00104 str_msg.data = current_plugin_;
00105 current_plugin_pub_.publish(str_msg);
00106 private_nh_.setParam(ros_name_, current_plugin_);
00107
00108 return true;
00109 }
00110
00115 std::string getCurrentPluginName() const
00116 {
00117 return current_plugin_;
00118 }
00119
00125 bool hasPlugin(const std::string& name) const
00126 {
00127 return plugins_.find(name) != plugins_.end();
00128 }
00129
00135 T& getPlugin(const std::string& name)
00136 {
00137 if (!hasPlugin(name))
00138 throw std::invalid_argument("Plugin not found");
00139 return *plugins_[name];
00140 }
00141
00146 T& getCurrentPlugin()
00147 {
00148 return getPlugin(current_plugin_);
00149 }
00150
00154 std::vector<std::string> getPluginNames() const
00155 {
00156 std::vector<std::string> names;
00157 for (auto& kv : plugins_)
00158 {
00159 names.push_back(kv.first);
00160 }
00161 return names;
00162 }
00163
00170 using SwitchCallback = std::function<void(const std::string&, const std::string&)>;
00171
00180 void setSwitchCallback(SwitchCallback switch_callback) { switch_callback_ = switch_callback; }
00181
00182 protected:
00186 bool switchPluginService(nav_2d_msgs::SwitchPlugin::Request &req, nav_2d_msgs::SwitchPlugin::Response &resp)
00187 {
00188 std::string name = req.new_plugin;
00189 if (usePlugin(name))
00190 {
00191 resp.success = true;
00192 resp.message = "Loaded plugin namespace " + name + ".";
00193 }
00194 else
00195 {
00196 resp.success = false;
00197 resp.message = "Namespace " + name + " not configured!";
00198 }
00199 return true;
00200 }
00201
00202
00203 pluginlib::ClassLoader<T> plugin_loader_;
00204 std::map<std::string, boost::shared_ptr<T>> plugins_;
00205 std::string current_plugin_;
00206
00207
00208 ros::ServiceServer switch_plugin_srv_;
00209 ros::Publisher current_plugin_pub_;
00210 ros::NodeHandle private_nh_;
00211 std::string ros_name_;
00212
00213
00214 SwitchCallback switch_callback_;
00215 };
00216
00217
00218
00219
00220 template<class T>
00221 PluginMux<T>::PluginMux(const std::string& plugin_package, const std::string& plugin_class,
00222 const std::string& parameter_name, const std::string& default_value,
00223 const std::string& ros_name, const std::string& switch_service_name)
00224 : plugin_loader_(plugin_package, plugin_class), private_nh_("~"), ros_name_(ros_name), switch_callback_(nullptr)
00225 {
00226
00227 current_plugin_pub_ = private_nh_.advertise<std_msgs::String>(ros_name_, 1, true);
00228
00229
00230 std::string plugin_class_name;
00231 std::vector<std::string> plugin_namespaces;
00232 private_nh_.getParam(parameter_name, plugin_namespaces);
00233 if (plugin_namespaces.size() == 0)
00234 {
00235
00236 std::string plugin_name = plugin_loader_.getName(default_value);
00237 plugin_namespaces.push_back(plugin_name);
00238 }
00239
00240 for (const std::string& the_namespace : plugin_namespaces)
00241 {
00242
00243 private_nh_.param(std::string(the_namespace + "/plugin_class"), plugin_class_name, default_value);
00244 addPlugin(the_namespace, plugin_class_name);
00245 }
00246
00247
00248 usePlugin(plugin_namespaces[0]);
00249
00250
00251 if (plugin_namespaces.size() > 1)
00252 {
00253 switch_plugin_srv_ = private_nh_.advertiseService(switch_service_name, &PluginMux::switchPluginService, this);
00254 }
00255 }
00256
00257 template<class T>
00258 void PluginMux<T>::addPlugin(const std::string& plugin_name, const std::string& plugin_class_name)
00259 {
00260 try
00261 {
00262 plugins_[plugin_name] = plugin_loader_.createInstance(plugin_class_name);
00263 }
00264 catch (const pluginlib::PluginlibException& ex)
00265 {
00266 ROS_FATAL_NAMED("PluginMux",
00267 "Failed to load the plugin: %s. Exception: %s", plugin_name.c_str(), ex.what());
00268 exit(EXIT_FAILURE);
00269 }
00270 }
00271
00272 }
00273
00274 #endif // NAV_2D_UTILS_PLUGIN_MUX_H