rtt_ros.cpp
Go to the documentation of this file.
1 #include <cstdlib>
2 #include <list>
3 #include <queue>
4 #include <sstream>
5 #include <set>
6 
7 #include <boost/filesystem.hpp>
8 #include <boost/version.hpp>
9 
10 #include <libxml/parser.h>
11 #include <libxml/xpath.h>
12 #include <libxml/xpathInternals.h>
13 #include <libxml/tree.h>
14 
15 #include <rtt/RTT.hpp>
17 
19 #include <rtt/Logger.hpp>
20 
21 #include <ros/package.h>
22 #include <rospack/rospack.h>
23 
24 #include <rtt_ros/rtt_ros.h>
25 
26 
27 bool rtt_ros::import(const std::string& package)
28 {
29  RTT::Logger::In in("ROSService::import(\""+package+"\")");
30 
31  boost::shared_ptr<RTT::ComponentLoader> loader = RTT::ComponentLoader::Instance();
32 
33  // List of packages which could not be loaded
34  std::vector<std::string> missing_packages;
35 
36  // Get the dependencies for a given ROS package --> deps
37  try {
38  // Get the package paths
39  std::vector<std::string> ros_package_paths;
40  rospack::Rospack rpack;
41  rpack.setQuiet(true);
42  rpack.getSearchPathFromEnv(ros_package_paths);
43 
44  RTT::log(RTT::Debug) << "Loading dependencies for ROS package \""<< package << "\" from: ";
45  for(size_t i=0; i<ros_package_paths.size(); i++) { RTT::log(RTT::Debug) << ros_package_paths[i]; }
47 
48  rpack.crawl(ros_package_paths,true);
49 
50  if ( ros_package_paths.size() == 0 ) {
51  RTT::log(RTT::Error) << "No paths in the ROS_PACKAGE_PATH environment variable! Could not load ROS package \"" << package << "\"" << RTT::endlog();
52  return false;
53  }
54 
55  // Add all rtt_ros/plugin_depend dependencies to package names
56  std::vector<std::string> deps_to_import;
57  std::vector<std::string> search_paths;
58  rpack.setQuiet(true);
59 
60  // Read the package.xml for this package
61  std::queue<std::string> dep_names;
62  dep_names.push(package);
63  deps_to_import.push_back(package);
64 
65  const xmlChar * rtt_plugin_depend_xpath = xmlCharStrdup("/package/export/rtt_ros/plugin_depend/text()");
66 
67  while(!dep_names.empty())
68  {
69  namespace fs = boost::filesystem;
70 
71  // Get the next dep name, store the dep path
72  std::string dep_name, dep_path;
73  dep_name = dep_names.front();
74  dep_names.pop();
75 
76  bool dep_found = rpack.find(dep_name,dep_path);
77 
78  if(!dep_found) {
79  RTT::log(RTT::Error) << "Could not find ROS package \""<< dep_name << "\" in ROS_PACKAGE_PATH environment variable." <<RTT::endlog();
80  continue;
81  }
82 
83  // Construct the package.xml path
84  fs::path package_xml_path = fs::path(dep_path) / "package.xml";
85  bool is_rosbuild_package = false;
86 
87  // Check if package.xml file exists
88  if(!boost::filesystem::is_regular_file( package_xml_path.string() ) ) {
89 
90  // Fall back to manifest.xml for rosbuild packages
91  package_xml_path = fs::path(dep_path) / "manifest.xml";
92  is_rosbuild_package = true;
93 
94  if(!boost::filesystem::is_regular_file( package_xml_path.string() ) ) {
95  RTT::log(RTT::Error) << "No package.xml or manifest.xml file for ROS package \""<< dep_name << "\" found at "<<package_xml_path.branch_path() <<RTT::endlog();
96  continue;
97  }
98  }
99 
100  // Add package path to the list of search paths
101  if (is_rosbuild_package) {
102  search_paths.push_back((fs::path(dep_path) / "lib" / "orocos").string());
103  }
104 
105  // Read in package.xml/manifest.xml
106  xmlInitParser();
107 
108  // libxml structures
109  xmlDocPtr package_doc;
110  xmlXPathContextPtr xpath_ctx;
111  xmlXPathObjectPtr xpath_obj;
112 
113  // Load package.xml
114  package_doc = xmlParseFile(package_xml_path.string().c_str());
115  xpath_ctx = xmlXPathNewContext(package_doc);
116 
117  // Get the text of the rtt_ros <plugin_depend>s
118  xpath_obj = xmlXPathEvalExpression(rtt_plugin_depend_xpath, xpath_ctx);
119 
120  // Iterate through the nodes
121  if(xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) {
122  RTT::log(RTT::Debug) << "ROS package \""<< dep_name << "\" has no RTT plugin dependencies." <<RTT::endlog();
123  } else {
124  RTT::log(RTT::Debug) << "ROS package \""<< dep_name << "\" has "<<xpath_obj->nodesetval->nodeNr<<" RTT plugin dependencies." <<RTT::endlog();
125 
126  for(int i=0; i < xpath_obj->nodesetval->nodeNr; i++) {
127  if(xpath_obj->nodesetval->nodeTab[i]) {
128  std::ostringstream oss;
129  oss << xmlNodeGetContent(xpath_obj->nodesetval->nodeTab[i]);
130  RTT::log(RTT::Debug) << "Found dependency \""<< oss.str() << "\"" <<RTT::endlog();
131  dep_names.push(oss.str());
132 
133  // Add the dep to the list of deps to import
134  deps_to_import.push_back(oss.str());
135  }
136  }
137  }
138 
139  xmlXPathFreeObject(xpath_obj);
140  xmlXPathFreeContext(xpath_ctx);
141  xmlFreeDoc(package_doc);
142  xmlCleanupParser();
143  }
144 
145  // Build path list by prepending paths from search_paths list to the RTT component path in reverse order without duplicates
146  std::set<std::string> search_paths_seen;
147  std::string path_list = loader->getComponentPath();
148  for(std::vector<std::string>::reverse_iterator it = search_paths.rbegin();
149  it != search_paths.rend();
150  ++it)
151  {
152  if (search_paths_seen.count(*it)) continue;
153  path_list = *it + ":" + path_list;
154  search_paths_seen.insert(*it);
155  }
156 
157  RTT::log(RTT::Debug) << "Attempting to load RTT plugins from "<<deps_to_import.size()<<" packages..." << RTT::endlog();
158 
159  // Import each package dependency and the package itself (in deps_to_import[0])
160  for(std::vector<std::string>::reverse_iterator it = deps_to_import.rbegin();
161  it != deps_to_import.rend();
162  ++it)
163  {
164  // Check if it's already been imported
165  if(*it == "rtt_ros" || loader->isImported(*it)) {
166  RTT::log(RTT::Debug) << "Package dependency '"<< *it <<"' already imported." << RTT::endlog();
167  continue;
168  }
169 
170  // Import the dependency
171  if(loader->import(*it, path_list)) {
172  RTT::log(RTT::Debug) << "Importing Orocos components from ROS package \""<<*it<<"\" SUCCEEDED.";
173  } else {
174  // Temporarily store the name of the missing package
175  missing_packages.push_back(*it);
176  RTT::log(RTT::Debug) << "Importing Orocos components from ROS package \""<<*it<<"\" FAILED.";
177  }
179  }
180 
181  } catch(std::string arg) {
182  RTT::log(RTT::Debug) << "While processing the dependencies of " << package << ": Dependency is not a ros package: " << arg << RTT::endlog();
183  missing_packages.push_back(arg);
184  }
185 
186  // Report success or failure
187  if(missing_packages.size() == 0) {
188  RTT::log(RTT::Info) << "Loaded plugins from ROS package \"" << package << "\" and its dependencies." << RTT::endlog();
189  } else {
190  RTT::log(RTT::Warning) << "Could not load RTT plugins from the following ROS packages (they might be empty, in which case this message can be ignored): "<< RTT::endlog();
191  for(std::vector<std::string>::iterator it = missing_packages.begin();
192  it != missing_packages.end();
193  ++it)
194  {
195  RTT::log(RTT::Warning) << " - " << *it<< RTT::endlog();
196  }
197  }
198 
199  return missing_packages.size() == 0;
200 }
void setQuiet(bool quiet)
std::string str()
static boost::shared_ptr< ComponentLoader > Instance()
bool import(const std::string &package)
Import a ROS package and all of its rtt_ros/plugin_depend dependencies.
Definition: rtt_ros.cpp:27
bool getSearchPathFromEnv(std::vector< std::string > &sp)
void crawl(std::vector< std::string > search_path, bool force)
bool find(const std::string &name, std::string &path)
static Logger & log()
static Logger::LogFunction endlog()


rtt_ros
Author(s): Ruben Smits
autogenerated on Sat Jun 8 2019 18:04:54