moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
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>
43
44namespace moveit_servo
45{
46namespace
47{
48rclcpp::Logger getLogger()
49{
50 return moveit::getLogger("moveit.ros.move_group.collision_monitor");
51}
52} // namespace
53
54CollisionMonitor::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
92void 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.