moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
planning_scene_monitor.hpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Ioan Sucan */
36
37#pragma once
38
39#include <rclcpp/rclcpp.hpp>
40#include <tf2_ros/buffer.h>
41#include <tf2_ros/transform_listener.h>
48#include <moveit_msgs/srv/get_planning_scene.hpp>
49#include <memory>
50#include <thread>
51#include <shared_mutex>
52#include <mutex>
53#include <thread>
54
55#include <moveit_planning_scene_monitor_export.h>
56
58{
59MOVEIT_CLASS_FORWARD(PlanningSceneMonitor); // Defines PlanningSceneMonitorPtr, ConstPtr, WeakPtr... etc
60
64class MOVEIT_PLANNING_SCENE_MONITOR_EXPORT PlanningSceneMonitor
65{
66public:
71
76
78 {
80 UPDATE_NONE = 0,
81
83 UPDATE_STATE = 1,
84
86 UPDATE_TRANSFORMS = 2,
87
90 UPDATE_GEOMETRY = 4,
91
93 UPDATE_SCENE = 8 + UPDATE_STATE + UPDATE_TRANSFORMS + UPDATE_GEOMETRY
94 };
95
97 static const std::string DEFAULT_JOINT_STATES_TOPIC; // "/joint_states"
98
100 static const std::string DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC; // "/attached_collision_object"
101
103 static const std::string DEFAULT_COLLISION_OBJECT_TOPIC; // "/collision_object"
104
107 static const std::string DEFAULT_PLANNING_SCENE_WORLD_TOPIC; // "/planning_scene_world"
108
110 static const std::string DEFAULT_PLANNING_SCENE_TOPIC; // "/planning_scene"
111
113 static const std::string DEFAULT_PLANNING_SCENE_SERVICE; // "/get_planning_scene"
114
117 static const std::string MONITORED_PLANNING_SCENE_TOPIC; // "monitored_planning_scene"
118
123 PlanningSceneMonitor(const rclcpp::Node::SharedPtr& node, const std::string& robot_description,
124 const std::string& name = "");
125
130 PlanningSceneMonitor(const rclcpp::Node::SharedPtr& node, const robot_model_loader::RobotModelLoaderPtr& rml,
131 const std::string& name = "");
132
138 PlanningSceneMonitor(const rclcpp::Node::SharedPtr& node, const planning_scene::PlanningScenePtr& scene,
139 const std::string& robot_description, const std::string& name = "");
140
146 PlanningSceneMonitor(const rclcpp::Node::SharedPtr& node, const planning_scene::PlanningScenePtr& scene,
147 const robot_model_loader::RobotModelLoaderPtr& rml, const std::string& name = "");
148
150
152 const std::string& getName() const
153 {
154 return monitor_name_;
155 }
156
158 const robot_model_loader::RobotModelLoaderPtr& getRobotModelLoader() const
159 {
160 return rm_loader_;
161 }
162
163 const moveit::core::RobotModelConstPtr& getRobotModel() const
164 {
165 return robot_model_;
166 }
167
182 const planning_scene::PlanningScenePtr& getPlanningScene()
183 {
184 return scene_;
185 }
186
190 const planning_scene::PlanningSceneConstPtr& getPlanningScene() const
191 {
192 return scene_const_;
193 }
194
196 planning_scene::PlanningScenePtr
197 copyPlanningScene(const moveit_msgs::msg::PlanningScene& diff = moveit_msgs::msg::PlanningScene());
198
203 bool updatesScene(const planning_scene::PlanningSceneConstPtr& scene) const;
204
209 bool updatesScene(const planning_scene::PlanningScenePtr& scene) const;
210
213 const std::string& getRobotDescription() const
214 {
215 return robot_description_;
216 }
217
220 {
221 return default_robot_padd_;
222 }
223
225 double getDefaultRobotScale() const
226 {
227 return default_robot_scale_;
228 }
229
232 {
233 return default_object_padd_;
234 }
235
238 {
239 return default_attached_padd_;
240 }
241
243 const std::shared_ptr<tf2_ros::Buffer>& getTFClient() const
244 {
245 return tf_buffer_;
246 }
247
253 void monitorDiffs(bool flag);
254
258 void startPublishingPlanningScene(SceneUpdateType event,
259 const std::string& planning_scene_topic = MONITORED_PLANNING_SCENE_TOPIC);
260
262 void stopPublishingPlanningScene();
263
265 void setPlanningScenePublishingFrequency(double hz);
266
269 {
270 return publish_planning_scene_frequency_;
271 }
272
275 const CurrentStateMonitorPtr& getStateMonitor() const
276 {
277 return current_state_monitor_;
278 }
279
280 CurrentStateMonitorPtr& getStateMonitorNonConst()
281 {
282 return current_state_monitor_;
283 }
284
290 void updateFrameTransforms();
291
295 void startStateMonitor(const std::string& joint_states_topic = DEFAULT_JOINT_STATES_TOPIC,
296 const std::string& attached_objects_topic = DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC);
297
299 void stopStateMonitor();
300
305 void updateSceneWithCurrentState(bool skip_update_if_locked = false);
306
312 void setStateUpdateFrequency(double hz);
313
316 {
317 if (dt_state_update_.count() > 0.0)
318 {
319 return 1.0 / dt_state_update_.count();
320 }
321 else
322 {
323 return 0.0;
324 }
325 }
326
330 void startSceneMonitor(const std::string& scene_topic = DEFAULT_PLANNING_SCENE_TOPIC);
331
339 bool requestPlanningSceneState(const std::string& service_name = DEFAULT_PLANNING_SCENE_SERVICE);
340
348 void providePlanningSceneService(const std::string& service_name = DEFAULT_PLANNING_SCENE_SERVICE);
349
351 void stopSceneMonitor();
352
361 void startWorldGeometryMonitor(const std::string& collision_objects_topic = DEFAULT_COLLISION_OBJECT_TOPIC,
362 const std::string& planning_scene_world_topic = DEFAULT_PLANNING_SCENE_WORLD_TOPIC,
363 const bool load_octomap_monitor = true);
364
366 void stopWorldGeometryMonitor();
367
369 void addUpdateCallback(const std::function<void(SceneUpdateType)>& fn);
370
372 void clearUpdateCallbacks();
373
375 void getMonitoredTopics(std::vector<std::string>& topics) const;
376
378 const rclcpp::Time& getLastUpdateTime() const
379 {
380 return last_update_time_;
381 }
382
383 void publishDebugInformation(bool flag);
384
386 void triggerSceneUpdateEvent(SceneUpdateType update_type);
387
393 bool waitForCurrentRobotState(const rclcpp::Time& t, double wait_time = 1.);
394
395 void clearOctomap();
396
397 // Called to update the planning scene with a new message.
398 bool newPlanningSceneMessage(const moveit_msgs::msg::PlanningScene& scene);
399
400 // Called to update a collision object in the planning scene.
401 bool processCollisionObjectMsg(const moveit_msgs::msg::CollisionObject::ConstSharedPtr& collision_object_msg,
402 const std::optional<moveit_msgs::msg::ObjectColor>& color_msg = std::nullopt);
403
404 // Called to update an attached collision object in the planning scene.
405 bool processAttachedCollisionObjectMsg(
406 const moveit_msgs::msg::AttachedCollisionObject::ConstSharedPtr& attached_collision_object_msg);
407
408protected:
412 void initialize(const planning_scene::PlanningScenePtr& scene);
413
415 void lockSceneRead();
416
418 void unlockSceneRead();
419
422 void lockSceneWrite();
423
426 void unlockSceneWrite();
427
429 void configureCollisionMatrix(const planning_scene::PlanningScenePtr& scene);
430
432 void configureDefaultPadding();
433
435 void newPlanningSceneWorldCallback(const moveit_msgs::msg::PlanningSceneWorld::ConstSharedPtr& world);
436
438 void octomapUpdateCallback();
439
441 void currentStateAttachedBodyUpdateCallback(moveit::core::AttachedBody* attached_body, bool just_attached);
442
444 void currentWorldObjectUpdateCallback(const collision_detection::World::ObjectConstPtr& object,
446
447 void includeRobotLinksInOctree();
448 void excludeRobotLinksFromOctree();
449
450 void excludeWorldObjectsFromOctree();
451 void includeWorldObjectsInOctree();
452 void excludeWorldObjectFromOctree(const collision_detection::World::ObjectConstPtr& obj);
453 void includeWorldObjectInOctree(const collision_detection::World::ObjectConstPtr& obj);
454
455 void excludeAttachedBodiesFromOctree();
456 void includeAttachedBodiesInOctree();
457 void excludeAttachedBodyFromOctree(const moveit::core::AttachedBody* attached_body);
458 void includeAttachedBodyInOctree(const moveit::core::AttachedBody* attached_body);
459
460 bool getShapeTransformCache(const std::string& target_frame, const rclcpp::Time& target_time,
462
464 std::string monitor_name_;
465
466 planning_scene::PlanningScenePtr scene_;
467 planning_scene::PlanningSceneConstPtr scene_const_;
468 planning_scene::PlanningScenePtr parent_scene_;
469 std::shared_mutex scene_update_mutex_;
470 rclcpp::Time last_update_time_;
472
473 std::shared_ptr<rclcpp::Node> node_;
474
475 // TODO: (anasarrak) callbacks on ROS2?
476 // https://answers.ros.org/question/300874/how-do-you-use-callbackgroups-as-a-replacement-for-callbackqueues-in-ros2/
477 // ros::CallbackQueue queue_;
478 std::shared_ptr<rclcpp::Node> pnode_;
479 std::shared_ptr<rclcpp::executors::SingleThreadedExecutor> private_executor_;
481
482 std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
483 std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
484
486
496 std::map<std::string, double> default_robot_link_padd_;
498 std::map<std::string, double> default_robot_link_scale_;
499
500 // variables for planning scene publishing
501 rclcpp::Publisher<moveit_msgs::msg::PlanningScene>::SharedPtr planning_scene_publisher_;
502 std::unique_ptr<std::thread> publish_planning_scene_;
505 std::atomic<SceneUpdateType> new_scene_update_;
506 std::condition_variable_any new_scene_update_condition_;
507
508 // subscribe to various sources of data
509 rclcpp::Subscription<moveit_msgs::msg::PlanningScene>::SharedPtr planning_scene_subscriber_;
510 rclcpp::Subscription<moveit_msgs::msg::PlanningSceneWorld>::SharedPtr planning_scene_world_subscriber_;
511
512 rclcpp::Subscription<moveit_msgs::msg::AttachedCollisionObject>::SharedPtr attached_collision_object_subscriber_;
513 rclcpp::Subscription<moveit_msgs::msg::CollisionObject>::SharedPtr collision_object_subscriber_;
514
515 // provide an optional service to get the full planning scene state
516 // this is used by MoveGroup and related application nodes
517 rclcpp::Service<moveit_msgs::srv::GetPlanningScene>::SharedPtr get_scene_service_;
518
519 // include a octomap monitor
520 std::unique_ptr<occupancy_map_monitor::OccupancyMapMonitor> octomap_monitor_;
521
522 // include a current state monitor
523 CurrentStateMonitorPtr current_state_monitor_;
524
525 typedef std::map<const moveit::core::LinkModel*,
526 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t> > >
529 std::vector<std::pair<occupancy_map_monitor::ShapeHandle, std::size_t> > >;
531 std::map<std::string, std::vector<std::pair<occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d*> > >;
532
536 mutable std::recursive_mutex shape_handles_lock_;
537
539 std::recursive_mutex update_lock_;
540 std::vector<std::function<void(SceneUpdateType)> > update_callbacks_;
542
543private:
544 void getUpdatedFrameTransforms(std::vector<geometry_msgs::msg::TransformStamped>& transforms);
545
546 // publish planning scene update diffs (runs in its own thread)
547 void scenePublishingThread();
548
549 // called by current_state_monitor_ when robot state (as monitored on joint state topic) changes
550 void onStateUpdate(const sensor_msgs::msg::JointState::ConstSharedPtr& joint_state);
551
552 // called by state_update_timer_ when a state update it pending
553 void stateUpdateTimerCallback();
554
555 // Callback for a new planning scene msg
556 void newPlanningSceneCallback(const moveit_msgs::msg::PlanningScene::ConstSharedPtr& scene);
557
558 // Callback for requesting the full planning scene via service
559 void getPlanningSceneServiceCallback(const moveit_msgs::srv::GetPlanningScene::Request::SharedPtr& req,
560 const moveit_msgs::srv::GetPlanningScene::Response::SharedPtr& res);
561
562 void updatePublishSettings(bool publish_geom_updates, bool publish_state_updates, bool publish_transform_updates,
563 bool publish_planning_scene, double publish_planning_scene_hz);
564
566 std::atomic<bool> state_update_pending_;
567
568 // Lock for writing last_robot_state_update_wall_time_ and dt_state_update_
569 std::mutex state_update_mutex_;
570
572 // Only access this from callback functions (and constructor)
573 // This field is protected by state_update_mutex_
574 std::chrono::system_clock::time_point last_robot_state_update_wall_time_;
575
577 // This field is protected by state_update_mutex_
578 std::chrono::duration<double> dt_state_update_; // 1hz
579
581 // Setting this to a non-zero value resolves issues when the sensor data is
582 // arriving so fast that it is preceding the transform state.
583 rclcpp::Duration shape_transform_cache_lookup_wait_time_;
584
586 // If state_update_pending_ is true, call updateSceneWithCurrentState()
587 // Not safe to access from callback functions.
588 rclcpp::TimerBase::SharedPtr state_update_timer_;
589
590 robot_model_loader::RobotModelLoaderPtr rm_loader_;
591 moveit::core::RobotModelConstPtr robot_model_;
592
594
595 rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr callback_handler_;
596
597 bool use_sim_time_;
598
601
602 rclcpp::Logger logger_;
603};
604
627{
628public:
629 LockedPlanningSceneRO(const PlanningSceneMonitorPtr& planning_scene_monitor)
631 {
632 initialize(true);
633 }
634
635 const PlanningSceneMonitorPtr& getPlanningSceneMonitor()
636 {
638 }
639
640 operator bool() const
641 {
642 return planning_scene_monitor_ && planning_scene_monitor_->getPlanningScene();
643 }
644
645 operator const planning_scene::PlanningSceneConstPtr&() const
646 {
647 return static_cast<const PlanningSceneMonitor*>(planning_scene_monitor_.get())->getPlanningScene();
648 }
649
650 const planning_scene::PlanningSceneConstPtr& operator->() const
651 {
652 return static_cast<const PlanningSceneMonitor*>(planning_scene_monitor_.get())->getPlanningScene();
653 }
654
655protected:
656 LockedPlanningSceneRO(const PlanningSceneMonitorPtr& planning_scene_monitor, bool read_only)
658 {
659 initialize(read_only);
660 }
661
662 void initialize(bool read_only)
663 {
665 lock_ = std::make_shared<SingleUnlock>(planning_scene_monitor_.get(), read_only);
666 }
667
669
670 // we use this struct so that lock/unlock are called only once
671 // even if the LockedPlanningScene instance is copied around
700
701 PlanningSceneMonitorPtr planning_scene_monitor_;
702 SingleUnlockPtr lock_;
703};
704
727{
728public:
729 LockedPlanningSceneRW(const PlanningSceneMonitorPtr& planning_scene_monitor)
731 {
732 }
733
734 operator const planning_scene::PlanningScenePtr&()
735 {
736 return planning_scene_monitor_->getPlanningScene();
737 }
738
739 const planning_scene::PlanningScenePtr& operator->()
740 {
741 return planning_scene_monitor_->getPlanningScene();
742 }
743};
744} // namespace planning_scene_monitor
#define MOVEIT_CLASS_FORWARD(C)
Represents an action that occurred on an object in the world. Several bits may be set indicating seve...
Definition world.hpp:268
Object defining bodies that can be attached to robot links.
A link from the robot. Contains the constant transform applied to the link and its geometry.
This is a convenience class for obtaining access to an instance of a locked PlanningScene.
LockedPlanningSceneRO(const PlanningSceneMonitorPtr &planning_scene_monitor, bool read_only)
LockedPlanningSceneRO(const PlanningSceneMonitorPtr &planning_scene_monitor)
const planning_scene::PlanningSceneConstPtr & operator->() const
const PlanningSceneMonitorPtr & getPlanningSceneMonitor()
This is a convenience class for obtaining access to an instance of a locked PlanningScene.
const planning_scene::PlanningScenePtr & operator->()
LockedPlanningSceneRW(const PlanningSceneMonitorPtr &planning_scene_monitor)
PlanningSceneMonitor Subscribes to the topic planning_scene.
static const std::string DEFAULT_PLANNING_SCENE_TOPIC
The name of the topic used by default for receiving full planning scenes or planning scene diffs.
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)
static const std::string DEFAULT_PLANNING_SCENE_SERVICE
The name of the service used by default for requesting full planning scene state.
std::unique_ptr< occupancy_map_monitor::OccupancyMapMonitor > octomap_monitor_
std::map< std::string, double > default_robot_link_padd_
default robot link padding
static const std::string DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC
The name of the topic used by default for attached collision objects.
const planning_scene::PlanningSceneConstPtr & getPlanningScene() const
Avoid this function! Returns an unsafe pointer to the current planning scene.
static const std::string DEFAULT_COLLISION_OBJECT_TOPIC
The name of the topic used by default for receiving collision objects in the world.
PlanningSceneMonitor(const PlanningSceneMonitor &)=delete
PlanningSceneMonitor cannot be copy-constructed.
rclcpp::Subscription< moveit_msgs::msg::AttachedCollisionObject >::SharedPtr attached_collision_object_subscriber_
std::map< std::string, std::vector< std::pair< occupancy_map_monitor::ShapeHandle, const Eigen::Isometry3d * > > > CollisionBodyShapeHandles
rclcpp::Service< moveit_msgs::srv::GetPlanningScene >::SharedPtr get_scene_service_
std::map< const moveit::core::LinkModel *, std::vector< std::pair< occupancy_map_monitor::ShapeHandle, std::size_t > > > LinkShapeHandles
double getDefaultAttachedObjectPadding() const
Get the default attached padding.
planning_scene::PlanningSceneConstPtr scene_const_
PlanningSceneMonitor & operator=(const PlanningSceneMonitor &)=delete
PlanningSceneMonitor cannot be copy-assigned.
rclcpp::Subscription< moveit_msgs::msg::CollisionObject >::SharedPtr collision_object_subscriber_
rclcpp::Subscription< moveit_msgs::msg::PlanningScene >::SharedPtr planning_scene_subscriber_
double getDefaultRobotPadding() const
Get the default robot padding.
std::shared_mutex scene_update_mutex_
if diffs are monitored, this is the pointer to the parent scene
const moveit::core::RobotModelConstPtr & getRobotModel() const
std::shared_ptr< tf2_ros::TransformListener > tf_listener_
double getStateUpdateFrequency() const
Get the maximum frequency (Hz) at which the current state of the planning scene is updated.
std::shared_ptr< rclcpp::executors::SingleThreadedExecutor > private_executor_
const rclcpp::Time & getLastUpdateTime() const
Return the time when the last update was made to the planning scene (by any monitor)
const CurrentStateMonitorPtr & getStateMonitor() const
Get the stored instance of the stored current state monitor.
std::map< const moveit::core::AttachedBody *, std::vector< std::pair< occupancy_map_monitor::ShapeHandle, std::size_t > > > AttachedBodyShapeHandles
double getDefaultObjectPadding() const
Get the default object padding.
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.
double getDefaultRobotScale() const
Get the default robot scaling.
std::string monitor_name_
The name of this scene monitor.
std::recursive_mutex update_lock_
lock access to update_callbacks_
rclcpp::Time last_update_time_
mutex for stored scene
const std::string & getRobotDescription() const
Get the stored robot description.
const std::string & getName() const
Get the name of this monitor.
const robot_model_loader::RobotModelLoaderPtr & getRobotModelLoader() const
Get the user kinematic model loader.
std::shared_ptr< rclcpp::Node > node_
Last time the robot has moved.
rclcpp::Publisher< moveit_msgs::msg::PlanningScene >::SharedPtr planning_scene_publisher_
static const std::string DEFAULT_JOINT_STATES_TOPIC
The name of the topic used by default for receiving joint states.
const planning_scene::PlanningScenePtr & getPlanningScene()
Avoid this function! Returns an unsafe pointer to the current planning scene.
const std::shared_ptr< tf2_ros::Buffer > & getTFClient() const
Get the instance of the TF client that was passed to the constructor of this class.
std::vector< std::function< void(SceneUpdateType)> > update_callbacks_
double getPlanningScenePublishingFrequency() const
Get the maximum frequency at which planning scenes are published (Hz)
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_
std::map< ShapeHandle, Eigen::Isometry3d, std::less< ShapeHandle >, Eigen::aligned_allocator< std::pair< const ShapeHandle, Eigen::Isometry3d > > > ShapeTransformCache
SingleUnlock(PlanningSceneMonitor *planning_scene_monitor, bool read_only)