31 #include <boost/algorithm/string.hpp>
32 #include <Eigen/Geometry>
51 std::string joint_name;
53 std::throw_with_nested(std::runtime_error(
"Joint: Missing or failed parsing attribute 'name'!"));
56 auto j = std::make_shared<tesseract_scene_graph::Joint>(joint_name);
59 const tinyxml2::XMLElement* origin = xml_element->FirstChildElement(
"origin");
60 if (origin !=
nullptr)
64 j->parent_to_joint_origin_transform =
parseOrigin(origin);
68 std::throw_with_nested(
69 std::runtime_error(
"Joint: Error parsing 'origin' element for joint '" + joint_name +
"'!"));
74 const tinyxml2::XMLElement* parent = xml_element->FirstChildElement(
"parent");
75 if (parent ==
nullptr)
76 std::throw_with_nested(std::runtime_error(
"Joint: Missing element 'parent' for joint '" + joint_name +
"'!"));
79 std::throw_with_nested(
80 std::runtime_error(
"Joint: Failed parsing element 'parent' attribute 'link' for joint '" + joint_name +
"'!"));
83 const tinyxml2::XMLElement* child = xml_element->FirstChildElement(
"child");
85 std::throw_with_nested(std::runtime_error(
"Joint: Missing element 'child' for joint '" + joint_name +
"'!"));
88 std::throw_with_nested(
89 std::runtime_error(
"Joint: Failed parsing element 'child' attribute 'link' for joint '" + joint_name +
"'!"));
92 std::string joint_type;
94 std::throw_with_nested(std::runtime_error(
"Joint: Missing element 'type' for joint '" + joint_name +
"'!"));
96 if (joint_type ==
"planar")
98 else if (joint_type ==
"floating")
100 else if (joint_type ==
"revolute")
102 else if (joint_type ==
"continuous")
104 else if (joint_type ==
"prismatic")
106 else if (joint_type ==
"fixed")
109 std::throw_with_nested(
110 std::runtime_error(
"Joint: Invalid joint type '" + joint_type +
"' for joint '" + joint_name +
"'!"));
115 const tinyxml2::XMLElement* axis = xml_element->FirstChildElement(
"axis");
118 j->axis = Eigen::Vector3d(1.0, 0.0, 0.0);
122 std::string axis_str;
124 std::throw_with_nested(
125 std::runtime_error(
"Joint: Failed parsing element 'axis' attribute 'xyz' for joint '" + joint_name +
"'!"));
127 std::vector<std::string> tokens;
128 boost::split(tokens, axis_str, boost::is_any_of(
" "), boost::token_compress_on);
130 std::throw_with_nested(std::runtime_error(
"Joint: Failed parsing element 'axis' attribute 'xyz' string for "
134 double ax{ 0 }, ay{ 0 }, az{ 0 };
140 j->axis = Eigen::Vector3d(ax, ay, az);
148 const tinyxml2::XMLElement* limits = xml_element->FirstChildElement(
"limit");
150 std::throw_with_nested(std::runtime_error(
"Joint: Missing element 'limits' for joint '" + joint_name +
"'!"));
154 j->limits = std::make_shared<tesseract_scene_graph::JointLimits>();
164 std::throw_with_nested(
165 std::runtime_error(
"Joint: Failed parsing element 'limits' for joint '" + joint_name +
"'!"));
171 const tinyxml2::XMLElement* safety = xml_element->FirstChildElement(
"safety_controller");
172 if (safety !=
nullptr)
180 std::throw_with_nested(
181 std::runtime_error(
"Joint: Failed parsing element 'safety_controller' for joint '" + joint_name +
"'!"));
186 const tinyxml2::XMLElement* calibration = xml_element->FirstChildElement(
"calibration");
187 if (calibration !=
nullptr)
195 std::throw_with_nested(
196 std::runtime_error(
"Joint: Failed parsing element 'calibration' for joint '" + joint_name +
"'!"));
201 const tinyxml2::XMLElement* mimic = xml_element->FirstChildElement(
"mimic");
202 if (mimic !=
nullptr)
210 std::throw_with_nested(
211 std::runtime_error(
"Joint: Failed parsing element 'mimic' for joint '" + joint_name +
"'!"));
216 const tinyxml2::XMLElement* dynamics = xml_element->FirstChildElement(
"dynamics");
217 if (dynamics !=
nullptr)
225 std::throw_with_nested(
226 std::runtime_error(
"Joint: Failed parsing element 'dynamics' for joint '" + joint_name +
"'!"));
233 tinyxml2::XMLElement*
writeJoint(
const std::shared_ptr<const tesseract_scene_graph::Joint>& joint,
234 tinyxml2::XMLDocument& doc)
236 if (joint ==
nullptr)
237 std::throw_with_nested(std::runtime_error(
"Joint is nullptr and cannot be converted to XML"));
241 xml_element->SetAttribute(
"name", joint->getName().c_str());
244 if (!joint->parent_to_joint_origin_transform.matrix().isIdentity(std::numeric_limits<double>::epsilon()))
246 tinyxml2::XMLElement* xml_origin =
writeOrigin(joint->parent_to_joint_origin_transform, doc);
247 xml_element->InsertEndChild(xml_origin);
251 tinyxml2::XMLElement* xml_parent = doc.NewElement(
"parent");
252 xml_parent->SetAttribute(
"link", joint->parent_link_name.c_str());
253 xml_element->InsertEndChild(xml_parent);
256 tinyxml2::XMLElement* xml_child = doc.NewElement(
"child");
257 xml_child->SetAttribute(
"link", joint->child_link_name.c_str());
258 xml_element->InsertEndChild(xml_child);
262 xml_element->SetAttribute(
"type",
"planar");
264 xml_element->SetAttribute(
"type",
"floating");
266 xml_element->SetAttribute(
"type",
"revolute");
268 xml_element->SetAttribute(
"type",
"continuous");
270 xml_element->SetAttribute(
"type",
"prismatic");
272 xml_element->SetAttribute(
"type",
"fixed");
274 std::throw_with_nested(std::runtime_error(
"Joint: Invalid joint type for joint '" + joint->getName() +
"'!"));
280 tinyxml2::XMLElement* xml_axis = doc.NewElement(
"axis");
281 Eigen::IOFormat eigen_format(Eigen::StreamPrecision, Eigen::DontAlignCols,
" ",
" ");
282 std::stringstream axis_str;
283 axis_str << joint->axis.format(eigen_format);
284 xml_axis->SetAttribute(
"xyz", axis_str.str().c_str());
285 xml_element->InsertEndChild(xml_axis);
293 if (joint->limits ==
nullptr)
294 std::throw_with_nested(std::runtime_error(
"Joint: Missing limits for joint '" + joint->getName() +
"'!"));
297 std::throw_with_nested(std::runtime_error(
"Upper/Lower limits for `" + joint->getName() +
"` are both zero!"));
299 tinyxml2::XMLElement* xml_limits =
writeLimits(joint->limits, doc);
300 xml_element->InsertEndChild(xml_limits);
310 tinyxml2::XMLElement* xml_limits =
writeLimits(joint->limits, doc);
311 xml_element->InsertEndChild(xml_limits);
316 if (joint->safety !=
nullptr)
319 xml_element->InsertEndChild(xml_safety);
323 if (joint->calibration !=
nullptr)
325 tinyxml2::XMLElement* xml_calibration =
writeCalibration(joint->calibration, doc);
326 xml_element->InsertEndChild(xml_calibration);
330 if (joint->mimic !=
nullptr)
332 tinyxml2::XMLElement* xml_mimic =
writeMimic(joint->mimic, doc);
333 xml_element->InsertEndChild(xml_mimic);
337 if (joint->dynamics !=
nullptr)
339 tinyxml2::XMLElement* xml_dynamics =
writeDynamics(joint->dynamics, doc);
340 xml_element->InsertEndChild(xml_dynamics);