plugin_mux.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2018, Locus Robotics
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the copyright holder nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
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     // If plugin with given name doesn't exist, return false
00092     if (plugins_.count(name) == 0) return false;
00093 
00094     if (switch_callback_)
00095     {
00096       switch_callback_(current_plugin_, name);
00097     }
00098 
00099     // Switch Mux
00100     current_plugin_ = name;
00101 
00102     // Update ROS info
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   // Plugin Management
00203   pluginlib::ClassLoader<T> plugin_loader_;
00204   std::map<std::string, boost::shared_ptr<T>> plugins_;
00205   std::string current_plugin_;
00206 
00207   // ROS Interface
00208   ros::ServiceServer switch_plugin_srv_;
00209   ros::Publisher current_plugin_pub_;
00210   ros::NodeHandle private_nh_;
00211   std::string ros_name_;
00212 
00213   // Switch Callback
00214   SwitchCallback switch_callback_;
00215 };
00216 
00217 // *********************************************************************************************************************
00218 // ****************** Implementation of Templated Methods **************************************************************
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   // Create the latched publisher
00227   current_plugin_pub_ = private_nh_.advertise<std_msgs::String>(ros_name_, 1, true);
00228 
00229   // Load Plugins
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     // If no namespaces are listed, use the name of the default class as the singular namespace.
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     // Load the class name from namespace/plugin_class, or use default value
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   // By default, use the first one as current
00248   usePlugin(plugin_namespaces[0]);
00249 
00250   // Now that the plugins are created, advertise the service if there are multiple
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 }  // namespace nav_2d_utils
00273 
00274 #endif  // NAV_2D_UTILS_PLUGIN_MUX_H


nav_2d_utils
Author(s):
autogenerated on Wed Jun 26 2019 20:09:36