moveit2
The MoveIt Motion Planning Framework for ROS 2.
utilities.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2022, Metro Robots
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Metro Robots nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: David V. Lu!! */
36 
38 
39 namespace moveit_setup
40 {
41 bool extractPackageNameFromPath(const std::filesystem::path& path, std::string& package_name,
42  std::filesystem::path& relative_filepath)
43 {
44  std::filesystem::path sub_path = path; // holds the directory less one folder
45  if (std::filesystem::is_regular_file(sub_path))
46  {
47  relative_filepath = sub_path.filename(); // holds the path after the sub_path
48  sub_path = sub_path.parent_path();
49  }
50  else
51  {
52  relative_filepath = sub_path;
53  }
54 
55  // truncate path step by step and check if it contains a package.xml
56  while (!sub_path.empty())
57  {
58  if (std::filesystem::is_regular_file(sub_path / "package.xml"))
59  {
60  // Search the <name> </name> string in the package.xml file
61  // This works assuming the package name is entered as <name>PACKAGE_NAME</name>
62  // Default package name to folder name
63  package_name = sub_path.filename().string();
64  tinyxml2::XMLDocument package_xml_file;
65  auto is_open = package_xml_file.LoadFile((sub_path / "package.xml").c_str());
66  if (is_open == tinyxml2::XML_SUCCESS)
67  {
68  auto name_potential =
69  package_xml_file.FirstChildElement("package")->FirstChildElement("name")->FirstChild()->ToText()->Value();
70  if (name_potential)
71  {
72  // Change package name if we have non-empty potential, else it defaults
73  package_name = name_potential;
74  }
75  }
76  return true;
77  }
78  relative_filepath = sub_path.filename() / relative_filepath;
79  sub_path = sub_path.parent_path();
80  }
81  // No package name found, we must be outside ROS
82  return false;
83 }
84 
85 bool hasRequiredAttributes(const tinyxml2::XMLElement& e, const std::vector<XMLAttribute>& attributes)
86 {
87  for (const auto& attr : attributes)
88  {
89  if (!attr.required)
90  continue; // attribute not required
91  const char* value = e.Attribute(attr.name);
92  if (value && strcmp(attr.value, value) == 0)
93  continue; // attribute has required value
94  else
95  return false;
96  }
97  return true;
98 };
99 
100 tinyxml2::XMLElement* uniqueInsert(tinyxml2::XMLDocument& doc, tinyxml2::XMLElement& element, const char* tag,
101  const std::vector<XMLAttribute>& attributes, const char* text)
102 {
103  // search for existing element with required tag name and attributes
104  tinyxml2::XMLElement* result = element.FirstChildElement(tag);
105  while (result && !hasRequiredAttributes(*result, attributes))
106  result = result->NextSiblingElement(tag);
107 
108  if (!result) // if not yet present, create new element
109  {
110  result = doc.NewElement(tag);
111  element.InsertEndChild(result);
112  }
113 
114  // set (not-yet existing) attributes
115  for (const auto& attr : attributes)
116  {
117  if (!result->Attribute(attr.name))
118  result->SetAttribute(attr.name, attr.value);
119  }
120 
121  // insert text if required
122  if (text && !result->GetText())
123  {
124  tinyxml2::XMLText* text_el = doc.NewText(text);
125  result->InsertEndChild(text_el);
126  }
127 
128  return result;
129 }
130 
131 } // namespace moveit_setup
bool hasRequiredAttributes(const tinyxml2::XMLElement &e, const std::vector< XMLAttribute > &attributes)
Definition: utilities.cpp:85
tinyxml2::XMLElement * uniqueInsert(tinyxml2::XMLDocument &doc, tinyxml2::XMLElement &element, const char *tag, const std::vector< XMLAttribute > &attributes={}, const char *text=nullptr)
Insert a new XML element with a given tag, attributes, and text.
Definition: utilities.cpp:100
bool extractPackageNameFromPath(const std::filesystem::path &path, std::string &package_name, std::filesystem::path &relative_filepath)
Definition: utilities.cpp:41
string package_name
Definition: setup.py:4