moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
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>
42
43const std::string moveit_warehouse::PlanningSceneStorage::DATABASE_NAME = "moveit_planning_scenes";
44
45const std::string moveit_warehouse::PlanningSceneStorage::PLANNING_SCENE_ID_NAME = "planning_scene_id";
47
48using warehouse_ros::Metadata;
49using warehouse_ros::Query;
50
51moveit_warehouse::PlanningSceneStorage::PlanningSceneStorage(warehouse_ros::DatabaseConnection::Ptr conn)
52 : MoveItMessageStorage(std::move(conn)), logger_(moveit::getLogger("moveit.ros.warehouse_planning_scene_storage"))
53{
54 createCollections();
55}
56
57void 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
76void 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
98std::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
136void moveit_warehouse::PlanningSceneStorage::addPlanningQuery(const moveit_msgs::msg::MotionPlanRequest& planning_query,
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
150std::string
151moveit_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
179void moveit_warehouse::PlanningSceneStorage::addPlanningResult(const moveit_msgs::msg::MotionPlanRequest& planning_query,
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
192void 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
212bool 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
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
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
This namespace includes the central class for representing planning contexts.