moveit2
The MoveIt Motion Planning Framework for ROS 2.
collision_monitor.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2019, Los Alamos National Security, LLC
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 are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *******************************************************************************/
33 /*
34  * Title : collision_monitor.cpp
35  * Project : moveit_servo
36  * Created : 06/08/2023
37  * Author : Brian O'Neil, Andy Zelenak, Blake Anderson, V Mohammed Ibrahim
38  */
39 
41 #include <rclcpp/rclcpp.hpp>
42 #include <moveit/utils/logger.hpp>
43 
44 namespace moveit_servo
45 {
46 namespace
47 {
48 rclcpp::Logger getLogger()
49 {
50  return moveit::getLogger("moveit.ros.move_group.collision_monitor");
51 }
52 } // namespace
53 
54 CollisionMonitor::CollisionMonitor(const planning_scene_monitor::PlanningSceneMonitorPtr& planning_scene_monitor,
55  const servo::Params& servo_params, std::atomic<double>& collision_velocity_scale)
56  : servo_params_(servo_params)
57  , planning_scene_monitor_(planning_scene_monitor)
58  , robot_state_(planning_scene_monitor->getPlanningScene()->getCurrentState())
59  , collision_velocity_scale_(collision_velocity_scale)
60 {
61  scene_collision_request_.distance = true;
62  scene_collision_request_.group_name = servo_params.move_group_name;
63 
64  self_collision_request_.distance = true;
65  self_collision_request_.group_name = servo_params.move_group_name;
66 }
67 
69 {
70  stop_requested_ = false;
71  if (!monitor_thread_.joinable())
72  {
73  monitor_thread_ = std::thread(&CollisionMonitor::checkCollisions, this);
74  RCLCPP_INFO_STREAM(getLogger(), "Collision monitor started");
75  }
76  else
77  {
78  RCLCPP_ERROR_STREAM(getLogger(), "Collision monitor could not be started");
79  }
80 }
81 
83 {
84  stop_requested_ = true;
85  if (monitor_thread_.joinable())
86  {
87  monitor_thread_.join();
88  }
89  RCLCPP_INFO_STREAM(getLogger(), "Collision monitor stopped");
90 }
91 
92 void CollisionMonitor::checkCollisions()
93 {
94  rclcpp::WallRate rate(servo_params_.collision_check_rate);
95 
96  bool approaching_self_collision, approaching_scene_collision;
97  double self_collision_threshold_delta, scene_collision_threshold_delta;
98  double self_collision_scale, scene_collision_scale;
99  const double log_val = -log(0.001);
100 
101  while (rclcpp::ok() && !stop_requested_)
102  {
103  const double self_velocity_scale_coefficient{ log_val / servo_params_.self_collision_proximity_threshold };
104  const double scene_velocity_scale_coefficient{ log_val / servo_params_.scene_collision_proximity_threshold };
105 
106  if (servo_params_.check_collisions)
107  {
108  // Get a read-only copy of the planning scene.
109  planning_scene_monitor::LockedPlanningSceneRO locked_scene(planning_scene_monitor_);
110 
111  // Fetch latest robot state using planning scene instead of state monitor due to
112  // https://github.com/moveit/moveit2/issues/2748
113  robot_state_ = locked_scene->getCurrentState();
114  // This must be called before doing collision checking.
115  robot_state_.updateCollisionBodyTransforms();
116 
117  // Check collision with environment.
118  scene_collision_result_.clear();
119  locked_scene->getCollisionEnv()->checkRobotCollision(scene_collision_request_, scene_collision_result_,
120  robot_state_, locked_scene->getAllowedCollisionMatrix());
121 
122  // Check robot self collision.
123  self_collision_result_.clear();
124  locked_scene->getCollisionEnvUnpadded()->checkSelfCollision(
125  self_collision_request_, self_collision_result_, robot_state_, locked_scene->getAllowedCollisionMatrix());
126 
127  // If collision detected scale velocity to 0, else start decelerating exponentially.
128  // velocity_scale = e ^ k * (collision_distance - threshold)
129  // k = - ln(0.001) / collision_proximity_threshold
130  // velocity_scale should equal one when collision_distance is at collision_proximity_threshold.
131  // velocity_scale should equal 0.001 when collision_distance is at zero.
132  //
133  // NOTE:
134  // collision_velocity_scale_ is shared by the primary servo thread. Be sure to not set any
135  // intermediate values in this loop or they can be picked up and throw off scaling while processing
136  // joint updates.
137 
138  if (self_collision_result_.collision || scene_collision_result_.collision)
139  {
140  collision_velocity_scale_ = 0.0;
141  }
142  else
143  {
144  self_collision_scale = scene_collision_scale = 1.0;
145 
146  approaching_scene_collision =
147  scene_collision_result_.distance < servo_params_.scene_collision_proximity_threshold;
148  approaching_self_collision = self_collision_result_.distance < servo_params_.self_collision_proximity_threshold;
149 
150  if (approaching_scene_collision)
151  {
152  scene_collision_threshold_delta =
153  scene_collision_result_.distance - servo_params_.scene_collision_proximity_threshold;
154  scene_collision_scale = std::exp(scene_velocity_scale_coefficient * scene_collision_threshold_delta);
155  }
156 
157  if (approaching_self_collision)
158  {
159  self_collision_threshold_delta =
160  self_collision_result_.distance - servo_params_.self_collision_proximity_threshold;
161  self_collision_scale = std::exp(self_velocity_scale_coefficient * self_collision_threshold_delta);
162  }
163 
164  // Use the scaling factor with lower value, i.e maximum scale down.
165  collision_velocity_scale_ = std::min(scene_collision_scale, self_collision_scale);
166  }
167  }
168  else
169  {
170  // If collision checking is disabled we do not scale
171  collision_velocity_scale_ = 1.0;
172  }
173 
174  rate.sleep();
175  }
176 }
177 } // namespace moveit_servo
void updateCollisionBodyTransforms()
Update the transforms for the collision bodies. This call is needed before calling collision checking...
CollisionMonitor(const planning_scene_monitor::PlanningSceneMonitorPtr &planning_scene_monitor, const servo::Params &servo_params, std::atomic< double > &collision_velocity_scale)
This is a convenience class for obtaining access to an instance of a locked PlanningScene.
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition: logger.cpp:79
std::string group_name
The group name to check collisions for (optional; if empty, assume the complete robot)....
bool distance
If true, compute proximity distance.
double distance
Closest distance between two bodies.
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void clear()
Clear a previously stored result.
bool collision
True if collision was found, false otherwise.