mesh.cpp
Go to the documentation of this file.
1 
29 #include <stdexcept>
30 
31 #include <boost/algorithm/string/classification.hpp>
32 #include <boost/algorithm/string/split.hpp>
33 #include <Eigen/Geometry>
34 #include <tesseract_common/utils.h>
35 #include <tinyxml2.h>
37 
41 #include <tesseract_urdf/mesh.h>
43 #include <tesseract_urdf/utils.h>
44 
45 namespace tesseract_urdf
46 {
47 std::vector<tesseract_geometry::PolygonMesh::Ptr> parseMesh(const tinyxml2::XMLElement* xml_element,
48  const tesseract_common::ResourceLocator& locator,
49  bool visual,
50  bool make_convex)
51 {
52  std::string filename;
53  if (tesseract_common::QueryStringAttribute(xml_element, "filename", filename) != tinyxml2::XML_SUCCESS)
54  std::throw_with_nested(std::runtime_error("Mesh: Missing or failed parsing attribute 'filename'!"));
55 
56  std::string scale_string;
57  Eigen::Vector3d scale(1, 1, 1);
58  if (tesseract_common::QueryStringAttribute(xml_element, "scale", scale_string) == tinyxml2::XML_SUCCESS)
59  {
60  std::vector<std::string> tokens;
61  boost::split(tokens, scale_string, boost::is_any_of(" "), boost::token_compress_on);
62  if (tokens.size() != 3 || !tesseract_common::isNumeric(tokens))
63  std::throw_with_nested(std::runtime_error("Mesh: Failed parsing attribute 'scale'!"));
64 
65  double sx{ 0 }, sy{ 0 }, sz{ 0 };
66  // No need to check return values because the tokens are verified above
70 
71  if (!(sx > 0))
72  std::throw_with_nested(std::runtime_error("Mesh: Scale x value is not greater than zero!"));
73 
74  if (!(sy > 0))
75  std::throw_with_nested(std::runtime_error("Mesh: Scale y value is not greater than zero!"));
76 
77  if (!(sz > 0))
78  std::throw_with_nested(std::runtime_error("Mesh: Scale z value is not greater than zero!"));
79 
80  scale = Eigen::Vector3d(sx, sy, sz);
81  }
82 
83  std::vector<tesseract_geometry::Mesh::Ptr> meshes;
84 
85  if (visual)
86  meshes = tesseract_geometry::createMeshFromResource<tesseract_geometry::Mesh>(
87  locator.locateResource(filename), scale, true, true, true, true, true);
88  else
89  meshes = tesseract_geometry::createMeshFromResource<tesseract_geometry::Mesh>(
90  locator.locateResource(filename), scale, true, false);
91 
92  if (meshes.empty())
93  std::throw_with_nested(std::runtime_error("Mesh: Error importing meshes from filename: '" + filename + "'!"));
94 
95  bool make_convex_override = false;
96  auto make_convex_override_status = xml_element->QueryBoolAttribute("tesseract:make_convex", &make_convex_override);
97  if (make_convex_override_status != tinyxml2::XML_NO_ATTRIBUTE)
98  {
99  // Make convex override attribute is specified
100  // Check that it was loaded successfully
101  if (make_convex_override_status != tinyxml2::XML_SUCCESS)
102  std::throw_with_nested(std::runtime_error("Mesh: Failed to parse attribute 'tesseract:make_convex'"));
103 
104  // Override the global make_convex flag with the value from the attribute
105  make_convex = make_convex_override;
106  }
107 
108  if (make_convex)
109  {
110  std::vector<tesseract_geometry::PolygonMesh::Ptr> convex_meshes;
111  convex_meshes.reserve(meshes.size());
112 
113  for (const auto& mesh : meshes)
114  {
116  convex_mesh->setCreationMethod(tesseract_geometry::ConvexMesh::CONVERTED);
117  convex_meshes.push_back(convex_mesh);
118  }
119 
120  return convex_meshes;
121  }
122 
123  // Convert to base class for output
124  std::vector<tesseract_geometry::PolygonMesh::Ptr> output;
125  output.reserve(meshes.size());
126  std::copy(meshes.begin(), meshes.end(), std::back_inserter(output));
127 
128  return output;
129 }
130 
131 tinyxml2::XMLElement* writeMesh(const std::shared_ptr<const tesseract_geometry::PolygonMesh>& mesh,
132  tinyxml2::XMLDocument& doc,
133  const std::string& package_path,
134  const std::string& filename)
135 {
136  if (mesh == nullptr)
137  std::throw_with_nested(std::runtime_error("Mesh is nullptr and cannot be converted to XML"));
138  tinyxml2::XMLElement* xml_element = doc.NewElement(MESH_ELEMENT_NAME.data());
139  Eigen::IOFormat eigen_format(Eigen::StreamPrecision, Eigen::DontAlignCols, " ", " ");
140 
141  try
142  {
143  writeMeshToFile(mesh, trailingSlash(package_path) + noLeadingSlash(filename));
144  }
145  catch (...)
146  {
147  std::throw_with_nested(std::runtime_error("Failed to write mesh to file: " + package_path + filename));
148  }
149  xml_element->SetAttribute("filename", makeURDFFilePath(package_path, filename).c_str());
150 
151  if (!mesh->getScale().isOnes(std::numeric_limits<double>::epsilon()))
152  {
153  std::stringstream scale_string;
154  scale_string << mesh->getScale().format(eigen_format);
155  xml_element->SetAttribute("scale", scale_string.str().c_str());
156  }
157 
158  // If the mesh is actually a convex mesh, set the `tesseract:make_convex` attribute true.
159  // The geometry itself is already convex, so telling Tesseract to make it convex won't change the geometry.
160  // However, it will make sure it gets added to the environment as a `ConvexMesh` shape instead of a `Mesh` shape.
161  if (std::dynamic_pointer_cast<const tesseract_geometry::ConvexMesh>(mesh))
162  {
163  xml_element->SetAttribute("tesseract:make_convex", true);
164  }
165 
166  return xml_element;
167 }
168 
169 } // namespace tesseract_urdf
mesh_parser.h
mesh.h
tesseract_urdf::makeURDFFilePath
std::string makeURDFFilePath(const std::string &package_path, const std::string &filename)
Definition: utils.cpp:55
utils.h
convex_hull_utils.h
resource_locator.h
tesseract_urdf::MESH_ELEMENT_NAME
static constexpr std::string_view MESH_ELEMENT_NAME
Definition: mesh.h:47
tesseract_urdf::trailingSlash
std::string trailingSlash(const std::string &path)
Definition: utils.cpp:20
tesseract_common::ResourceLocator::locateResource
virtual std::shared_ptr< Resource > locateResource(const std::string &url) const=0
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
tesseract_urdf::writeMesh
tinyxml2::XMLElement * writeMesh(const std::shared_ptr< const tesseract_geometry::PolygonMesh > &mesh, tinyxml2::XMLDocument &doc, const std::string &package_path, const std::string &filename)
writeMesh Write a mesh to URDF XML and PLY file
Definition: mesh.cpp:131
tesseract_collision::makeConvexMesh
tesseract_geometry::ConvexMesh::Ptr makeConvexMesh(const tesseract_geometry::Mesh &mesh)
utils.h
tesseract_geometry::ConvexMesh::Ptr
std::shared_ptr< ConvexMesh > Ptr
tesseract_common::ResourceLocator
mesh.h
Parse mesh from xml string.
tesseract_common::QueryStringAttribute
int QueryStringAttribute(const tinyxml2::XMLElement *xml_element, const char *name, std::string &value)
TESSERACT_COMMON_IGNORE_WARNINGS_POP
tesseract_urdf::writeMeshToFile
void writeMeshToFile(const std::shared_ptr< const tesseract_geometry::PolygonMesh > &mesh, const std::string &filepath)
Definition: utils.cpp:140
tesseract_common::isNumeric
bool isNumeric(const std::string &s)
tesseract_common::toNumeric< double >
template bool toNumeric< double >(const std::string &, double &)
macros.h
tesseract_urdf
Definition: box.h:43
tesseract_urdf::noLeadingSlash
std::string noLeadingSlash(const std::string &filename)
Definition: utils.cpp:45
tesseract_geometry::ConvexMesh::CONVERTED
CONVERTED
tesseract_urdf::parseMesh
std::vector< std::shared_ptr< tesseract_geometry::PolygonMesh > > parseMesh(const tinyxml2::XMLElement *xml_element, const tesseract_common::ResourceLocator &locator, bool visual, bool make_convex)
Parse xml element mesh.
Definition: mesh.cpp:47


tesseract_urdf
Author(s): Levi Armstrong
autogenerated on Thu Apr 24 2025 03:10:44