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 #include "plugin.h"
00031 #include "type_registry.h"
00032
00033 #include <iostream>
00034 #include <fstream>
00035 #include <yaml-cpp/yaml.h>
00036
00037 #include <ros/console.h>
00038 #include <ros/package.h>
00039
00040 #include <boost/filesystem.hpp>
00041
00042 namespace fs = boost::filesystem;
00043
00044 namespace rviz
00045 {
00046
00047 Plugin::Plugin()
00048 : loaded_(false)
00049 , auto_load_(true)
00050 , auto_load_tried_(false)
00051 , doc_(0)
00052 {
00053
00054 }
00055
00056 Plugin::~Plugin()
00057 {
00058 unload();
00059
00060 delete doc_;
00061 }
00062
00063 void Plugin::loadDescription(const std::string& description_path)
00064 {
00065 description_path_ = description_path;
00066
00067 std::ifstream fin(description_path.c_str());
00068
00069 try
00070 {
00071 YAML::Parser parser(fin);
00072 doc_ = new YAML::Node;
00073 YAML::Node& doc = *doc_;
00074 parser.GetNextDocument(doc);
00075
00076 std::string library;
00077 doc["library"] >> library;
00078
00079 fs::path p(description_path);
00080 fs::path parent = p.parent_path();
00081
00082 while (true)
00083 {
00084 if (fs::exists(parent / "manifest.xml"))
00085 {
00086 #if BOOST_FILESYSTEM_VERSION == 3
00087 std::string package = parent.filename().string();
00088 #else
00089 std::string package = parent.filename();
00090 #endif
00091 std::string package_path = ros::package::getPath(package);
00092 if (description_path.find(package_path) == 0)
00093 {
00094 package_name_ = package;
00095 break;
00096 }
00097 }
00098
00099 parent = parent.parent_path();
00100
00101 if (parent.string().empty())
00102 {
00103 ROS_ERROR("Could not find package name for plugin [%s]", description_path.c_str());
00104 break;
00105 }
00106 }
00107
00108 library_path_ = (p.parent_path() / fs::path((const char*)wxDynamicLibrary::CanonicalizeName(wxString::FromAscii(library.c_str()), wxDL_LIBRARY).char_str())).string();
00109
00110
00111 #if __WXMAC__
00112 fs::path mac_path(library_path_);
00113 mac_path.replace_extension(".so");
00114 library_path_ = mac_path.string();
00115 #endif
00116
00117 doc["name"] >> name_;
00118
00119 const YAML::Node& displays = doc["displays"];
00120 for (uint32_t i = 0; i < displays.size(); ++i)
00121 {
00122 const YAML::Node& n = displays[i];
00123 DisplayTypeInfoPtr info(new DisplayTypeInfo);
00124 info->package = package_name_;
00125
00126
00127
00128 n["class_name"] >> info->class_name;
00129 n["display_name"] >> info->display_name;
00130 n["description"] >> info->help_description;
00131
00132 display_info_.push_back(info);
00133 }
00134
00135
00136 try
00137 {
00138 const YAML::Node& n = doc["display_class_mapping"];
00139 for (uint32_t i = 0; i < n.size(); ++i)
00140 {
00141 const YAML::Node& mapping = n[i];
00142 std::string old_class, new_class;
00143 mapping["old_class"] >> old_class;
00144 mapping["new_class"] >> new_class;
00145 display_class_mappings_[old_class] = new_class;
00146 }
00147 }
00148 catch (YAML::RepresentationException& e)
00149 {
00150 }
00151
00152
00153 try
00154 {
00155 const YAML::Node& n = doc["display_name_mapping"];
00156 for (uint32_t i = 0; i < n.size(); ++i)
00157 {
00158 const YAML::Node& mapping = n[i];
00159 std::string old_class, new_class;
00160 mapping["old_name"] >> old_class;
00161 mapping["new_name"] >> new_class;
00162 display_name_mappings_[old_class] = new_class;
00163 }
00164 }
00165 catch (YAML::RepresentationException& e)
00166 {
00167 }
00168 }
00169 catch (YAML::ParserException& e)
00170 {
00171 throw PluginParseException(description_path, e.msg);
00172 }
00173 catch (YAML::RepresentationException& e)
00174 {
00175 throw PluginParseException(description_path, e.msg);
00176 }
00177 }
00178
00179 void Plugin::load()
00180 {
00181 if (loaded_)
00182 {
00183 return;
00184 }
00185
00186 loading_signal_(PluginStatus(this));
00187
00188 if (!fs::exists(library_path_))
00189 {
00190 throw LibraryDoesNotExistException(library_path_);
00191 }
00192
00193 if (!library_.Load(wxString::FromAscii(library_path_.c_str())))
00194 {
00195 throw UnableToLoadLibraryException(library_path_);
00196 }
00197
00198 if (!library_.HasSymbol(wxT("rvizPluginInit")))
00199 {
00200 throw NoPluginInitFunctionException(library_path_);
00201 }
00202
00203 typedef void (*InitFunc)(TypeRegistry*);
00204 InitFunc init = reinterpret_cast<InitFunc>(library_.GetSymbol(wxT("rvizPluginInit")));
00205
00206 TypeRegistry reg;
00207 (*init)(®);
00208
00209 {
00210 L_DisplayEntry::const_iterator it = reg.getDisplayEntries().begin();
00211 L_DisplayEntry::const_iterator end = reg.getDisplayEntries().end();
00212 for (; it != end; ++it)
00213 {
00214 const DisplayEntry& ent = *it;
00215 DisplayTypeInfoPtr info = getDisplayTypeInfo(ent.class_name);
00216 if (!info)
00217 {
00218 ROS_ERROR("Display with class name [%s] did not exist in the plugin yaml file.", ent.class_name.c_str());
00219 info.reset(new DisplayTypeInfo);
00220 info->class_name = ent.class_name;
00221 }
00222
00223 if (info->display_name.empty())
00224 {
00225 info->display_name = info->class_name;
00226 }
00227
00228 info->creator = ent.creator;
00229 }
00230 }
00231
00232 {
00233 M_ClassEntry::const_iterator it = reg.getClassEntries().begin();
00234 M_ClassEntry::const_iterator end = reg.getClassEntries().end();
00235 for (; it != end; ++it)
00236 {
00237 const std::string& base_class = it->first;
00238 const L_ClassEntry& entries = it->second;
00239 L_ClassEntry::const_iterator ent_it = entries.begin();
00240 L_ClassEntry::const_iterator ent_end = entries.end();
00241 for (; ent_it != ent_end; ++ent_it)
00242 {
00243 const ClassEntry& ent = *ent_it;
00244 ClassTypeInfoPtr info(new ClassTypeInfo);
00245 info->base_class_name = base_class;
00246 info->class_name = ent.class_name;
00247 info->readable_name = ent.readable_name;
00248 info->creator = ent.creator;
00249 info->package = package_name_;
00250 class_info_[base_class].push_back(info);
00251 }
00252 }
00253 }
00254
00255 loaded_ = true;
00256 loaded_signal_(PluginStatus(this));
00257 }
00258
00259 const L_ClassTypeInfo* Plugin::getClassTypeInfoList(const std::string& base_class) const
00260 {
00261 M_ClassTypeInfo::const_iterator it = class_info_.find(base_class);
00262 if (it == class_info_.end())
00263 {
00264 return 0;
00265 }
00266
00267 return &it->second;
00268 }
00269
00270 void Plugin::unload()
00271 {
00272 if (!loaded_)
00273 {
00274 return;
00275 }
00276
00277 unloading_signal_(PluginStatus(this));
00278
00279 {
00280 L_DisplayTypeInfo::iterator it = display_info_.begin();
00281 L_DisplayTypeInfo::iterator end = display_info_.end();
00282 for (; it != end; ++it)
00283 {
00284 (*it)->creator.reset();
00285 }
00286 }
00287
00288 class_info_.clear();
00289
00290 library_.Unload();
00291 loaded_ = false;
00292
00293 unloaded_signal_(PluginStatus(this));
00294 }
00295
00296 bool Plugin::isLoaded()
00297 {
00298 return loaded_;
00299 }
00300
00301 bool Plugin::isAutoLoad()
00302 {
00303 return auto_load_;
00304 }
00305
00306 void Plugin::setAutoLoad(bool autoload)
00307 {
00308 auto_load_ = autoload;
00309 }
00310
00311 const std::string& Plugin::mapDisplayClassName(const std::string& class_name) const
00312 {
00313 M_string::const_iterator it = display_class_mappings_.find(class_name);
00314 if (it == display_class_mappings_.end())
00315 {
00316 return class_name;
00317 }
00318
00319 return it->second;
00320 }
00321
00322 DisplayTypeInfoPtr Plugin::getDisplayTypeInfo(const std::string& class_name) const
00323 {
00324 std::string mapped_name = mapDisplayClassName(class_name);
00325 L_DisplayTypeInfo::const_iterator it = display_info_.begin();
00326 L_DisplayTypeInfo::const_iterator end = display_info_.end();
00327 for (; it != end; ++it)
00328 {
00329 const DisplayTypeInfoPtr& info = *it;
00330 if (info->class_name == mapped_name)
00331 {
00332 return info;
00333 }
00334 }
00335
00336 return DisplayTypeInfoPtr();
00337 }
00338
00339 const std::string& Plugin::mapDisplayName(const std::string& name) const
00340 {
00341 M_string::const_iterator it = display_name_mappings_.find(name);
00342 if (it == display_name_mappings_.end())
00343 {
00344 return name;
00345 }
00346
00347 return it->second;
00348 }
00349
00350 DisplayTypeInfoPtr Plugin::getDisplayTypeInfoByDisplayName(const std::string& display_name) const
00351 {
00352 std::string mapped_name = mapDisplayName(display_name);
00353 L_DisplayTypeInfo::const_iterator it = display_info_.begin();
00354 L_DisplayTypeInfo::const_iterator end = display_info_.end();
00355 for (; it != end; ++it)
00356 {
00357 const DisplayTypeInfoPtr& info = *it;
00358 if (info->display_name == mapped_name)
00359 {
00360 return info;
00361 }
00362 }
00363
00364 return DisplayTypeInfoPtr();
00365 }
00366
00367 void Plugin::autoLoad()
00368 {
00369 if (auto_load_tried_ || loaded_ || !auto_load_)
00370 {
00371 return;
00372 }
00373
00374 try
00375 {
00376 load();
00377 }
00378 catch (LibraryDoesNotExistException&)
00379 {
00380 }
00381 catch (std::runtime_error& e)
00382 {
00383 ROS_ERROR("%s", e.what());
00384 }
00385 }
00386
00387 Display* Plugin::createDisplay(const std::string& class_name, const std::string& name, VisualizationManager* manager)
00388 {
00389 autoLoad();
00390
00391 DisplayTypeInfoPtr typeinfo = getDisplayTypeInfo(class_name);
00392 if (!typeinfo || !typeinfo->creator)
00393 {
00394 return 0;
00395 }
00396
00397 return typeinfo->creator->create(name, manager);
00398 }
00399
00400 }