plugin_manager.h
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2016, Alexander Stumpf, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Simulation, Systems Optimization and Robotics
00013 //       group, TU Darmstadt nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 // DISCLAIMED. IN NO EVENT SHALL THE 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 VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__
00030 #define VIGIR_PLUGINLIB_PLUGIN_MANAGER_H__
00031 
00032 #include <ros/ros.h>
00033 
00034 #include <actionlib/server/simple_action_server.h>
00035 
00036 #include <boost/noncopyable.hpp>
00037 
00038 #include <vigir_generic_params/parameter_manager.h>
00039 
00040 #include <vigir_pluginlib/plugin_loader.h>
00041 #include <vigir_pluginlib/plugin.h>
00042 
00043 #include <vigir_pluginlib_msgs/pluginlib_msgs.h>
00044 
00045 
00046 
00047 namespace vigir_pluginlib
00048 {
00049 class PluginManager
00050   : private boost::noncopyable
00051 {
00052 public:
00053   // typedefs
00054   typedef boost::shared_ptr<PluginManager> Ptr;
00055   typedef boost::shared_ptr<const PluginManager> ConstPtr;
00056 
00057   typedef std::vector<PluginLoaderBase*> PluginLoaderVector;
00058 
00059 protected:
00060   typedef actionlib::SimpleActionServer<msgs::GetPluginDescriptionsAction>  GetPluginDescriptionsActionServer;
00061   typedef actionlib::SimpleActionServer<msgs::GetPluginStatesAction>        GetPluginStatesActionServer;
00062   typedef actionlib::SimpleActionServer<msgs::PluginManagementAction>       PluginManagementActionServer;
00063 
00064   static PluginManager::Ptr singelton_;
00065 
00066   PluginManager();
00067 
00068   static PluginManager::Ptr Instance();
00069 
00070 public:
00071   ~PluginManager();
00072 
00077   static void initialize(ros::NodeHandle& nh);
00078 
00085   static bool autocompletePluginDescriptionByName(const std::string& name, msgs::PluginDescription& plugin_description);
00086 
00095   template<class PluginBaseClass>
00096   static bool addPluginClassLoader(const std::string& package, const std::string& base_class, const std::string& attrib_name = std::string("plugin"), const std::vector<std::string>& plugin_xml_paths = std::vector<std::string>())
00097   {
00098     boost::upgrade_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00099 
00100     // check for duplicate
00101     for (PluginLoaderBase* loader : Instance()->class_loader_)
00102     {
00103       if (loader->getBaseClassType() == base_class)
00104       {
00105         ROS_DEBUG("[PluginManager] The ClassLoader for plugins of type '%s' has been already added!", base_class.c_str());
00106         return false;
00107       }
00108     }
00109 
00110     try
00111     {
00112       boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
00113       PluginLoader<PluginBaseClass>* loader = new PluginLoader<PluginBaseClass>(package, base_class, attrib_name, plugin_xml_paths);
00114       Instance()->class_loader_.push_back(loader);
00115       ROS_INFO("[PluginManager] Added ClassLoader for plugins of type '%s'.", base_class.c_str());
00116       ROS_DEBUG("  Declared classes:");
00117       for (const std::string s : loader->getDeclaredClasses())
00118         ROS_DEBUG("    %s", s.c_str());
00119       ROS_DEBUG("  Registered libraries:");
00120       for (const std::string s : loader->getRegisteredLibraries())
00121         ROS_DEBUG("    %s", s.c_str());
00122     }
00123     catch (pluginlib::LibraryLoadException& e)
00124     {
00125       ROS_ERROR("[PluginManager] The ClassLoader for plugin '%s' of package '%s' failed to load for some reason. Error:\n%s", base_class.c_str(), package.c_str(), e.what());
00126       return false;
00127     }
00128 
00129     return true;
00130   }
00131 
00140   static bool addPlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions, bool initialize = true);
00141   static bool addPlugin(const msgs::PluginDescription& plugin_description, bool initialize = true);
00142   static bool addPluginByName(const std::string& name, bool initialize = true);
00143 
00144   template<typename PluginDerivedClass>
00145   static void addPlugin(bool initialize = true)
00146   {
00147     addPlugin(new PluginDerivedClass());
00148   }
00149   static void addPlugin(Plugin* plugin, bool initialize = true); // this function takes over pointer and will free memory automatically, when plugin is removed
00150   static void addPlugin(Plugin::Ptr plugin, bool initialize = true);
00151 
00155   template<typename T>
00156   static boost::shared_ptr<T> getPlugin(const std::string& name = std::string())
00157   {
00158     // name specific search
00159     if (!name.empty())
00160     {
00161       boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(getPluginByName(name));
00162       if (plugin)
00163         return plugin;
00164 
00165       ROS_ERROR("[PluginManager] Couldn't find any matching plugin named '%s' of type '%s'!", name.c_str(), Plugin::getTypeClass<T>().c_str());
00166     }
00167     // type specific search
00168     else
00169     {
00170       boost::shared_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00171 
00172       for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name_.begin(); itr != Instance()->plugins_by_name_.end(); itr++)
00173       {
00174         boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
00175         if (plugin)
00176           return plugin;
00177       }
00178 
00179       ROS_ERROR("[PluginManager] Couldn't find any matching plugin of type '%s'!", Plugin::getTypeClass<T>().c_str());
00180     }
00181 
00182     return boost::shared_ptr<T>();
00183   }
00184 
00188   template<typename T>
00189   static bool getPlugin(boost::shared_ptr<T>& plugin, const std::string& name = std::string())
00190   {
00191     plugin = getPlugin<T>(name);
00192     return plugin != nullptr;
00193   }
00194 
00195   template<typename T>
00196   inline static bool getPluginByName(const std::string& name, boost::shared_ptr<T>& plugin)
00197   {
00198     return getPlugin(plugin, name);
00199   }
00200   static Plugin::Ptr getPluginByName(const std::string& name);
00201   static bool getPluginByName(const std::string& name, Plugin::Ptr& plugin);
00202 
00204   template<typename T>
00205   static bool getPluginsByType(std::vector<boost::shared_ptr<T> >& plugins)
00206   {
00207     plugins.clear();
00208 
00209     boost::shared_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00210 
00211     for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name_.begin(); itr != Instance()->plugins_by_name_.end(); itr++)
00212     {
00213       boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
00214       if (plugin)
00215         plugins.push_back(plugin);
00216     }
00217 
00218     return !plugins.empty();
00219   }
00221   template<typename T>
00222   static bool getPluginsByType(std::map<std::string, boost::shared_ptr<T> >& plugins)
00223   {
00224     plugins.clear();
00225 
00226     boost::shared_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00227 
00228     for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name_.begin(); itr != Instance()->plugins_by_name_.end(); itr++)
00229     {
00230       boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
00231       if (plugin)
00232         plugins[itr->first] = plugin;
00233     }
00234 
00235     return !plugins.empty();
00236   }
00237   static bool getPluginsByTypeClass(const std::string& type_class, std::vector<Plugin::Ptr>& plugins);
00238 
00240   static bool getUniquePluginByTypeClass(const std::string& type_class, Plugin::Ptr& plugin);
00241 
00242   static void getPluginDescriptions(std::vector<msgs::PluginDescription>& descriptions, msgs::PluginDescription filter = msgs::PluginDescription());
00243   static void getPluginStates(std::vector<msgs::PluginState>& plugin_states, msgs::PluginDescription filter = msgs::PluginDescription());
00244 
00245   static bool removePlugins(const std::vector<msgs::PluginDescription>& plugin_descriptions);
00246   static bool removePlugin(const msgs::PluginDescription& plugin_description);
00247   static bool removePluginByName(const std::string& name);
00248 
00249   static void removePlugin(Plugin::Ptr& plugin);
00250 
00251   template<typename T>
00252   static void removePluginsByType()
00253   {
00254     boost::shared_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00255 
00256     for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name_.begin(); itr != Instance()->plugins_by_name_.end();)
00257     {
00258       boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
00259       if (plugin)
00260       {
00261         lock.unlock();
00262         removePluginByName(itr++->first);
00263         lock.lock();
00264       }
00265       else
00266         itr++;
00267     }
00268   }
00269   static void removePluginsByTypeClass(const std::string& type_class);
00270 
00271   static bool loadPluginSet(const std::vector<msgs::PluginDescription>& plugin_descriptions);
00272   static bool loadPluginSet(const std::string& name);
00273 
00274   static bool hasPlugin(Plugin::Ptr& plugin);
00275 
00276   static bool hasPluginByName(const std::string& name);
00277 
00278   template<typename T>
00279   static bool hasPluginsByType()
00280   {
00281     boost::shared_lock<boost::shared_mutex> lock(Instance()->plugins_mutex_);
00282 
00283     for (std::map<std::string, Plugin::Ptr>::iterator itr = Instance()->plugins_by_name_.begin(); itr != Instance()->plugins_by_name_.end(); itr++)
00284     {
00285       boost::shared_ptr<T> plugin = boost::dynamic_pointer_cast<T>(itr->second);
00286       if (plugin)
00287         return true;
00288     }
00289 
00290     return false;
00291   }
00292   static bool hasPluginsByTypeClass(const std::string& type_class);
00293 
00294   static void loadParams(const vigir_generic_params::ParameterSet& params);
00295 
00296 protected:
00297   // helper
00298   bool getPluginDescription(const std::string& key, msgs::PluginDescription& description);
00299   void publishPluginStateUpdate();
00300 
00301   // mutex to ensure thread safeness
00302   mutable boost::shared_mutex plugins_mutex_;
00303 
00304   // nodehandle (namespace) to be used
00305   ros::NodeHandle nh_;
00306 
00307   // class loader
00308   PluginLoaderVector class_loader_;
00309 
00310   // instantiated plugins
00311   std::string loaded_plugin_set_;
00312   std::map<std::string, Plugin::Ptr> plugins_by_name_;
00313 
00315 
00316   // subscriber
00317   void addPlugin(const msgs::PluginDescriptionConstPtr plugin_description);
00318   void removePlugin(const msgs::PluginDescriptionConstPtr plugin_description);
00319 
00320   // service calls
00321   bool getPluginDescriptionsService(msgs::GetPluginDescriptionsService::Request& req, msgs::GetPluginDescriptionsService::Response& resp);
00322   bool getPluginStatesService(msgs::GetPluginStatesService::Request& req, msgs::GetPluginStatesService::Response& resp);
00323   bool addPluginService(msgs::PluginManagementService::Request& req, msgs::PluginManagementService::Response& resp);
00324   bool removePluginService(msgs::PluginManagementService::Request& req, msgs::PluginManagementService::Response& resp);
00325   bool loadPluginSetService(msgs::PluginManagementService::Request& req, msgs::PluginManagementService::Response& resp);
00326 
00327   // action server calls
00328   void getPluginDescriptionsAction(const msgs::GetPluginDescriptionsGoalConstPtr goal);
00329   void getPluginStatesAction(const msgs::GetPluginStatesGoalConstPtr goal);
00330   void addPluginAction(const msgs::PluginManagementGoalConstPtr goal);
00331   void removePluginAction(const msgs::PluginManagementGoalConstPtr goal);
00332   void loadPluginSetAction(const msgs::PluginManagementGoalConstPtr goal);
00333 
00334   // subscriber
00335   ros::Subscriber add_plugin_sub_;
00336   ros::Subscriber remove_plugin_sub_;
00337 
00338   // publisher
00339   ros::Publisher plugin_states_pub_;
00340 
00341   // service servers
00342   ros::ServiceServer get_plugin_descriptions_srv_;
00343   ros::ServiceServer get_plugin_states_srv_;
00344   ros::ServiceServer add_plugin_srv_;
00345   ros::ServiceServer remove_plugin_srv_;
00346   ros::ServiceServer load_plugin_set_srv_;
00347 
00348   // action servers
00349   boost::shared_ptr<GetPluginDescriptionsActionServer> get_plugin_descriptions_as_;
00350   boost::shared_ptr<GetPluginStatesActionServer> get_plugin_states_as_;
00351   boost::shared_ptr<PluginManagementActionServer> add_plugin_as_;
00352   boost::shared_ptr<PluginManagementActionServer> remove_plugin_as_;
00353   boost::shared_ptr<PluginManagementActionServer> load_plugin_set_as_;
00354 };
00355 }
00356 
00357 #endif


vigir_pluginlib
Author(s): Alexander Stumpf
autogenerated on Tue Sep 13 2016 03:47:30