41 #include <moveit_msgs/srv/get_planning_scene.hpp>
44 #if __has_include(<tf2/exceptions.hpp>)
45 #include <tf2/exceptions.hpp>
47 #include <tf2/exceptions.h>
49 #if __has_include(<tf2/LinearMath/Transform.hpp>)
50 #include <tf2/LinearMath/Transform.hpp>
52 #include <tf2/LinearMath/Transform.h>
54 #include <tf2_eigen/tf2_eigen.hpp>
55 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
57 #include <boost/algorithm/string/join.hpp>
60 #include <std_msgs/msg/string.hpp>
63 using namespace std::chrono_literals;
65 static const rclcpp::Logger
LOGGER = rclcpp::get_logger(
"moveit_ros.planning_scene_monitor.planning_scene_monitor");
69 const std::string PlanningSceneMonitor::DEFAULT_JOINT_STATES_TOPIC =
"joint_states";
70 const std::string PlanningSceneMonitor::DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC =
"attached_collision_object";
71 const std::string PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC =
"collision_object";
72 const std::string PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC =
"planning_scene_world";
73 const std::string PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_TOPIC =
"planning_scene";
74 const std::string PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_SERVICE =
"get_planning_scene";
75 const std::string PlanningSceneMonitor::MONITORED_PLANNING_SCENE_TOPIC =
"monitored_planning_scene";
77 PlanningSceneMonitor::PlanningSceneMonitor(
const rclcpp::Node::SharedPtr& node,
const std::string& robot_description,
78 const std::string&
name)
84 const planning_scene::PlanningScenePtr&
scene,
85 const std::string& robot_description,
const std::string&
name)
92 const robot_model_loader::RobotModelLoaderPtr& rm_loader,
93 const std::string&
name)
99 const planning_scene::PlanningScenePtr&
scene,
100 const robot_model_loader::RobotModelLoaderPtr& rm_loader,
101 const std::string&
name)
102 : monitor_name_(
name)
104 , private_executor_(std::make_shared<
rclcpp::executors::SingleThreadedExecutor>())
105 , tf_buffer_(std::make_shared<
tf2_ros::Buffer>(node->get_clock()))
106 , dt_state_update_(0.0)
107 , shape_transform_cache_lookup_wait_time_(0, 0)
108 , rm_loader_(rm_loader)
110 std::vector<std::string> new_args = rclcpp::NodeOptions().arguments();
111 new_args.push_back(
"--ros-args");
112 new_args.push_back(
"-r");
114 new_args.push_back(std::string(
"__node:=") +
node_->get_name() +
"_private_" +
115 std::to_string(
reinterpret_cast<std::size_t
>(
this)));
116 new_args.push_back(
"--");
117 pnode_ = std::make_shared<rclcpp::Node>(
"_",
node_->get_namespace(), rclcpp::NodeOptions().arguments(new_args));
127 use_sim_time_ = node->get_parameter(
"use_sim_time").as_bool();
151 robot_model_.reset();
160 if (rm_loader_->getModel())
162 robot_model_ = rm_loader_->getModel();
168 scene_ = std::make_shared<planning_scene::PlanningScene>(rm_loader_->getModel());
176 scene_->getCollisionEnvNonConst()->setLinkPadding(it.first, it.second);
180 scene_->getCollisionEnvNonConst()->setLinkScale(it.first, it.second);
185 RCLCPP_ERROR(LOGGER,
"Configuration of planning scene failed");
198 scene_->setCollisionObjectUpdateCallback(
206 RCLCPP_ERROR(LOGGER,
"Robot model not loaded");
213 last_robot_state_update_wall_time_ = std::chrono::system_clock::now();
214 dt_state_update_ = std::chrono::duration<double>(0.03);
216 double temp_wait_time = 0.05;
219 node_->get_parameter_or(
robot_description_ +
"_planning.shape_transform_cache_lookup_wait_time", temp_wait_time,
222 shape_transform_cache_lookup_wait_time_ = rclcpp::Duration::from_seconds(temp_wait_time);
224 state_update_pending_.store(
false);
226 using std::chrono::nanoseconds;
227 state_update_timer_ =
pnode_->create_wall_timer(dt_state_update_, [
this]() {
return stateUpdateTimerCallback(); });
236 rcl_interfaces::msg::ParameterDescriptor desc;
238 return pnode_->declare_parameter(param_name, default_val, desc);
244 bool publish_planning_scene =
245 declare_parameter(
"publish_planning_scene",
false,
"Set to True to publish Planning Scenes");
246 bool publish_geometry_updates =
declare_parameter(
"publish_geometry_updates",
false,
247 "Set to True to publish geometry updates of the planning scene");
248 bool publish_state_updates =
249 declare_parameter(
"publish_state_updates",
false,
"Set to True to publish state updates of the planning scene");
251 "publish_transforms_updates",
false,
"Set to True to publish transform updates of the planning scene");
253 "publish_planning_scene_hz", 4.0,
"Set the maximum frequency at which planning scene updates are published");
254 updatePublishSettings(publish_geometry_updates, publish_state_updates, publish_transform_updates,
255 publish_planning_scene, publish_planning_scene_hz);
257 catch (
const rclcpp::exceptions::InvalidParameterTypeException& e)
259 RCLCPP_ERROR_STREAM(LOGGER,
"Invalid parameter type in PlanningSceneMonitor: " << e.what());
260 RCLCPP_ERROR(LOGGER,
"Dynamic publishing parameters won't be available");
264 auto psm_parameter_set_callback = [
this](
const std::vector<rclcpp::Parameter>& parameters) ->
auto
266 auto result = rcl_interfaces::msg::SetParametersResult();
267 result.successful =
true;
269 bool publish_planning_scene =
false, publish_geometry_updates =
false, publish_state_updates =
false,
270 publish_transform_updates =
false;
271 double publish_planning_scene_hz = 4.0;
272 bool declared_params_valid =
pnode_->get_parameter(
"publish_planning_scene", publish_planning_scene) &&
273 pnode_->get_parameter(
"publish_geometry_updates", publish_geometry_updates) &&
274 pnode_->get_parameter(
"publish_state_updates", publish_state_updates) &&
275 pnode_->get_parameter(
"publish_transforms_updates", publish_transform_updates) &&
276 pnode_->get_parameter(
"publish_planning_scene_hz", publish_planning_scene_hz);
278 if (!declared_params_valid)
280 RCLCPP_ERROR(LOGGER,
"Initially declared parameters are invalid - failed to process update callback");
281 result.successful =
false;
285 for (
const auto& parameter : parameters)
287 const auto&
name = parameter.get_name();
288 const auto&
type = parameter.get_type();
293 RCLCPP_ERROR(LOGGER,
"Invalid parameter in PlanningSceneMonitor parameter callback");
294 result.successful =
false;
299 if (
name ==
"planning_scene_monitor.publish_planning_scene")
300 publish_planning_scene = parameter.as_bool();
301 else if (
name ==
"planning_scene_monitor.publish_geometry_updates")
302 publish_geometry_updates = parameter.as_bool();
303 else if (
name ==
"planning_scene_monitor.publish_state_updates")
304 publish_state_updates = parameter.as_bool();
305 else if (
name ==
"planning_scene_monitor.publish_transforms_updates")
306 publish_transform_updates = parameter.as_bool();
307 else if (
name ==
"planning_scene_monitor.publish_planning_scene_hz")
308 publish_planning_scene_hz = parameter.as_double();
311 if (result.successful)
312 updatePublishSettings(publish_geometry_updates, publish_state_updates, publish_transform_updates,
313 publish_planning_scene, publish_planning_scene_hz);
317 callback_handler_ =
pnode_->add_on_set_parameters_callback(psm_parameter_set_callback);
338 scene_->setCollisionObjectUpdateCallback(
339 [
this](
const collision_detection::World::ObjectConstPtr&
object,
347 RCLCPP_WARN(LOGGER,
"Diff monitoring was stopped while publishing planning scene diffs. "
348 "Stopping planning scene diff publisher");
358 if (!
scene_->getName().empty())
360 if (
scene_->getName()[
scene_->getName().length() - 1] ==
'+')
373 std::unique_ptr<std::thread> copy;
379 RCLCPP_INFO(LOGGER,
"Stopped publishing maintained planning scene.");
384 const std::string& planning_scene_topic)
390 RCLCPP_INFO(LOGGER,
"Publishing maintained planning scene on '%s'", planning_scene_topic.c_str());
396 void PlanningSceneMonitor::scenePublishingThread()
398 RCLCPP_DEBUG(LOGGER,
"Started scene publishing thread ...");
402 moveit_msgs::msg::PlanningScene msg;
407 scene_->getPlanningSceneMsg(msg);
410 RCLCPP_DEBUG(LOGGER,
"Published the full planning scene: '%s'", msg.name.c_str());
415 moveit_msgs::msg::PlanningScene msg;
416 bool publish_msg =
false;
417 bool is_full =
false;
434 scene_->getPlanningSceneDiffMsg(msg);
437 msg.robot_state.attached_collision_objects.clear();
438 msg.robot_state.is_diff =
true;
453 scene_->setCollisionObjectUpdateCallback(
454 [
this](
const collision_detection::World::ObjectConstPtr&
object,
466 scene_->getPlanningSceneMsg(msg);
479 RCLCPP_DEBUG(LOGGER,
"Published full planning scene: '%s'", msg.name.c_str());
507 bool sceneIsParentOf(
const planning_scene::PlanningSceneConstPtr&
scene,
513 return sceneIsParentOf(
scene->getParent(), possible_parent);
534 update_callback(update_type);
543 RCLCPP_FATAL_STREAM(LOGGER,
"requestPlanningSceneState() to self-provided service '" << service_name <<
"'");
544 throw std::runtime_error(
"requestPlanningSceneState() to self-provided service: " + service_name);
547 auto client =
pnode_->create_client<moveit_msgs::srv::GetPlanningScene>(service_name);
548 auto srv = std::make_shared<moveit_msgs::srv::GetPlanningScene::Request>();
549 srv->components.components = srv->components.SCENE_SETTINGS | srv->components.ROBOT_STATE |
550 srv->components.ROBOT_STATE_ATTACHED_OBJECTS | srv->components.WORLD_OBJECT_NAMES |
551 srv->components.WORLD_OBJECT_GEOMETRY | srv->components.OCTOMAP |
552 srv->components.TRANSFORMS | srv->components.ALLOWED_COLLISION_MATRIX |
553 srv->components.LINK_PADDING_AND_SCALING | srv->components.OBJECT_COLORS;
556 RCLCPP_DEBUG(LOGGER,
"Waiting for GetPlanningScene service `%s` to exist.", service_name.c_str());
557 if (client->wait_for_service(std::chrono::seconds(5)))
559 RCLCPP_DEBUG(LOGGER,
"Sending service request to `%s`.", service_name.c_str());
560 auto service_result = client->async_send_request(srv);
561 const auto service_result_status = service_result.wait_for(std::chrono::seconds(5));
562 if (service_result_status == std::future_status::ready)
564 RCLCPP_DEBUG(LOGGER,
"Service request succeeded, applying new planning scene");
568 if (service_result_status == std::future_status::timeout)
570 RCLCPP_INFO(LOGGER,
"GetPlanningScene service call to %s timed out. at %s:%d", service_name.c_str(), __FILE__,
578 "Failed to call service %s, have you launched move_group or called psm.providePlanningSceneService()?",
579 service_name.c_str());
588 service_name, [
this](
const moveit_msgs::srv::GetPlanningScene::Request::SharedPtr& req,
589 const moveit_msgs::srv::GetPlanningScene::Response::SharedPtr& res) {
590 return getPlanningSceneServiceCallback(req, res);
594 void PlanningSceneMonitor::getPlanningSceneServiceCallback(
595 const moveit_msgs::srv::GetPlanningScene::Request::SharedPtr& req,
596 const moveit_msgs::srv::GetPlanningScene::Response::SharedPtr& res)
598 if (req->components.components & moveit_msgs::msg::PlanningSceneComponents::TRANSFORMS)
601 moveit_msgs::msg::PlanningSceneComponents all_components;
602 all_components.components = UINT_MAX;
605 scene_->getPlanningSceneMsg(res->scene, req->components.components ? req->components : all_components);
608 void PlanningSceneMonitor::updatePublishSettings(
bool publish_geom_updates,
bool publish_state_updates,
609 bool publish_transform_updates,
bool publish_planning_scene,
610 double publish_planning_scene_hz)
613 if (publish_geom_updates)
616 if (publish_state_updates)
619 if (publish_transform_updates)
622 if (publish_planning_scene)
631 void PlanningSceneMonitor::newPlanningSceneCallback(
const moveit_msgs::msg::PlanningScene::ConstSharedPtr&
scene)
638 bool removed =
false;
641 removed =
scene_->getWorldNonConst()->removeObject(
scene_->OCTOMAP_NS);
651 RCLCPP_WARN(LOGGER,
"Unable to clear octomap since no octomap monitor has been initialized");
667 std::string old_scene_name;
675 RCLCPP_DEBUG(LOGGER,
"scene update %f robot stamp: %f", fmod(
last_update_time_.seconds(), 10.),
677 old_scene_name =
scene_->getName();
682 if (
scene.robot_state.is_diff)
698 if (!
scene.is_diff &&
scene.world.octomap.octomap.data.empty())
705 robot_model_ =
scene_->getRobotModel();
717 bool no_other_scene_upd = (
scene.name.empty() ||
scene.name == old_scene_name) &&
718 scene.allowed_collision_matrix.entry_names.empty() &&
scene.link_padding.empty() &&
719 scene.link_scale.empty();
720 if (no_other_scene_upd)
726 if (!
scene.fixed_frame_transforms.empty())
732 if (!
scene.robot_state.attached_collision_objects.empty() || !
scene.robot_state.is_diff)
742 const moveit_msgs::msg::PlanningSceneWorld::ConstSharedPtr& world)
750 scene_->getWorldNonConst()->clearObjects();
751 scene_->processPlanningSceneWorldMsg(*world);
754 if (world->octomap.octomap.data.empty())
775 if (!
scene_->processCollisionObjectMsg(*obj))
789 scene_->processAttachedCollisionObjectMsg(*obj);
803 const std::vector<const moveit::core::LinkModel*>& links =
getRobotModel()->getLinkModelsWithCollisionGeometry();
804 auto start = std::chrono::system_clock::now();
808 std::vector<shapes::ShapeConstPtr>
shapes = link->getShapes();
809 for (std::size_t j = 0; j <
shapes.size(); ++j)
814 shapes::Mesh* m =
static_cast<shapes::Mesh*
>(
shapes[j]->clone());
815 m->mergeVertices(1e-4);
824 if (!warned && ((std::chrono::system_clock::now() - start) > std::chrono::seconds(30)))
826 RCLCPP_WARN(LOGGER,
"It is likely there are too many vertices in collision geometry");
840 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>>>& link_shape_handle :
842 for (std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>& it : link_shape_handle.second)
856 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>>>& attached_body_shape_handle :
858 for (std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>& it : attached_body_shape_handle.second)
869 std::vector<const moveit::core::AttachedBody*> ab;
870 scene_->getCurrentState().getAttachedBodies(ab);
883 for (std::pair<
const std::string, std::vector<std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*>>>&
885 for (std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*>& it :
886 collision_body_shape_handle.second)
896 for (
const std::pair<const std::string, collision_detection::World::ObjectPtr>& it : *
scene_->getWorld())
907 for (std::size_t i = 0; i < attached_body->
getShapes().size(); ++i)
909 if (attached_body->
getShapes()[i]->type == shapes::PLANE || attached_body->
getShapes()[i]->type == shapes::OCTREE)
919 RCLCPP_DEBUG(LOGGER,
"Excluding attached body '%s' from monitored octomap", attached_body->
getName().c_str());
932 for (std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>& shape_handle : it->second)
934 RCLCPP_DEBUG(LOGGER,
"Including attached body '%s' in monitored octomap", attached_body->
getName().c_str());
947 for (std::size_t i = 0; i < obj->shapes_.size(); ++i)
949 if (obj->shapes_[i]->type == shapes::PLANE || obj->shapes_[i]->type == shapes::OCTREE)
959 RCLCPP_DEBUG(LOGGER,
"Excluding collision object '%s' from monitored octomap", obj->id_.c_str());
972 for (std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*>& shape_handle : it->second)
974 RCLCPP_DEBUG(LOGGER,
"Including collision object '%s' in monitored octomap", obj->id_.c_str());
1012 if (t.nanoseconds() == 0)
1014 RCLCPP_DEBUG(LOGGER,
"sync robot state to: %.3fs", fmod(t.seconds(), 10.));
1026 if (state_update_pending_.load())
1033 RCLCPP_WARN(LOGGER,
"Failed to fetch current robot state.");
1040 auto start =
node_->get_clock()->now();
1041 auto timeout = rclcpp::Duration::from_seconds(wait_time);
1045 timeout > rclcpp::Duration(0, 0))
1049 timeout = timeout - (
node_->get_clock()->now() - start);
1054 RCLCPP_WARN(LOGGER,
"Maybe failed to update robot state, time diff: %.3fs", (t -
last_robot_motion_time_).seconds());
1093 RCLCPP_INFO(LOGGER,
"Starting planning scene monitor");
1095 if (!scene_topic.empty())
1098 scene_topic, rclcpp::SystemDefaultsQoS(), [
this](
const moveit_msgs::msg::PlanningScene::ConstSharedPtr&
scene) {
1099 return newPlanningSceneCallback(
scene);
1109 RCLCPP_INFO(LOGGER,
"Stopping planning scene monitor");
1122 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>>>& link_shape_handle :
1125 if (
tf_buffer_->canTransform(target_frame, link_shape_handle.first->getName(), target_time,
1126 shape_transform_cache_lookup_wait_time_))
1128 Eigen::Isometry3d ttr = tf2::transformToEigen(
1129 tf_buffer_->lookupTransform(target_frame, link_shape_handle.first->getName(), target_time));
1130 for (std::size_t j = 0; j < link_shape_handle.second.size(); ++j)
1131 cache[link_shape_handle.second[j].first] =
1132 ttr * link_shape_handle.first->getCollisionOriginTransforms()[link_shape_handle.second[j].second];
1136 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t>>>&
1139 if (
tf_buffer_->canTransform(target_frame, attached_body_shape_handle.first->getAttachedLinkName(), target_time,
1140 shape_transform_cache_lookup_wait_time_))
1142 Eigen::Isometry3d transform = tf2::transformToEigen(
tf_buffer_->lookupTransform(
1143 target_frame, attached_body_shape_handle.first->getAttachedLinkName(), target_time));
1144 for (std::size_t k = 0; k < attached_body_shape_handle.second.size(); ++k)
1145 cache[attached_body_shape_handle.second[k].first] =
1147 attached_body_shape_handle.first->getShapePosesInLinkFrame()[attached_body_shape_handle.second[k].second];
1151 if (
tf_buffer_->canTransform(target_frame,
scene_->getPlanningFrame(), target_time,
1152 shape_transform_cache_lookup_wait_time_))
1154 Eigen::Isometry3d transform =
1155 tf2::transformToEigen(
tf_buffer_->lookupTransform(target_frame,
scene_->getPlanningFrame(), target_time));
1156 for (
const std::pair<
const std::string,
1157 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*>>>&
1159 for (
const std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*>& it :
1160 collision_body_shape_handle.second)
1161 cache[it.first] = transform * (*it.second);
1165 catch (tf2::TransformException& ex)
1167 rclcpp::Clock steady_clock = rclcpp::Clock();
1168 RCLCPP_ERROR_THROTTLE(LOGGER, steady_clock, 1000,
"Transform error: %s", ex.what());
1175 const std::string& planning_scene_world_topic,
1176 const bool load_octomap_monitor)
1179 RCLCPP_INFO(LOGGER,
"Starting world geometry update monitor for collision objects, attached objects, octomap "
1183 if (!collision_objects_topic.empty())
1186 collision_objects_topic, rclcpp::SystemDefaultsQoS(),
1187 [
this](
const moveit_msgs::msg::CollisionObject::ConstSharedPtr& obj) {
return collisionObjectCallback(obj); });
1188 RCLCPP_INFO(LOGGER,
"Listening to '%s'", collision_objects_topic.c_str());
1191 if (!planning_scene_world_topic.empty())
1194 planning_scene_world_topic, rclcpp::SystemDefaultsQoS(),
1195 [
this](
const moveit_msgs::msg::PlanningSceneWorld::ConstSharedPtr& world) {
1198 RCLCPP_INFO(LOGGER,
"Listening to '%s' for planning scene world geometry", planning_scene_world_topic.c_str());
1202 if (load_octomap_monitor)
1207 std::make_unique<occupancy_map_monitor::OccupancyMapMonitor>(
node_,
tf_buffer_,
scene_->getPlanningFrame());
1212 octomap_monitor_->setTransformCacheCallback([
this](
const std::string& frame,
const rclcpp::Time& stamp,
1226 RCLCPP_INFO(LOGGER,
"Stopping world geometry monitor");
1231 RCLCPP_INFO(LOGGER,
"Stopping world geometry monitor");
1239 const std::string& attached_objects_topic)
1250 [
this](
const sensor_msgs::msg::JointState::ConstSharedPtr& joint_state) {
return onStateUpdate(joint_state); });
1254 std::unique_lock<std::mutex> lock(state_update_mutex_);
1255 if (dt_state_update_.count() > 0)
1258 state_update_timer_ =
1259 pnode_->create_wall_timer(dt_state_update_, [
this]() {
return stateUpdateTimerCallback(); });
1262 if (!attached_objects_topic.empty())
1266 attached_objects_topic, rclcpp::SystemDefaultsQoS(),
1267 [
this](
const moveit_msgs::msg::AttachedCollisionObject::ConstSharedPtr& obj) {
1270 RCLCPP_INFO(LOGGER,
"Listening to '%s' for attached collision objects",
1275 RCLCPP_ERROR(LOGGER,
"Cannot monitor robot state because planning scene is not configured");
1285 if (state_update_timer_)
1286 state_update_timer_->cancel();
1287 state_update_pending_.store(
false);
1290 void PlanningSceneMonitor::onStateUpdate(
const sensor_msgs::msg::JointState::ConstSharedPtr& )
1292 state_update_pending_.store(
true);
1297 if (std::chrono::system_clock::now() - last_robot_state_update_wall_time_ >= dt_state_update_)
1301 void PlanningSceneMonitor::stateUpdateTimerCallback()
1305 if (state_update_pending_.load() &&
1306 std::chrono::system_clock::now() - last_robot_state_update_wall_time_ >= dt_state_update_)
1336 bool update =
false;
1337 if (hz > std::numeric_limits<double>::epsilon())
1339 std::unique_lock<std::mutex> lock(state_update_mutex_);
1340 dt_state_update_ = std::chrono::duration<double>(1.0 / hz);
1343 state_update_timer_ =
pnode_->create_wall_timer(dt_state_update_, [
this]() {
return stateUpdateTimerCallback(); });
1350 if (state_update_timer_)
1351 state_update_timer_->cancel();
1352 std::unique_lock<std::mutex> lock(state_update_mutex_);
1353 dt_state_update_ = std::chrono::duration<double>(0.0);
1354 if (state_update_pending_.load())
1357 RCLCPP_INFO(LOGGER,
"Updating internal planning scene state at most every %lf seconds", dt_state_update_.count());
1365 rclcpp::Time time =
node_->now();
1366 rclcpp::Clock steady_clock = rclcpp::Clock(RCL_STEADY_TIME);
1369 std::vector<std::string> missing;
1373 std::string missing_str = boost::algorithm::join(missing,
", ");
1374 RCLCPP_WARN_THROTTLE(LOGGER, steady_clock, 1000,
"The complete state of the robot is not yet known. Missing %s",
1375 missing_str.c_str());
1380 if (!skip_update_if_locked)
1384 else if (!ulock.try_lock())
1392 scene_->getCurrentStateNonConst().update();
1397 std::unique_lock<std::mutex> lock(state_update_mutex_);
1398 last_robot_state_update_wall_time_ = std::chrono::system_clock::now();
1399 state_update_pending_.store(
false);
1405 RCLCPP_ERROR_THROTTLE(LOGGER, steady_clock, 1000,
1406 "State monitor is not active. Unable to set the planning scene state");
1425 RCLCPP_DEBUG(LOGGER,
"Maximum frequency for publishing a planning scene is now %lf Hz",
1429 void PlanningSceneMonitor::getUpdatedFrameTransforms(std::vector<geometry_msgs::msg::TransformStamped>& transforms)
1431 const std::string& target =
getRobotModel()->getModelFrame();
1433 std::vector<std::string> all_frame_names;
1434 tf_buffer_->_getFrameStrings(all_frame_names);
1435 for (
const std::string& all_frame_name : all_frame_names)
1437 if (all_frame_name == target ||
getRobotModel()->hasLinkModel(all_frame_name))
1440 geometry_msgs::msg::TransformStamped
f;
1443 f =
tf_buffer_->lookupTransform(target, all_frame_name, tf2::TimePointZero);
1445 catch (tf2::TransformException& ex)
1447 RCLCPP_WARN(LOGGER,
"Unable to transform object from frame '%s' to planning frame'%s' (%s)",
1448 all_frame_name.c_str(), target.c_str(), ex.what());
1451 f.header.frame_id = all_frame_name;
1452 f.child_frame_id = target;
1453 transforms.push_back(
f);
1461 std::vector<geometry_msgs::msg::TransformStamped> transforms;
1462 getUpdatedFrameTransforms(transforms);
1465 scene_->getTransformsNonConst().setTransforms(transforms);
1489 RCLCPP_DEBUG(LOGGER,
"No additional default collision operations specified");
1492 RCLCPP_DEBUG(LOGGER,
"Reading additional default collision operations");
1536 static const std::string ROBOT_DESCRIPTION =
void setupScene(const rclcpp::Node::SharedPtr &node, const planning_scene::PlanningScenePtr &scene)
Fetch plugin name from parameter server and activate the plugin for the given scene.
std::shared_lock< std::shared_mutex > ReadLock
Represents an action that occurred on an object in the world. Several bits may be set indicating seve...
std::function< void(const ObjectConstPtr &, Action)> ObserverCallbackFn
This may be thrown during construction of objects if errors occur.
Object defining bodies that can be attached to robot links.
const std::string & getName() const
Get the name of the attached body.
const std::vector< shapes::ShapeConstPtr > & getShapes() const
Get the shapes that make up this attached body.
A link from the robot. Contains the constant transform applied to the link and its geometry.
This class maintains the representation of the environment as seen by a planning instance....
static const std::string OCTOMAP_NS
PlanningSceneMonitor Subscribes to the topic planning_scene.
void lockSceneRead()
Lock the scene for reading (multiple threads can lock for reading at the same time)
void lockSceneWrite()
Lock the scene for writing (only one thread can lock for writing and no other thread can lock for rea...
void unlockSceneRead()
Unlock the scene from reading (multiple threads can lock for reading at the same time)
void excludeAttachedBodiesFromOctree()
planning_scene::PlanningScenePtr scene_
double default_attached_padd_
default attached padding
void currentWorldObjectUpdateCallback(const collision_detection::World::ObjectConstPtr &object, collision_detection::World::Action action)
Callback for a change in the world maintained by the planning scene.
double default_robot_scale_
default robot scaling
std::unique_ptr< occupancy_map_monitor::OccupancyMapMonitor > octomap_monitor_
const moveit::core::RobotModelConstPtr & getRobotModel() const
AttachedBodyShapeHandles attached_body_shape_handles_
void attachObjectCallback(const moveit_msgs::msg::AttachedCollisionObject::ConstSharedPtr &obj)
Callback for a new attached object msg.
std::map< std::string, double > default_robot_link_padd_
default robot link padding
LinkShapeHandles link_shape_handles_
void collisionObjectCallback(const moveit_msgs::msg::CollisionObject::ConstSharedPtr &obj)
Callback for a new collision object msg.
SceneUpdateType publish_update_types_
void configureDefaultPadding()
Configure the default padding.
void publishDebugInformation(bool flag)
PlanningSceneMonitor(const PlanningSceneMonitor &)=delete
PlanningSceneMonitor cannot be copy-constructed.
rclcpp::Subscription< moveit_msgs::msg::AttachedCollisionObject >::SharedPtr attached_collision_object_subscriber_
void stopPublishingPlanningScene()
Stop publishing the maintained planning scene.
void excludeAttachedBodyFromOctree(const moveit::core::AttachedBody *attached_body)
double default_object_padd_
default object padding
void addUpdateCallback(const std::function< void(SceneUpdateType)> &fn)
Add a function to be called when an update to the scene is received.
std::shared_ptr< rclcpp::Node > pnode_
bool newPlanningSceneMessage(const moveit_msgs::msg::PlanningScene &scene)
void setPlanningScenePublishingFrequency(double hz)
Set the maximum frequency at which planning scenes are being published.
void includeWorldObjectInOctree(const collision_detection::World::ObjectConstPtr &obj)
rclcpp::Service< moveit_msgs::srv::GetPlanningScene >::SharedPtr get_scene_service_
void initialize(const planning_scene::PlanningScenePtr &scene)
Initialize the planning scene monitor.
void getMonitoredTopics(std::vector< std::string > &topics) const
Get the topic names that the monitor is listening to.
void triggerSceneUpdateEvent(SceneUpdateType update_type)
This function is called every time there is a change to the planning scene.
void newPlanningSceneWorldCallback(const moveit_msgs::msg::PlanningSceneWorld::ConstSharedPtr &world)
Callback for a new planning scene world.
planning_scene::PlanningSceneConstPtr scene_const_
rclcpp::Subscription< moveit_msgs::msg::CollisionObject >::SharedPtr collision_object_subscriber_
void includeAttachedBodyInOctree(const moveit::core::AttachedBody *attached_body)
void octomapUpdateCallback()
Callback for octomap updates.
rclcpp::Subscription< moveit_msgs::msg::PlanningScene >::SharedPtr planning_scene_subscriber_
void clearUpdateCallbacks()
Clear the functions to be called when an update to the scene is received.
void providePlanningSceneService(const std::string &service_name=DEFAULT_PLANNING_SCENE_SERVICE)
Create an optional service for getting the complete planning scene This is useful for satisfying the ...
std::shared_mutex scene_update_mutex_
if diffs are monitored, this is the pointer to the parent scene
void setStateUpdateFrequency(double hz)
Update the scene using the monitored state at a specified frequency, in Hz. This function has an effe...
double publish_planning_scene_frequency_
std::shared_ptr< tf2_ros::TransformListener > tf_listener_
void stopWorldGeometryMonitor()
Stop the world geometry monitor.
void startStateMonitor(const std::string &joint_states_topic=DEFAULT_JOINT_STATES_TOPIC, const std::string &attached_objects_topic=DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC)
Start the current state monitor.
void stopStateMonitor()
Stop the state monitor.
@ UPDATE_SCENE
The entire scene was updated.
@ UPDATE_STATE
The state in the monitored scene was updated.
@ UPDATE_GEOMETRY
The geometry of the scene was updated. This includes receiving new octomaps, collision objects,...
@ UPDATE_TRANSFORMS
The maintained set of fixed transforms in the monitored scene was updated.
std::atomic< SceneUpdateType > new_scene_update_
std::shared_ptr< rclcpp::executors::SingleThreadedExecutor > private_executor_
void includeAttachedBodiesInOctree()
bool getShapeTransformCache(const std::string &target_frame, const rclcpp::Time &target_time, occupancy_map_monitor::ShapeTransformCache &cache) const
void startSceneMonitor(const std::string &scene_topic=DEFAULT_PLANNING_SCENE_TOPIC)
Start the scene monitor (ROS topic-based)
void startPublishingPlanningScene(SceneUpdateType event, const std::string &planning_scene_topic=MONITORED_PLANNING_SCENE_TOPIC)
Start publishing the maintained planning scene. The first message set out is a complete planning scen...
std::string robot_description_
bool waitForCurrentRobotState(const rclcpp::Time &t, double wait_time=1.)
Wait for robot state to become more recent than time t.
std::recursive_mutex shape_handles_lock_
std::map< std::string, double > default_robot_link_scale_
default robot link scale
rclcpp::Time last_robot_motion_time_
Last time the state was updated.
void updateSceneWithCurrentState(bool skip_update_if_locked=false)
Update the scene using the monitored state. This function is automatically called when an update to t...
std::thread private_executor_thread_
void excludeWorldObjectsFromOctree()
double default_robot_padd_
default robot padding
std::string monitor_name_
The name of this scene monitor.
bool updatesScene(const planning_scene::PlanningSceneConstPtr &scene) const
Return true if the scene scene can be updated directly or indirectly by this monitor....
CurrentStateMonitorPtr current_state_monitor_
std::recursive_mutex update_lock_
lock access to update_callbacks_
void includeWorldObjectsInOctree()
CollisionBodyShapeHandles collision_body_shape_handles_
void stopSceneMonitor()
Stop the scene monitor.
void includeRobotLinksInOctree()
rclcpp::Time last_update_time_
mutex for stored scene
void excludeRobotLinksFromOctree()
bool requestPlanningSceneState(const std::string &service_name=DEFAULT_PLANNING_SCENE_SERVICE)
Request a full planning scene state using a service call Be careful not to use this in conjunction wi...
void monitorDiffs(bool flag)
By default, the maintained planning scene does not reason about diffs. When the flag passed in is tru...
void currentStateAttachedBodyUpdateCallback(moveit::core::AttachedBody *attached_body, bool just_attached)
Callback for a change for an attached object of the current state of the planning scene.
std::unique_ptr< std::thread > publish_planning_scene_
std::shared_ptr< rclcpp::Node > node_
Last time the robot has moved.
void configureCollisionMatrix(const planning_scene::PlanningScenePtr &scene)
Configure the collision matrix for a particular scene.
void startWorldGeometryMonitor(const std::string &collision_objects_topic=DEFAULT_COLLISION_OBJECT_TOPIC, const std::string &planning_scene_world_topic=DEFAULT_PLANNING_SCENE_WORLD_TOPIC, const bool load_octomap_monitor=true)
Start the OccupancyMapMonitor and listening for:
rclcpp::Publisher< moveit_msgs::msg::PlanningScene >::SharedPtr planning_scene_publisher_
void excludeWorldObjectFromOctree(const collision_detection::World::ObjectConstPtr &obj)
std::vector< std::function< void(SceneUpdateType)> > update_callbacks_
void updateFrameTransforms()
Update the transforms for the frames that are not part of the kinematic model using tf....
planning_scene::PlanningScenePtr parent_scene_
std::condition_variable_any new_scene_update_condition_
std::shared_ptr< tf2_ros::Buffer > tf_buffer_
void unlockSceneWrite()
Lock the scene from writing (only one thread can lock for writing and no other thread can lock for re...
rclcpp::Subscription< moveit_msgs::msg::PlanningSceneWorld >::SharedPtr planning_scene_world_subscriber_
rclcpp::Parameter declare_parameter(const rclcpp::Node::SharedPtr &node, const std::string ¶meter_name)
bool isEmpty(const moveit_msgs::msg::PlanningScene &msg)
Check if a message includes any information about a planning scene, or whether it is empty.
std::function< void(AttachedBody *body, bool attached)> AttachedBodyCallback
std::map< ShapeHandle, Eigen::Isometry3d, std::less< ShapeHandle >, Eigen::aligned_allocator< std::pair< const ShapeHandle, Eigen::Isometry3d > > > ShapeTransformCache
This namespace includes the central class for representing planning contexts.
const rclcpp::Logger LOGGER