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  // This runs until the path is either empty "" or at the root "/" or "C:\\"
57  while (!sub_path.empty() && sub_path != sub_path.root_path())
58  {
59  if (std::filesystem::is_regular_file(sub_path / "package.xml"))
60  {
61  // Search the <name> </name> string in the package.xml file
62  // This works assuming the package name is entered as <name>PACKAGE_NAME</name>
63  // Default package name to folder name
64  package_name = sub_path.filename().string();
65  tinyxml2::XMLDocument package_xml_file;
66  auto is_open = package_xml_file.LoadFile((sub_path / "package.xml").c_str());
67  if (is_open == tinyxml2::XML_SUCCESS)
68  {
69  auto name_potential =
70  package_xml_file.FirstChildElement("package")->FirstChildElement("name")->FirstChild()->ToText()->Value();
71  if (name_potential)
72  {
73  // Change package name if we have non-empty potential, else it defaults
74  package_name = name_potential;
75  }
76  }
77  return true;
78  }
79  relative_filepath = sub_path.filename() / relative_filepath;
80  sub_path = sub_path.parent_path();
81  }
82  // No package name found, we must be outside ROS
83  return false;
84 }
85 
86 bool hasRequiredAttributes(const tinyxml2::XMLElement& e, const std::vector<XMLAttribute>& attributes)
87 {
88  for (const auto& attr : attributes)
89  {
90  if (!attr.required)
91  continue; // attribute not required
92  const char* value = e.Attribute(attr.name);
93  if (value && strcmp(attr.value, value) == 0)
94  {
95  continue; // attribute has required value
96  }
97  else
98  {
99  return false;
100  }
101  }
102  return true;
103 };
104 
105 tinyxml2::XMLElement* uniqueInsert(tinyxml2::XMLDocument& doc, tinyxml2::XMLElement& element, const char* tag,
106  const std::vector<XMLAttribute>& attributes, const char* text)
107 {
108  // search for existing element with required tag name and attributes
109  tinyxml2::XMLElement* result = element.FirstChildElement(tag);
110  while (result && !hasRequiredAttributes(*result, attributes))
111  result = result->NextSiblingElement(tag);
112 
113  if (!result) // if not yet present, create new element
114  {
115  result = doc.NewElement(tag);
116  element.InsertEndChild(result);
117  }
118 
119  // set (not-yet existing) attributes
120  for (const auto& attr : attributes)
121  {
122  if (!result->Attribute(attr.name))
123  result->SetAttribute(attr.name, attr.value);
124  }
125 
126  // insert text if required
127  if (text && !result->GetText())
128  {
129  tinyxml2::XMLText* text_el = doc.NewText(text);
130  result->InsertEndChild(text_el);
131  }
132 
133  return result;
134 }
135 
136 } // namespace moveit_setup
bool hasRequiredAttributes(const tinyxml2::XMLElement &e, const std::vector< XMLAttribute > &attributes)
Definition: utilities.cpp:86
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:105
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