moveit2
The MoveIt Motion Planning Framework for ROS 2.
planning_scene_storage.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, 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 
38 #include <utility>
39 #include <rclcpp/serialization.hpp>
40 #include <regex>
41 #include <moveit/utils/logger.hpp>
42 
43 const std::string moveit_warehouse::PlanningSceneStorage::DATABASE_NAME = "moveit_planning_scenes";
44 
45 const std::string moveit_warehouse::PlanningSceneStorage::PLANNING_SCENE_ID_NAME = "planning_scene_id";
46 const std::string moveit_warehouse::PlanningSceneStorage::MOTION_PLAN_REQUEST_ID_NAME = "motion_request_id";
47 
48 using warehouse_ros::Metadata;
49 using warehouse_ros::Query;
50 
51 moveit_warehouse::PlanningSceneStorage::PlanningSceneStorage(warehouse_ros::DatabaseConnection::Ptr conn)
52  : MoveItMessageStorage(std::move(conn)), logger_(moveit::getLogger("moveit_warehouse_planning_scene_storage"))
53 {
54  createCollections();
55 }
56 
57 void moveit_warehouse::PlanningSceneStorage::createCollections()
58 {
59  planning_scene_collection_ =
60  conn_->openCollectionPtr<moveit_msgs::msg::PlanningScene>(DATABASE_NAME, "planning_scene");
61  motion_plan_request_collection_ =
62  conn_->openCollectionPtr<moveit_msgs::msg::MotionPlanRequest>(DATABASE_NAME, "motion_plan_request");
63  robot_trajectory_collection_ =
64  conn_->openCollectionPtr<moveit_msgs::msg::RobotTrajectory>(DATABASE_NAME, "robot_trajectory");
65 }
66 
68 {
69  planning_scene_collection_.reset();
70  motion_plan_request_collection_.reset();
71  robot_trajectory_collection_.reset();
72  conn_->dropDatabase(DATABASE_NAME);
73  createCollections();
74 }
75 
76 void moveit_warehouse::PlanningSceneStorage::addPlanningScene(const moveit_msgs::msg::PlanningScene& scene)
77 {
78  bool replace = false;
79  if (hasPlanningScene(scene.name))
80  {
81  removePlanningScene(scene.name);
82  replace = true;
83  }
84  Metadata::Ptr metadata = planning_scene_collection_->createMetadata();
85  metadata->append(PLANNING_SCENE_ID_NAME, scene.name);
86  planning_scene_collection_->insert(scene, metadata);
87  RCLCPP_DEBUG(logger_, "%s scene '%s'", replace ? "Replaced" : "Added", scene.name.c_str());
88 }
89 
91 {
92  Query::Ptr q = planning_scene_collection_->createQuery();
93  q->append(PLANNING_SCENE_ID_NAME, name);
94  std::vector<PlanningSceneWithMetadata> planning_scenes = planning_scene_collection_->queryList(q, true);
95  return !planning_scenes.empty();
96 }
97 
98 std::string moveit_warehouse::PlanningSceneStorage::getMotionPlanRequestName(
99  const moveit_msgs::msg::MotionPlanRequest& planning_query, const std::string& scene_name) const
100 {
101  // get all existing motion planning requests for this planning scene
102  Query::Ptr q = motion_plan_request_collection_->createQuery();
103  q->append(PLANNING_SCENE_ID_NAME, scene_name);
104  std::vector<MotionPlanRequestWithMetadata> existing_requests = motion_plan_request_collection_->queryList(q, false);
105 
106  // if there are no requests stored, we are done
107  if (existing_requests.empty())
108  return "";
109 
110  // compute the serialization of the message passed as argument
111  rclcpp::Serialization<moveit_msgs::msg::MotionPlanRequest> serializer;
112  rclcpp::SerializedMessage serialized_msg_arg;
113  serializer.serialize_message(&planning_query, &serialized_msg_arg);
114  const size_t serial_size_arg = serialized_msg_arg.size();
115  const void* data_arg = serialized_msg_arg.get_rcl_serialized_message().buffer;
116 
117  for (MotionPlanRequestWithMetadata& existing_request : existing_requests)
118  {
119  auto msg = static_cast<const moveit_msgs::msg::MotionPlanRequest&>(*existing_request);
120  rclcpp::SerializedMessage serialized_msg;
121  serializer.serialize_message(&msg, &serialized_msg);
122  const size_t serial_size = serialized_msg.size();
123  const void* data = serialized_msg.get_rcl_serialized_message().buffer;
124 
125  if (serial_size != serial_size_arg)
126  continue;
127  if (memcmp(data_arg, data, serial_size) == 0)
128  {
129  // we found the same message twice
130  return existing_request->lookupString(MOTION_PLAN_REQUEST_ID_NAME);
131  }
132  }
133  return "";
134 }
135 
137  const std::string& scene_name,
138  const std::string& query_name)
139 {
140  std::string id = getMotionPlanRequestName(planning_query, scene_name);
141 
142  // if we are trying to overwrite, we remove the old query first (if it exists).
143  if (!query_name.empty() && id.empty())
144  removePlanningQuery(scene_name, query_name);
145 
146  if (id != query_name || id.empty())
147  addNewPlanningRequest(planning_query, scene_name, query_name);
148 }
149 
150 std::string
151 moveit_warehouse::PlanningSceneStorage::addNewPlanningRequest(const moveit_msgs::msg::MotionPlanRequest& planning_query,
152  const std::string& scene_name,
153  const std::string& query_name)
154 {
155  std::string id = query_name;
156  if (id.empty())
157  {
158  std::set<std::string> used;
159  Query::Ptr q = motion_plan_request_collection_->createQuery();
160  q->append(PLANNING_SCENE_ID_NAME, scene_name);
161  std::vector<MotionPlanRequestWithMetadata> existing_requests = motion_plan_request_collection_->queryList(q, true);
162  for (MotionPlanRequestWithMetadata& existing_request : existing_requests)
163  used.insert(existing_request->lookupString(MOTION_PLAN_REQUEST_ID_NAME));
164  std::size_t index = existing_requests.size();
165  do
166  {
167  id = "Motion Plan Request " + std::to_string(index);
168  index++;
169  } while (used.find(id) != used.end());
170  }
171  Metadata::Ptr metadata = motion_plan_request_collection_->createMetadata();
172  metadata->append(PLANNING_SCENE_ID_NAME, scene_name);
173  metadata->append(MOTION_PLAN_REQUEST_ID_NAME, id);
174  motion_plan_request_collection_->insert(planning_query, metadata);
175  RCLCPP_DEBUG(logger_, "Saved planning query '%s' for scene '%s'", id.c_str(), scene_name.c_str());
176  return id;
177 }
178 
180  const moveit_msgs::msg::RobotTrajectory& result,
181  const std::string& scene_name)
182 {
183  std::string id = getMotionPlanRequestName(planning_query, scene_name);
184  if (id.empty())
185  id = addNewPlanningRequest(planning_query, scene_name, "");
186  Metadata::Ptr metadata = robot_trajectory_collection_->createMetadata();
187  metadata->append(PLANNING_SCENE_ID_NAME, scene_name);
188  metadata->append(MOTION_PLAN_REQUEST_ID_NAME, id);
189  robot_trajectory_collection_->insert(result, metadata);
190 }
191 
192 void moveit_warehouse::PlanningSceneStorage::getPlanningSceneNames(std::vector<std::string>& names) const
193 {
194  names.clear();
195  Query::Ptr q = planning_scene_collection_->createQuery();
196  std::vector<PlanningSceneWithMetadata> planning_scenes =
197  planning_scene_collection_->queryList(q, true, PLANNING_SCENE_ID_NAME, true);
198  for (PlanningSceneWithMetadata& planning_scene : planning_scenes)
199  {
200  if (planning_scene->lookupField(PLANNING_SCENE_ID_NAME))
201  names.push_back(planning_scene->lookupString(PLANNING_SCENE_ID_NAME));
202  }
203 }
204 
206  std::vector<std::string>& names) const
207 {
208  getPlanningSceneNames(names);
209  filterNames(regex, names);
210 }
211 
212 bool moveit_warehouse::PlanningSceneStorage::getPlanningSceneWorld(moveit_msgs::msg::PlanningSceneWorld& world,
213  const std::string& scene_name) const
214 {
216  if (getPlanningScene(scene_m, scene_name))
217  {
218  world = scene_m->world;
219  return true;
220  }
221  else
222  return false;
223 }
224 
226  const std::string& scene_name) const
227 {
228  Query::Ptr q = planning_scene_collection_->createQuery();
229  q->append(PLANNING_SCENE_ID_NAME, scene_name);
230  std::vector<PlanningSceneWithMetadata> planning_scenes = planning_scene_collection_->queryList(q, false);
231  if (planning_scenes.empty())
232  {
233  RCLCPP_WARN(logger_, "Planning scene '%s' was not found in the database", scene_name.c_str());
234  return false;
235  }
236  scene_m = planning_scenes.back();
237  // in case the scene was renamed, the name in the message may be out of date
238  const_cast<moveit_msgs::msg::PlanningScene*>(static_cast<const moveit_msgs::msg::PlanningScene*>(scene_m.get()))->name =
239  scene_name;
240  return true;
241 }
242 
244  const std::string& scene_name,
245  const std::string& query_name)
246 {
247  Query::Ptr q = motion_plan_request_collection_->createQuery();
248  q->append(PLANNING_SCENE_ID_NAME, scene_name);
249  q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
250  std::vector<MotionPlanRequestWithMetadata> planning_queries = motion_plan_request_collection_->queryList(q, false);
251  if (planning_queries.empty())
252  {
253  RCLCPP_ERROR(logger_, "Planning query '%s' not found for scene '%s'", query_name.c_str(), scene_name.c_str());
254  return false;
255  }
256  else
257  {
258  query_m = planning_queries.front();
259  return true;
260  }
261 }
262 
264  std::vector<MotionPlanRequestWithMetadata>& planning_queries, const std::string& scene_name) const
265 {
266  Query::Ptr q = motion_plan_request_collection_->createQuery();
267  q->append(PLANNING_SCENE_ID_NAME, scene_name);
268  planning_queries = motion_plan_request_collection_->queryList(q, false);
269 }
270 
271 void moveit_warehouse::PlanningSceneStorage::getPlanningQueriesNames(std::vector<std::string>& query_names,
272  const std::string& scene_name) const
273 {
274  Query::Ptr q = motion_plan_request_collection_->createQuery();
275  q->append(PLANNING_SCENE_ID_NAME, scene_name);
276  std::vector<MotionPlanRequestWithMetadata> planning_queries = motion_plan_request_collection_->queryList(q, true);
277  query_names.clear();
278  for (MotionPlanRequestWithMetadata& planning_query : planning_queries)
279  {
280  if (planning_query->lookupField(MOTION_PLAN_REQUEST_ID_NAME))
281  query_names.push_back(planning_query->lookupString(MOTION_PLAN_REQUEST_ID_NAME));
282  }
283 }
284 
286  std::vector<std::string>& query_names,
287  const std::string& scene_name) const
288 {
289  getPlanningQueriesNames(query_names, scene_name);
290 
291  if (!regex.empty())
292  {
293  std::vector<std::string> fnames;
294  std::regex r(regex);
295  for (const std::string& query_name : query_names)
296  {
297  std::smatch match;
298  if (std::regex_match(query_name, match, r))
299  {
300  fnames.push_back(query_name);
301  }
302  }
303  query_names.swap(fnames);
304  }
305 }
306 
308  std::vector<MotionPlanRequestWithMetadata>& planning_queries, std::vector<std::string>& query_names,
309  const std::string& scene_name) const
310 {
311  Query::Ptr q = motion_plan_request_collection_->createQuery();
312  q->append(PLANNING_SCENE_ID_NAME, scene_name);
313  planning_queries = motion_plan_request_collection_->queryList(q, false);
314  query_names.resize(planning_queries.size());
315  for (std::size_t i = 0; i < planning_queries.size(); ++i)
316  {
317  if (planning_queries[i]->lookupField(MOTION_PLAN_REQUEST_ID_NAME))
318  {
319  query_names[i] = planning_queries[i]->lookupString(MOTION_PLAN_REQUEST_ID_NAME);
320  }
321  else
322  {
323  query_names[i].clear();
324  }
325  }
326 }
327 
329  std::vector<RobotTrajectoryWithMetadata>& planning_results, const std::string& scene_name,
330  const moveit_msgs::msg::MotionPlanRequest& planning_query) const
331 {
332  std::string id = getMotionPlanRequestName(planning_query, scene_name);
333  if (id.empty())
334  {
335  planning_results.clear();
336  }
337  else
338  {
339  getPlanningResults(planning_results, id, scene_name);
340  }
341 }
342 
344  std::vector<RobotTrajectoryWithMetadata>& planning_results, const std::string& scene_name,
345  const std::string& planning_query) const
346 {
347  Query::Ptr q = robot_trajectory_collection_->createQuery();
348  q->append(PLANNING_SCENE_ID_NAME, scene_name);
349  q->append(MOTION_PLAN_REQUEST_ID_NAME, planning_query);
350  planning_results = robot_trajectory_collection_->queryList(q, false);
351 }
352 
354  const std::string& query_name) const
355 {
356  Query::Ptr q = motion_plan_request_collection_->createQuery();
357  q->append(PLANNING_SCENE_ID_NAME, scene_name);
358  q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
359  std::vector<MotionPlanRequestWithMetadata> queries = motion_plan_request_collection_->queryList(q, true);
360  return !queries.empty();
361 }
362 
363 void moveit_warehouse::PlanningSceneStorage::renamePlanningScene(const std::string& old_scene_name,
364  const std::string& new_scene_name)
365 {
366  Query::Ptr q = planning_scene_collection_->createQuery();
367  q->append(PLANNING_SCENE_ID_NAME, old_scene_name);
368  Metadata::Ptr m = planning_scene_collection_->createMetadata();
369  m->append(PLANNING_SCENE_ID_NAME, new_scene_name);
370  planning_scene_collection_->modifyMetadata(q, m);
371  RCLCPP_DEBUG(logger_, "Renamed planning scene from '%s' to '%s'", old_scene_name.c_str(), new_scene_name.c_str());
372 }
373 
375  const std::string& old_query_name,
376  const std::string& new_query_name)
377 {
378  Query::Ptr q = motion_plan_request_collection_->createQuery();
379  q->append(PLANNING_SCENE_ID_NAME, scene_name);
380  q->append(MOTION_PLAN_REQUEST_ID_NAME, old_query_name);
381  Metadata::Ptr m = motion_plan_request_collection_->createMetadata();
382  m->append(MOTION_PLAN_REQUEST_ID_NAME, new_query_name);
383  motion_plan_request_collection_->modifyMetadata(q, m);
384  RCLCPP_DEBUG(logger_, "Renamed planning query for scene '%s' from '%s' to '%s'", scene_name.c_str(),
385  old_query_name.c_str(), new_query_name.c_str());
386 }
387 
389 {
390  removePlanningQueries(scene_name);
391  Query::Ptr q = planning_scene_collection_->createQuery();
392  q->append(PLANNING_SCENE_ID_NAME, scene_name);
393  unsigned int rem = planning_scene_collection_->removeMessages(q);
394  RCLCPP_DEBUG(logger_, "Removed %u PlanningScene messages (named '%s')", rem, scene_name.c_str());
395 }
396 
398 {
399  removePlanningResults(scene_name);
400  Query::Ptr q = motion_plan_request_collection_->createQuery();
401  q->append(PLANNING_SCENE_ID_NAME, scene_name);
402  unsigned int rem = motion_plan_request_collection_->removeMessages(q);
403  RCLCPP_DEBUG(logger_, "Removed %u MotionPlanRequest messages for scene '%s'", rem, scene_name.c_str());
404 }
405 
407  const std::string& query_name)
408 {
409  removePlanningResults(scene_name, query_name);
410  Query::Ptr q = motion_plan_request_collection_->createQuery();
411  q->append(PLANNING_SCENE_ID_NAME, scene_name);
412  q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
413  unsigned int rem = motion_plan_request_collection_->removeMessages(q);
414  RCLCPP_DEBUG(logger_, "Removed %u MotionPlanRequest messages for scene '%s', query '%s'", rem, scene_name.c_str(),
415  query_name.c_str());
416 }
417 
419 {
420  Query::Ptr q = robot_trajectory_collection_->createQuery();
421  q->append(PLANNING_SCENE_ID_NAME, scene_name);
422  unsigned int rem = robot_trajectory_collection_->removeMessages(q);
423  RCLCPP_DEBUG(logger_, "Removed %u RobotTrajectory messages for scene '%s'", rem, scene_name.c_str());
424 }
425 
427  const std::string& query_name)
428 {
429  Query::Ptr q = robot_trajectory_collection_->createQuery();
430  q->append(PLANNING_SCENE_ID_NAME, scene_name);
431  q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
432  unsigned int rem = robot_trajectory_collection_->removeMessages(q);
433  RCLCPP_DEBUG(logger_, "Removed %u RobotTrajectory messages for scene '%s', query '%s'", rem, scene_name.c_str(),
434  query_name.c_str());
435 }
This class provides the mechanism to connect to a database and reads needed ROS parameters when appro...
bool getPlanningSceneWorld(moveit_msgs::msg::PlanningSceneWorld &world, const std::string &scene_name) const
void removePlanningScene(const std::string &scene_name)
void addPlanningQuery(const moveit_msgs::msg::MotionPlanRequest &planning_query, const std::string &scene_name, const std::string &query_name="")
void removePlanningQuery(const std::string &scene_name, const std::string &query_name)
void getPlanningResults(std::vector< RobotTrajectoryWithMetadata > &planning_results, const std::string &scene_name, const moveit_msgs::msg::MotionPlanRequest &planning_query) const
void removePlanningQueries(const std::string &scene_name)
PlanningSceneStorage(warehouse_ros::DatabaseConnection::Ptr conn)
void addPlanningResult(const moveit_msgs::msg::MotionPlanRequest &planning_query, const moveit_msgs::msg::RobotTrajectory &result, const std::string &scene_name)
void renamePlanningQuery(const std::string &scene_name, const std::string &old_query_name, const std::string &new_query_name)
bool hasPlanningQuery(const std::string &scene_name, const std::string &query_name) const
void getPlanningQueries(std::vector< MotionPlanRequestWithMetadata > &planning_queries, const std::string &scene_name) const
void removePlanningResults(const std::string &scene_name)
void addPlanningScene(const moveit_msgs::msg::PlanningScene &scene)
bool getPlanningQuery(MotionPlanRequestWithMetadata &query_m, const std::string &scene_name, const std::string &query_name)
void renamePlanningScene(const std::string &old_scene_name, const std::string &new_scene_name)
void getPlanningSceneNames(std::vector< std::string > &names) const
void getPlanningQueriesNames(std::vector< std::string > &query_names, const std::string &scene_name) const
bool hasPlanningScene(const std::string &name) const
static const std::string MOTION_PLAN_REQUEST_ID_NAME
bool getPlanningScene(PlanningSceneWithMetadata &scene_m, const std::string &scene_name) const
Get the latest planning scene named scene_name.
warehouse_ros::MessageWithMetadata< moveit_msgs::msg::PlanningScene >::ConstPtr PlanningSceneWithMetadata
warehouse_ros::MessageWithMetadata< moveit_msgs::msg::MotionPlanRequest >::ConstPtr MotionPlanRequestWithMetadata
Main namespace for MoveIt.
Definition: exceptions.h:43
moveit_msgs::msg::MotionPlanRequest MotionPlanRequest
This namespace includes the central class for representing planning contexts.
name
Definition: setup.py:7