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{
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 {
223 return false;
224 }
225}
226
228 const std::string& scene_name) const
229{
230 Query::Ptr q = planning_scene_collection_->createQuery();
231 q->append(PLANNING_SCENE_ID_NAME, scene_name);
232 std::vector<PlanningSceneWithMetadata> planning_scenes = planning_scene_collection_->queryList(q, false);
233 if (planning_scenes.empty())
234 {
235 RCLCPP_WARN(logger_, "Planning scene '%s' was not found in the database", scene_name.c_str());
236 return false;
237 }
238 scene_m = planning_scenes.back();
239 // in case the scene was renamed, the name in the message may be out of date
240 const_cast<moveit_msgs::msg::PlanningScene*>(static_cast<const moveit_msgs::msg::PlanningScene*>(scene_m.get()))->name =
241 scene_name;
242 return true;
243}
244
246 const std::string& scene_name,
247 const std::string& query_name)
248{
249 Query::Ptr q = motion_plan_request_collection_->createQuery();
250 q->append(PLANNING_SCENE_ID_NAME, scene_name);
251 q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
252 std::vector<MotionPlanRequestWithMetadata> planning_queries = motion_plan_request_collection_->queryList(q, false);
253 if (planning_queries.empty())
254 {
255 RCLCPP_ERROR(logger_, "Planning query '%s' not found for scene '%s'", query_name.c_str(), scene_name.c_str());
256 return false;
257 }
258 else
259 {
260 query_m = planning_queries.front();
261 return true;
262 }
263}
264
266 std::vector<MotionPlanRequestWithMetadata>& planning_queries, const std::string& scene_name) const
267{
268 Query::Ptr q = motion_plan_request_collection_->createQuery();
269 q->append(PLANNING_SCENE_ID_NAME, scene_name);
270 planning_queries = motion_plan_request_collection_->queryList(q, false);
271}
272
274 const std::string& scene_name) const
275{
276 Query::Ptr q = motion_plan_request_collection_->createQuery();
277 q->append(PLANNING_SCENE_ID_NAME, scene_name);
278 std::vector<MotionPlanRequestWithMetadata> planning_queries = motion_plan_request_collection_->queryList(q, true);
279 query_names.clear();
280 for (MotionPlanRequestWithMetadata& planning_query : planning_queries)
281 {
282 if (planning_query->lookupField(MOTION_PLAN_REQUEST_ID_NAME))
283 query_names.push_back(planning_query->lookupString(MOTION_PLAN_REQUEST_ID_NAME));
284 }
285}
286
288 std::vector<std::string>& query_names,
289 const std::string& scene_name) const
290{
291 getPlanningQueriesNames(query_names, scene_name);
292
293 if (!regex.empty())
294 {
295 std::vector<std::string> fnames;
296 std::regex r(regex);
297 for (const std::string& query_name : query_names)
298 {
299 std::smatch match;
300 if (std::regex_match(query_name, match, r))
301 {
302 fnames.push_back(query_name);
303 }
304 }
305 query_names.swap(fnames);
306 }
307}
308
310 std::vector<MotionPlanRequestWithMetadata>& planning_queries, std::vector<std::string>& query_names,
311 const std::string& scene_name) const
312{
313 Query::Ptr q = motion_plan_request_collection_->createQuery();
314 q->append(PLANNING_SCENE_ID_NAME, scene_name);
315 planning_queries = motion_plan_request_collection_->queryList(q, false);
316 query_names.resize(planning_queries.size());
317 for (std::size_t i = 0; i < planning_queries.size(); ++i)
318 {
319 if (planning_queries[i]->lookupField(MOTION_PLAN_REQUEST_ID_NAME))
320 {
321 query_names[i] = planning_queries[i]->lookupString(MOTION_PLAN_REQUEST_ID_NAME);
322 }
323 else
324 {
325 query_names[i].clear();
326 }
327 }
328}
329
331 std::vector<RobotTrajectoryWithMetadata>& planning_results, const std::string& scene_name,
332 const moveit_msgs::msg::MotionPlanRequest& planning_query) const
333{
334 std::string id = getMotionPlanRequestName(planning_query, scene_name);
335 if (id.empty())
336 {
337 planning_results.clear();
338 }
339 else
340 {
341 getPlanningResults(planning_results, id, scene_name);
342 }
343}
344
346 std::vector<RobotTrajectoryWithMetadata>& planning_results, const std::string& scene_name,
347 const std::string& planning_query) const
348{
349 Query::Ptr q = robot_trajectory_collection_->createQuery();
350 q->append(PLANNING_SCENE_ID_NAME, scene_name);
351 q->append(MOTION_PLAN_REQUEST_ID_NAME, planning_query);
352 planning_results = robot_trajectory_collection_->queryList(q, false);
353}
354
356 const std::string& query_name) const
357{
358 Query::Ptr q = motion_plan_request_collection_->createQuery();
359 q->append(PLANNING_SCENE_ID_NAME, scene_name);
360 q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
361 std::vector<MotionPlanRequestWithMetadata> queries = motion_plan_request_collection_->queryList(q, true);
362 return !queries.empty();
363}
364
366 const std::string& new_scene_name)
367{
368 Query::Ptr q = planning_scene_collection_->createQuery();
369 q->append(PLANNING_SCENE_ID_NAME, old_scene_name);
370 Metadata::Ptr m = planning_scene_collection_->createMetadata();
371 m->append(PLANNING_SCENE_ID_NAME, new_scene_name);
372 planning_scene_collection_->modifyMetadata(q, m);
373 RCLCPP_DEBUG(logger_, "Renamed planning scene from '%s' to '%s'", old_scene_name.c_str(), new_scene_name.c_str());
374}
375
377 const std::string& old_query_name,
378 const std::string& new_query_name)
379{
380 Query::Ptr q = motion_plan_request_collection_->createQuery();
381 q->append(PLANNING_SCENE_ID_NAME, scene_name);
382 q->append(MOTION_PLAN_REQUEST_ID_NAME, old_query_name);
383 Metadata::Ptr m = motion_plan_request_collection_->createMetadata();
384 m->append(MOTION_PLAN_REQUEST_ID_NAME, new_query_name);
385 motion_plan_request_collection_->modifyMetadata(q, m);
386 RCLCPP_DEBUG(logger_, "Renamed planning query for scene '%s' from '%s' to '%s'", scene_name.c_str(),
387 old_query_name.c_str(), new_query_name.c_str());
388}
389
391{
392 removePlanningQueries(scene_name);
393 Query::Ptr q = planning_scene_collection_->createQuery();
394 q->append(PLANNING_SCENE_ID_NAME, scene_name);
395 unsigned int rem = planning_scene_collection_->removeMessages(q);
396 RCLCPP_DEBUG(logger_, "Removed %u PlanningScene messages (named '%s')", rem, scene_name.c_str());
397}
398
400{
401 removePlanningResults(scene_name);
402 Query::Ptr q = motion_plan_request_collection_->createQuery();
403 q->append(PLANNING_SCENE_ID_NAME, scene_name);
404 unsigned int rem = motion_plan_request_collection_->removeMessages(q);
405 RCLCPP_DEBUG(logger_, "Removed %u MotionPlanRequest messages for scene '%s'", rem, scene_name.c_str());
406}
407
409 const std::string& query_name)
410{
411 removePlanningResults(scene_name, query_name);
412 Query::Ptr q = motion_plan_request_collection_->createQuery();
413 q->append(PLANNING_SCENE_ID_NAME, scene_name);
414 q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
415 unsigned int rem = motion_plan_request_collection_->removeMessages(q);
416 RCLCPP_DEBUG(logger_, "Removed %u MotionPlanRequest messages for scene '%s', query '%s'", rem, scene_name.c_str(),
417 query_name.c_str());
418}
419
421{
422 Query::Ptr q = robot_trajectory_collection_->createQuery();
423 q->append(PLANNING_SCENE_ID_NAME, scene_name);
424 unsigned int rem = robot_trajectory_collection_->removeMessages(q);
425 RCLCPP_DEBUG(logger_, "Removed %u RobotTrajectory messages for scene '%s'", rem, scene_name.c_str());
426}
427
429 const std::string& query_name)
430{
431 Query::Ptr q = robot_trajectory_collection_->createQuery();
432 q->append(PLANNING_SCENE_ID_NAME, scene_name);
433 q->append(MOTION_PLAN_REQUEST_ID_NAME, query_name);
434 unsigned int rem = robot_trajectory_collection_->removeMessages(q);
435 RCLCPP_DEBUG(logger_, "Removed %u RobotTrajectory messages for scene '%s', query '%s'", rem, scene_name.c_str(),
436 query_name.c_str());
437}
warehouse_ros::DatabaseConnection::Ptr conn_
void filterNames(const std::string &regex, std::vector< std::string > &names) const
Keep only the names that match regex.
MoveItMessageStorage(warehouse_ros::DatabaseConnection::Ptr conn)
Takes a warehouse_ros DatabaseConnection. The DatabaseConnection is expected to have already been ini...
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
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.
This namespace includes the central class for representing planning contexts.