65 get_urdf_service_ =
context_->moveit_cpp_->getNode()->create_service<moveit_msgs::srv::GetGroupUrdf>(
66 GET_URDF_SERVICE_NAME,
67 [
this](
const std::shared_ptr<moveit_msgs::srv::GetGroupUrdf::Request>& req,
68 const std::shared_ptr<moveit_msgs::srv::GetGroupUrdf::Response>& res) {
69 res->error_code.source = std::string(
"GetUrdfService");
70 const auto subgroup =
context_->moveit_cpp_->getRobotModel()->getJointModelGroup(req->group_name);
74 const auto error_string = std::string(
"Cannot create URDF because planning group '") + req->group_name +
75 std::string(
"' does not exist");
76 RCLCPP_ERROR(getLogger(),
"%s", error_string.c_str());
77 res->error_code.message = error_string;
78 res->error_code.val = moveit_msgs::msg::MoveItErrorCodes::FAILURE;
82 std::string full_urdf_string =
83 context_->moveit_cpp_->getPlanningSceneMonitor()->getRobotModelLoader()->getRDFLoader()->getURDFString();
86 if (full_urdf_string.empty())
88 const auto error_string = std::string(
"Couldn't get the robot description string from MoveItCpp");
89 RCLCPP_ERROR(getLogger(),
"%s", error_string.c_str());
90 res->error_code.message = error_string;
91 res->error_code.val = moveit_msgs::msg::MoveItErrorCodes::FAILURE;
97 res->urdf_string = std::string(
"<?xml version=\"1.0\" ?><robot name=\"") + req->group_name +
98 std::string(
"\" xmlns:xacro=\"http://ros.org/wiki/xacro\">");
101 auto link_names = subgroup->getLinkModelNames();
103 std::sort(link_names.begin(), link_names.end());
104 link_names.erase(std::unique(link_names.begin(), link_names.end()), link_names.end());
106 for (
const auto& link_name : link_names)
108 const auto start = full_urdf_string.find(
"<link name=\"" + link_name +
"\"");
109 auto substring = full_urdf_string.substr(start, full_urdf_string.size() - start);
112 auto const substring_without_opening = substring.substr(1, substring.size() - 2);
113 auto const general_opening_pos_a = substring_without_opening.find(
'<');
114 auto const link_closing_pos_b = substring.find(GENERAL_ELEMENT_CLOSING);
116 if (link_closing_pos_b < general_opening_pos_a)
118 res->urdf_string += substring.substr(0, link_closing_pos_b + GENERAL_ELEMENT_CLOSING.size());
123 res->urdf_string += substring.substr(0, substring.find(LINK_ELEMENT_CLOSING) + LINK_ELEMENT_CLOSING.size());
128 auto joint_names = subgroup->getJointModelNames();
130 std::sort(joint_names.begin(), joint_names.end());
131 joint_names.erase(std::unique(joint_names.begin(), joint_names.end()), joint_names.end());
132 for (
const auto& joint_name : joint_names)
134 const auto start = full_urdf_string.find(
"<joint name=\"" + joint_name +
"\" type");
135 auto substring = full_urdf_string.substr(start, full_urdf_string.size() - start);
136 res->urdf_string += substring.substr(0, substring.find(JOINT_ELEMENT_CLOSING) + JOINT_ELEMENT_CLOSING.size());
139 const auto parent_link_element = subgroup->getJointModel(joint_name)->getParentLinkModel()->getName();
140 if (std::find(link_names.begin(), link_names.end(), parent_link_element) == link_names.end())
142 auto const base_link_element =
"<link name=\"" + parent_link_element +
"\"/>";
143 res->urdf_string += base_link_element;
144 link_names.push_back(parent_link_element);
149 res->urdf_string += ROBOT_ELEMENT_CLOSING;
152 if (!urdf::parseURDF(res->urdf_string))
154 const std::string error_string = std::string(
"Failed to create valid urdf");
155 RCLCPP_ERROR(getLogger(),
"%s", error_string.c_str());
156 res->error_code.message = error_string;
157 res->error_code.val = moveit_msgs::msg::MoveItErrorCodes::FAILURE;
160 res->error_code.val = moveit_msgs::msg::MoveItErrorCodes::SUCCESS;