39 #include <boost/graph/depth_first_search.hpp>
40 #include <console_bridge/console.h>
51 KDL::Frame
convert(
const Eigen::Isometry3d& transform)
56 frame.p[0] = transform(0, 3);
57 frame.p[1] = transform(1, 3);
58 frame.p[2] = transform(2, 3);
61 frame.M.data[0] = transform(0, 0);
62 frame.M.data[1] = transform(0, 1);
63 frame.M.data[2] = transform(0, 2);
64 frame.M.data[3] = transform(1, 0);
65 frame.M.data[4] = transform(1, 1);
66 frame.M.data[5] = transform(1, 2);
67 frame.M.data[6] = transform(2, 0);
68 frame.M.data[7] = transform(2, 1);
69 frame.M.data[8] = transform(2, 2);
74 Eigen::Isometry3d
convert(
const KDL::Frame& frame)
76 Eigen::Isometry3d transform;
79 transform(0, 3) = frame.p[0];
80 transform(1, 3) = frame.p[1];
81 transform(2, 3) = frame.p[2];
84 transform(0, 0) = frame.M.data[0];
85 transform(0, 1) = frame.M.data[1];
86 transform(0, 2) = frame.M.data[2];
87 transform(1, 0) = frame.M.data[3];
88 transform(1, 1) = frame.M.data[4];
89 transform(1, 2) = frame.M.data[5];
90 transform(2, 0) = frame.M.data[6];
91 transform(2, 1) = frame.M.data[7];
92 transform(2, 2) = frame.M.data[8];
103 KDL::Vector
convert(
const Eigen::Vector3d& vector) {
return KDL::Vector{ vector(0), vector(1), vector(2) }; }
105 Eigen::Vector3d
convert(
const KDL::Vector& vector) {
return Eigen::Vector3d{ vector(0), vector(1), vector(2) }; }
107 Eigen::MatrixXd
convert(
const KDL::Jacobian& jacobian) {
return jacobian.data; }
109 KDL::Jacobian
convert(
const Eigen::MatrixXd& jacobian)
111 if (jacobian.rows() != 6)
112 throw std::runtime_error(
"Eigen Jacobian must have six rows!");
114 KDL::Jacobian matrix;
115 matrix.data = jacobian;
120 Eigen::MatrixXd
convert(
const KDL::Jacobian& jacobian,
const std::vector<int>& q_nrs)
122 Eigen::MatrixXd matrix(jacobian.rows(), q_nrs.size());
124 for (
int j = 0; j < static_cast<int>(q_nrs.size()); ++j)
126 auto c =
static_cast<unsigned>(q_nrs[
static_cast<size_t>(j)]);
127 matrix.col(j) = jacobian.data.col(c);
133 KDL::Joint
convert(
const std::shared_ptr<const Joint>& joint)
135 KDL::Frame parent_joint =
convert(joint->parent_to_joint_origin_transform);
136 const std::string& name = joint->getName();
143 return KDL::Joint(name, KDL::Joint::None);
147 KDL::Vector axis =
convert(joint->axis);
148 return KDL::Joint{ name, parent_joint.p, parent_joint.M * axis, KDL::Joint::RotAxis };
153 return KDL::Joint{ name, parent_joint.p, parent_joint.M * axis, KDL::Joint::RotAxis };
157 KDL::Vector axis =
convert(joint->axis);
158 return KDL::Joint{ name, parent_joint.p, parent_joint.M * axis, KDL::Joint::TransAxis };
162 CONSOLE_BRIDGE_logWarn(
"Converting unknown joint type of joint '%s' into a fixed joint", name.c_str());
163 return KDL::Joint(name, KDL::Joint::None);
168 KDL::RigidBodyInertia
convert(
const std::shared_ptr<const Inertial>& inertial)
170 KDL::Frame origin =
convert(inertial->origin);
173 double kdl_mass = inertial->mass;
176 KDL::Vector kdl_com = origin.p;
180 KDL::RotationalInertia urdf_inertia =
181 KDL::RotationalInertia(inertial->ixx, inertial->iyy, inertial->izz, inertial->ixy, inertial->ixz, inertial->iyz);
185 KDL::RigidBodyInertia kdl_inertia_wrt_com_workaround =
186 origin.M * KDL::RigidBodyInertia(0, KDL::Vector::Zero(), urdf_inertia);
191 KDL::RotationalInertia kdl_inertia_wrt_com = kdl_inertia_wrt_com_workaround.getRotationalInertia();
193 return KDL::RigidBodyInertia(kdl_mass, kdl_com, kdl_inertia_wrt_com);
207 auto isometry_equal = [](
const Eigen::Isometry3d& iso_1,
const Eigen::Isometry3d& iso_2) {
208 return iso_1.isApprox(iso_2, 1e-5);
210 equal &= tesseract_common::isIdenticalMap<tesseract_common::TransformMap, Eigen::Isometry3d>(
222 struct kdl_tree_builder :
public boost::dfs_visitor<>
226 template <
class u,
class g>
232 KDL::RigidBodyInertia inert(0);
234 inert =
convert(link->inertial);
237 auto num_in_edges =
static_cast<int>(boost::in_degree(vertex, graph));
238 if (num_in_edges == 0)
240 std::size_t num_v = boost::num_vertices(graph);
241 std::size_t num_e = boost::num_edges(graph);
257 boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
258 boost::tie(ei, ei_end) = boost::in_edges(vertex, graph);
269 KDL::Joint kdl_jnt =
convert(parent_joint);
270 if (kdl_jnt.getType() != KDL::Joint::None)
286 KDL::Segment sgm(link->getName(), kdl_jnt,
convert(parent_joint->parent_to_joint_origin_transform), inert);
289 data_.
tree.addSegment(sgm, parent_joint->parent_link_name);
300 struct kdl_sub_tree_builder :
public boost::dfs_visitor<>
303 const std::vector<std::string>& joint_names,
304 const std::unordered_map<std::string, double>& joint_values,
308 for (
const auto& floating_joint_value : floating_joint_values)
312 template <
class u,
class g>
318 KDL::RigidBodyInertia inert(0);
320 inert =
convert(link->inertial);
323 auto num_in_edges =
static_cast<int>(boost::in_degree(vertex, graph));
324 if (num_in_edges == 0)
330 std::size_t num_v = boost::num_vertices(graph);
331 std::size_t num_e = boost::num_edges(graph);
342 boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
343 boost::tie(ei, ei_end) = boost::in_edges(vertex, graph);
347 KDL::Joint kdl_jnt =
convert(parent_joint);
350 convert(parent_joint->parent_to_joint_origin_transform);
352 KDL::Segment kdl_sgm(link->getName(), kdl_jnt, parent_to_joint, inert);
353 std::string parent_link_name = parent_joint->parent_link_name;
369 KDL::Segment world_sgm = KDL::Segment(parent_link_name,
370 KDL::Joint(world_joint_name, KDL::Joint::None),
372 KDL::RigidBodyInertia(0));
384 KDL::Segment sgm = KDL::Segment(link->getName(), kdl_jnt, parent_to_joint, inert);
387 data_.
tree.addSegment(sgm, parent_link_name);
402 KDL::Frame new_tree_parent_to_joint =
407 KDL::Segment sgm = KDL::Segment(parent_link_name,
408 KDL::Joint(new_joint_name, KDL::Joint::None),
409 new_tree_parent_to_joint,
410 KDL::RigidBodyInertia(0));
418 parent_to_joint = kdl_sgm.pose(0.0);
420 parent_to_joint = kdl_sgm.pose(
joint_values_.at(parent_joint->getName()));
422 kdl_jnt = KDL::Joint(parent_joint->getName(), KDL::Joint::None);
434 if (kdl_jnt.getType() != KDL::Joint::None)
438 KDL::Segment sgm = KDL::Segment(link->getName(), kdl_jnt, parent_to_joint, inert);
441 data_.
tree.addSegment(sgm, parent_link_name);
454 const std::unordered_map<std::string, double>&
joint_values_;
461 if (!scene_graph.isTree())
462 throw std::runtime_error(
"parseSubSceneGraph: currently only works if the scene graph is a tree.");
464 const std::string& root_name = scene_graph.getRoot();
468 data.tree = KDL::Tree(root_name);
471 if (root_link->inertial)
473 CONSOLE_BRIDGE_logWarn(
"The root link %s has an inertia specified in the URDF, but KDL does not "
474 "support a root link with an inertia. As a workaround, you can add an extra "
475 "dummy link to your URDF.",
481 std::map<SceneGraph::Vertex, size_t> index_map;
482 boost::associative_property_map<std::map<SceneGraph::Vertex, size_t>> prop_index_map(index_map);
485 Graph::vertex_iterator i, iend;
486 for (boost::tie(i, iend) = boost::vertices(scene_graph); i != iend; ++i, ++c)
487 boost::put(prop_index_map, *i, c);
489 boost::depth_first_search(
490 static_cast<const Graph&
>(scene_graph),
491 boost::visitor(builder).root_vertex(scene_graph.getVertex(root_name)).vertex_index_map(prop_index_map));
493 assert(data.link_names.size() == scene_graph.getLinks().size());
494 assert(data.active_joint_names.size() <= scene_graph.getJoints().size());
495 assert(data.active_link_names.size() < scene_graph.getLinks().size());
500 const std::vector<std::string>& joint_names,
501 const std::unordered_map<std::string, double>& joint_values,
504 if (!scene_graph.isTree())
505 throw std::runtime_error(
"parseSubSceneGraph: currently only works if the scene graph is a tree.");
508 data.tree = KDL::Tree(scene_graph.getRoot());
510 kdl_sub_tree_builder builder(data, joint_names, joint_values, floating_joint_values);
512 std::map<SceneGraph::Vertex, size_t> index_map;
513 boost::associative_property_map<std::map<SceneGraph::Vertex, size_t>> prop_index_map(index_map);
516 Graph::vertex_iterator i, iend;
517 for (boost::tie(i, iend) = boost::vertices(scene_graph); i != iend; ++i, ++c)
518 boost::put(prop_index_map, *i, c);
520 boost::depth_first_search(
static_cast<const Graph&
>(scene_graph),
521 boost::visitor(builder)
522 .root_vertex(scene_graph.getVertex(scene_graph.getRoot()))
523 .vertex_index_map(prop_index_map));
525 if (data.tree.getNrOfJoints() != joint_names.size())
526 throw std::runtime_error(
"parseSubSceneGraph: failed to generate sub-tree given the provided joint names.");