29 #include <boost/graph/directed_graph.hpp>
30 #include <boost/graph/depth_first_search.hpp>
31 #include <boost/graph/breadth_first_search.hpp>
32 #include <boost/graph/adj_list_serialize.hpp>
33 #include <boost/graph/dijkstra_shortest_paths.hpp>
34 #include <boost/graph/undirected_graph.hpp>
35 #include <boost/graph/copy.hpp>
36 #include <boost/serialization/access.hpp>
37 #include <boost/serialization/base_object.hpp>
38 #include <boost/serialization/nvp.hpp>
39 #include <boost/serialization/shared_ptr.hpp>
40 #include <boost/serialization/split_member.hpp>
42 #include <console_bridge/console.h>
43 #if (BOOST_VERSION >= 107400) && (BOOST_VERSION < 107500)
44 #include <boost/serialization/library_version_type.hpp>
46 #include <boost/serialization/unordered_map.hpp>
47 #include <boost/serialization/utility.hpp>
62 template <
class e,
class g>
76 template <
class u,
class g>
79 auto num_in_edges =
static_cast<int>(boost::in_degree(vertex, graph));
94 if (num_in_edges == 0)
98 if (num_in_edges == 0 && boost::out_degree(vertex, graph) == 0)
105 template <
class e,
class g>
120 template <
class u,
class g>
133 std::map<SceneGraph::Vertex, boost::default_color_type>& color_map,
134 const std::string& base_link_name,
135 const std::vector<std::string>& terminate_on_links)
143 template <
class u,
class g>
146 for (
auto vd : boost::make_iterator_range(adjacent_vertices(vertex, graph)))
150 color_map_[vd] = boost::default_color_type::black_color;
154 template <
class u,
class g>
165 std::map<SceneGraph::Vertex, boost::default_color_type>&
color_map_;
171 boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, VertexProperty, EdgeProperty, GraphProperty>;
180 template <
typename Vertex1,
typename Vertex2>
186 mutable typename boost::property_map<UGraph, boost::vertex_all_t>::type
vertex_all_map2;
191 boost::set_property(
static_cast<Graph&
>(*
this), boost::graph_name, name);
196 , link_map_(std::move(other.link_map_))
197 , joint_map_(std::move(other.joint_map_))
198 , acm_(std::move(other.acm_))
200 rebuildLinkAndJointMaps();
205 Graph::operator=(other);
207 link_map_ = std::move(other.link_map_);
208 joint_map_ = std::move(other.joint_map_);
209 acm_ = std::move(other.acm_);
211 rebuildLinkAndJointMaps();
218 auto cloned_graph = std::make_unique<SceneGraph>();
222 cloned_graph->addLink(link->clone(link->getName()));
223 cloned_graph->setLinkVisibility(link->getName(),
getLinkVisibility(link->getName()));
228 cloned_graph->addJoint(joint->clone(joint->getName()));
232 cloned_graph->setName(
getName());
233 cloned_graph->setRoot(
getRoot());
243 acm_->clearAllowedCollisions();
248 boost::set_property(
static_cast<Graph&
>(*
this), boost::graph_name, name);
253 return boost::get_property(
static_cast<const Graph&
>(*
this), boost::graph_name);
275 auto link_ptr = std::make_shared<tesseract_scene_graph::Link>(link.
clone());
283 CONSOLE_BRIDGE_logWarn(
"Tried to add link (%s) with same name as an existing link.", link.
getName().c_str());
289 CONSOLE_BRIDGE_logWarn(
"Tried to add joint (%s) with same name as an existing joint.", joint.
getName().c_str());
304 auto found =
link_map_.find(link_ptr->getName());
305 bool link_exists = (found !=
link_map_.end());
306 if (link_exists && !replace_allowed)
309 if (link_exists && replace_allowed)
311 found->second.first = link_ptr;
312 boost::property_map<Graph, boost::vertex_link_t>::type param = get(
boost::vertex_link,
static_cast<Graph&
>(*
this));
313 param[found->second.second] = link_ptr;
318 boost::property<boost::vertex_link_visible_t, bool, boost::property<boost::vertex_link_collision_enabled_t, bool>>
321 Vertex v = boost::add_vertex(info,
static_cast<Graph&
>(*
this));
322 link_map_[link_ptr->getName()] = std::make_pair(link_ptr, v);
338 return found->second.first;
343 std::vector<Link::ConstPtr> links;
346 links.push_back(link.second.first);
353 std::vector<Link::ConstPtr> links;
357 if (boost::out_degree(link.second.second, *
this) == 0)
358 links.push_back(link.second.first);
369 CONSOLE_BRIDGE_logWarn(
"Tried to remove link (%s) from scene graph that does not exist.", name.c_str());
377 boost::clear_vertex(vertex, *
this);
381 Graph::edge_iterator ei, ei_end;
382 for (boost::tie(ei, ei_end) = boost::edges(*
this); ei != ei_end; ++ei)
386 joint_map_[joint->getName()] = std::make_pair(joint, e);
390 boost::remove_vertex(found->second.second,
static_cast<Graph&
>(*
this));
398 for (
const auto& link_name : adjacent_link_names)
412 CONSOLE_BRIDGE_logWarn(
"Tried to move link (%s) in scene graph that does not exist.",
419 CONSOLE_BRIDGE_logWarn(
"Tried to move link (%s) in scene graph that parent link (%s) which does not exist.",
426 for (
const auto& joint : joints)
434 boost::property_map<Graph, boost::vertex_link_visible_t>::type param =
441 boost::property_map<Graph, boost::vertex_link_visible_t>::const_type param =
448 boost::property_map<Graph, boost::vertex_link_collision_enabled_t>::type param =
455 boost::property_map<Graph, boost::vertex_link_collision_enabled_t>::const_type param =
462 auto joint_ptr = std::make_shared<tesseract_scene_graph::Joint>(joint.
clone());
468 auto parent =
link_map_.find(joint_ptr->parent_link_name);
469 auto child =
link_map_.find(joint_ptr->child_link_name);
470 auto found =
joint_map_.find(joint_ptr->getName());
474 CONSOLE_BRIDGE_logWarn(
"Parent link (%s) does not exist in scene graph.", joint_ptr->parent_link_name.c_str());
480 CONSOLE_BRIDGE_logWarn(
"Child link (%s) does not exist in scene graph.", joint_ptr->child_link_name.c_str());
486 CONSOLE_BRIDGE_logWarn(
"Joint with name (%s) already exists in scene graph.", joint_ptr->getName().c_str());
493 CONSOLE_BRIDGE_logWarn(
"Joint with name (%s) requires limits because it is not of type fixed, floating or "
495 joint_ptr->getName().c_str());
503 if (joint_ptr->limits ==
nullptr)
505 joint_ptr->limits = std::make_shared<JointLimits>(-4 * M_PI, 4 * M_PI, 0, 2, 1, 1000);
509 joint_ptr->limits->lower = -4 * M_PI;
510 joint_ptr->limits->upper = +4 * M_PI;
514 double d = joint_ptr->parent_to_joint_origin_transform.translation().norm();
517 std::pair<Edge, bool> e =
518 boost::add_edge(parent->second.second, child->second.second, info,
static_cast<Graph&
>(*
this));
519 assert(e.second ==
true);
520 joint_map_[joint_ptr->getName()] = std::make_pair(joint_ptr, e.first);
531 return found->second.first;
542 boost::remove_edge(found->second.second,
static_cast<Graph&
>(*
this));
549 std::string child_link_name = found->second.first->child_link_name;
560 auto found_parent_link =
link_map_.find(parent_link);
564 CONSOLE_BRIDGE_logWarn(
"Tried to move Joint with name (%s) which does not exist in scene graph.", name.c_str());
568 if (found_parent_link ==
link_map_.end())
570 CONSOLE_BRIDGE_logWarn(
"Tried to move Joint with name (%s) to parent link (%s) which does not exist in scene "
573 parent_link.c_str());
581 joint->parent_link_name = parent_link;
587 std::vector<Joint::ConstPtr> joints;
590 joints.push_back(joint.second.first);
597 std::vector<Joint::ConstPtr> joints;
602 joints.push_back(joint.second.first);
614 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint origin with name (%s) which does not exist in scene graph.",
621 joint->parent_to_joint_origin_transform = new_origin;
625 double d = joint->parent_to_joint_origin_transform.translation().norm();
626 boost::put(boost::edge_weight_t(), *
this, e, d);
637 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint limit with name (%s) which does not exist in scene graph.",
644 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint limits for a fixed or floating joint type.", name.c_str());
648 if (found->second.first->limits ==
nullptr)
649 found->second.first->limits = std::make_shared<JointLimits>();
651 found->second.first->limits->lower = limits.
lower;
652 found->second.first->limits->upper = limits.
upper;
653 found->second.first->limits->effort = limits.
effort;
654 found->second.first->limits->velocity = limits.
velocity;
655 found->second.first->limits->acceleration = limits.
acceleration;
656 found->second.first->limits->jerk = limits.
jerk;
667 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Position limits with name (%s) which does not exist in scene graph.",
674 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Position limits for a fixed or floating joint type.", name.c_str());
678 found->second.first->limits->lower = lower;
679 found->second.first->limits->upper = upper;
690 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Velocity limit with name (%s) which does not exist in scene graph.",
697 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Velocity limit for a fixed or floating joint type.", name.c_str());
701 found->second.first->limits->velocity = limit;
711 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Acceleration limit with name (%s) which does not exist in scene "
719 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Acceleration limit for a fixed or floating joint type.",
724 if (found->second.first->limits ==
nullptr)
725 found->second.first->limits = std::make_shared<JointLimits>();
727 found->second.first->limits->acceleration = limit;
738 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Jerk limit with name (%s) which does not exist in scene "
746 CONSOLE_BRIDGE_logWarn(
"Tried to change Joint Jerk limit for a fixed or floating joint type.", name.c_str());
750 if (found->second.first->limits ==
nullptr)
751 found->second.first->limits = std::make_shared<JointLimits>();
753 found->second.first->limits->jerk = limit;
764 CONSOLE_BRIDGE_logWarn(
"SceneGraph::getJointLimits tried to find Joint with name (%s) which does not exist in "
769 return found->second.first->limits;
774 acm_ = std::move(acm);
778 const std::string& link_name2,
779 const std::string& reason)
781 acm_->addAllowedCollision(link_name1, link_name2, reason);
786 acm_->removeAllowedCollision(link_name1, link_name2);
795 return acm_->isCollisionAllowed(link_name1, link_name2);
808 Vertex v = boost::source(e, *
this);
815 Vertex v = boost::target(e, *
this);
821 std::vector<Joint::ConstPtr> joints;
825 auto num_in_edges =
static_cast<int>(boost::in_degree(vertex, *
this));
826 if (num_in_edges == 0)
829 boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
830 for (boost::tie(ei, ei_end) = boost::in_edges(vertex, *
this); ei != ei_end; ++ei)
841 std::vector<Joint::ConstPtr> joints;
845 auto num_out_edges =
static_cast<int>(boost::out_degree(vertex, *
this));
846 if (num_out_edges == 0)
849 boost::graph_traits<Graph>::out_edge_iterator eo, eo_end;
850 for (boost::tie(eo, eo_end) = boost::out_edges(vertex, *
this); eo != eo_end; ++eo)
863 const auto& graph =
static_cast<const Graph&
>(*this);
866 std::map<Vertex, size_t> index_map;
867 boost::associative_property_map<std::map<Vertex, size_t>> prop_index_map(index_map);
870 Graph::vertex_iterator i, iend;
871 for (boost::tie(i, iend) = boost::vertices(graph); i != iend; ++i, ++c)
872 boost::put(prop_index_map, *i, c);
875 boost::depth_first_search(
static_cast<const Graph&
>(*
this), boost::visitor(vis).vertex_index_map(prop_index_map));
881 const auto& graph =
static_cast<const Graph&
>(*this);
884 std::map<Vertex, size_t> index_map;
885 boost::associative_property_map<std::map<Vertex, size_t>> prop_index_map(index_map);
888 Graph::vertex_iterator i, iend;
889 for (boost::tie(i, iend) = boost::vertices(graph); i != iend; ++i, ++c)
890 boost::put(prop_index_map, *i, c);
893 boost::depth_first_search(
static_cast<const Graph&
>(*
this), boost::visitor(vis).vertex_index_map(prop_index_map));
899 std::vector<std::string> link_names;
901 for (
auto* vd : boost::make_iterator_range(adjacent_vertices(v, *
this)))
909 std::vector<std::string> link_names;
911 for (
auto* vd : boost::make_iterator_range(inv_adjacent_vertices(v, *
this)))
923 child_link_names.erase(child_link_names.begin());
924 return child_link_names;
929 const auto& graph =
static_cast<const Graph&
>(*this);
931 Vertex v = boost::target(e, graph);
937 std::set<std::string> link_names;
938 for (
const auto& name : names)
941 link_names.insert(joint_children.begin(), joint_children.end());
944 return std::vector<std::string>{ link_names.begin(), link_names.end() };
947 std::unordered_map<std::string, std::string>
950 std::map<Vertex, size_t> index_map;
951 boost::associative_property_map<std::map<Vertex, size_t>> prop_index_map(index_map);
953 std::map<Vertex, boost::default_color_type> color_map;
954 boost::associative_property_map<std::map<Vertex, boost::default_color_type>> prop_color_map(color_map);
957 Graph::vertex_iterator i, iend;
958 for (boost::tie(i, iend) = boost::vertices(*
this); i != iend; ++i, ++c)
959 boost::put(prop_index_map, *i, c);
961 std::unordered_map<std::string, std::string> adjacency_map;
962 for (
const auto& link_name : link_names)
968 boost::breadth_first_search(
971 boost::visitor(vis).root_vertex(start_vertex).vertex_index_map(prop_index_map).color_map(prop_color_map));
974 return adjacency_map;
979 std::ofstream dot_file(path);
980 if (!dot_file.is_open())
982 throw std::runtime_error(
"Failed to open file: " + path);
985 dot_file <<
"digraph D {\n"
988 <<
" ratio=\"fill\"\n"
989 <<
" edge[style=\"bold\"]\n"
990 <<
" node[shape=\"circle\"]\n";
992 const auto& graph =
static_cast<const Graph&
>(*this);
993 Graph::edge_iterator ei, ei_end;
994 for (boost::tie(ei, ei_end) = boost::edges(graph); ei != ei_end; ++ei)
997 Vertex u = boost::source(e, graph);
998 Vertex v = boost::target(e, graph);
1001 dot_file <<
'"' << boost::get(
boost::vertex_link, graph)[u]->getName() <<
'"' <<
" -> " <<
'"'
1002 << boost::get(
boost::vertex_link, graph)[v]->getName() <<
'"' <<
"[label=\"" << joint->getName() <<
"\n("
1003 << joint->type <<
")\", color=\"black\"]";
1015 std::map<Graph::vertex_descriptor, size_t> index_map;
1016 boost::associative_property_map<std::map<Graph::vertex_descriptor, size_t>> prop_index_map(index_map);
1020 Graph::vertex_iterator i, iend;
1021 for (boost::tie(i, iend) = boost::vertices(*
this); i != iend; ++i, ++c)
1022 boost::put(prop_index_map, *i, c);
1026 boost::copy_graph(*
this, graph, boost::vertex_index_map(prop_index_map).vertex_copy(v_copier));
1029 UGraph::vertex_descriptor s_root =
getVertex(root);
1030 UGraph::vertex_descriptor s_tip =
getVertex(tip);
1032 auto prop_weight_map = boost::get(boost::edge_weight, graph);
1034 std::map<UGraph::vertex_descriptor, UGraph::vertex_descriptor> predicessor_map;
1035 boost::associative_property_map<std::map<UGraph::vertex_descriptor, UGraph::vertex_descriptor>> prop_predicessor_map(
1038 std::map<UGraph::vertex_descriptor, double> distance_map;
1039 boost::associative_property_map<std::map<UGraph::vertex_descriptor, double>> prop_distance_map(distance_map);
1041 std::map<UGraph::vertex_descriptor, size_t> u_index_map;
1042 boost::associative_property_map<std::map<UGraph::vertex_descriptor, size_t>> u_prop_index_map(u_index_map);
1046 UGraph::vertex_iterator i, iend;
1047 for (boost::tie(i, iend) = boost::vertices(graph); i != iend; ++i, ++c)
1056 boost::put(u_prop_index_map, *i, c);
1060 dijkstra_shortest_paths(graph,
1062 prop_predicessor_map,
1067 boost::closed_plus<double>(),
1068 (std::numeric_limits<double>::max)(),
1070 boost::default_dijkstra_visitor());
1073 path.
links.reserve(predicessor_map.size());
1074 path.
joints.reserve(predicessor_map.size());
1077 for (
Vertex u = predicessor_map[s_tip];
1079 s_tip = u, u = predicessor_map[s_tip])
1085 path.
joints.push_back(joint->getName());
1089 path.
links.push_back(root);
1090 std::reverse(path.
links.begin(), path.
links.end());
1095 CONSOLE_BRIDGE_logDebug(
"distances and parents:");
1096 UGraph::vertex_iterator vi, vend;
1097 for (boost::tie(vi, vend) = boost::vertices(graph); vi != vend; ++vi)
1099 CONSOLE_BRIDGE_logDebug(
"distance(%s) = %f, parent(%s) = %s",
1113 throw std::runtime_error(
"SceneGraph, vertex with name '" + name +
"' does not exist!");
1115 return found->second.second;
1122 throw std::runtime_error(
"SceneGraph, edge with name '" + name +
"' does not exist!");
1124 return found->second.second;
1132 return link->
clone(prefix + link->getName());
1136 const std::string& prefix)
1138 auto ret = joint->
clone(prefix + joint->getName());
1140 ret.parent_link_name = prefix + joint->parent_link_name;
1148 return std::make_shared<tesseract_common::AllowedCollisionMatrix>(*acm);
1150 auto new_acm = std::make_shared<tesseract_common::AllowedCollisionMatrix>();
1151 for (
const auto& entry : acm->getAllAllowedCollisions())
1152 new_acm->addAllowedCollision(prefix + entry.first.first, prefix + entry.first.second, entry.second);
1163 for (
const auto& link : scene_graph.
getLinks())
1167 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph, link names are not unique: %s",
1168 (prefix + link->getName()).c_str());
1174 for (
const auto& joint : scene_graph.
getJoints())
1178 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph, joint names are not unique: %s",
1179 (prefix + joint->getName()).c_str());
1184 for (
const auto& link : scene_graph.
getLinks())
1186 auto new_link = std::make_shared<Link>(clone_prefix(link, prefix));
1190 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph link: %s", link->getName().c_str());
1199 for (
const auto& joint : scene_graph.
getJoints())
1201 auto new_joint = std::make_shared<Joint>(clone_prefix(joint, prefix));
1205 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph joint: %s", joint->getName().c_str());
1221 const std::string& prefix)
1227 if (!prefix.empty())
1228 child_link.erase(0, prefix.length());
1230 if (
getLink(parent_link) ==
nullptr || scene_graph.
getLink(child_link) ==
nullptr)
1232 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph, provided joint link names do not exist in inserted graph!");
1238 CONSOLE_BRIDGE_logError(
"Failed to add inserted graph, provided joint name %s already exists!",
1255 Graph::vertex_iterator i, iend;
1256 for (boost::tie(i, iend) = boost::vertices(*
this); i != iend; ++i)
1259 link_map_[link->getName()] = std::make_pair(link, *i);
1264 Graph::edge_iterator i, iend;
1265 for (boost::tie(i, iend) = boost::edges(*
this); i != iend; ++i)
1268 joint_map_[joint->getName()] = std::make_pair(joint, *i);
1275 const auto& graph =
static_cast<const Graph&
>(*this);
1276 std::vector<std::string> child_link_names;
1278 std::map<Vertex, size_t> index_map;
1279 boost::associative_property_map<std::map<Vertex, size_t>> prop_index_map(index_map);
1281 std::map<Vertex, boost::default_color_type> color_map;
1282 boost::associative_property_map<std::map<Vertex, boost::default_color_type>> prop_color_map(color_map);
1285 Graph::vertex_iterator i, iend;
1286 for (boost::tie(i, iend) = boost::vertices(graph); i != iend; ++i, ++c)
1287 boost::put(prop_index_map, *i, c);
1291 boost::breadth_first_search(
1294 boost::visitor(vis).root_vertex(start_vertex).vertex_index_map(prop_index_map).color_map(prop_color_map));
1296 return child_link_names;
1303 auto link_pair_equal = [](
const std::pair<const Link::Ptr, Vertex>& v1,
const std::pair<Link::Ptr, Vertex>& v2) {
1306 auto joint_pair_equal = [](
const std::pair<const Joint::Ptr, Edge>& v1,
const std::pair<Joint::Ptr, Edge>& v2) {
1312 equal &= isIdenticalMap<std::unordered_map<std::string, std::pair<Link::Ptr, Vertex>>, std::pair<Link::Ptr, Vertex>>(
1314 equal &= isIdenticalMap<std::unordered_map<std::string, std::pair<Joint::Ptr, Edge>>, std::pair<Joint::Ptr, Edge>>(
1321 template <
class Archive>
1325 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(
Graph);
1326 ar& BOOST_SERIALIZATION_NVP(
acm_);
1329 template <
class Archive>
1333 ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(
Graph);
1334 ar& BOOST_SERIALIZATION_NVP(
acm_);
1339 template <
class Archive>
1342 boost::serialization::split_member(ar, *
this, version);
1349 for (
const auto& l : path.
links)
1350 os <<
" " << l <<
"\n";
1354 for (
const auto& j : path.
joints)
1355 os <<
" " << j <<
"\n";
1357 os <<
"Active Joints:"
1360 os <<
" " << j <<
"\n";