25#include <rclcpp/rclcpp.hpp>
26#include <rclcpp/logging.hpp>
28#include <warehouse_ros/message_collection.h>
29#include <warehouse_ros/database_connection.h>
31#include <geometry_msgs/msg/pose.hpp>
32#include <geometry_msgs/msg/pose_stamped.hpp>
34#include <moveit_msgs/msg/motion_plan_request.hpp>
35#include <moveit_msgs/msg/robot_trajectory.hpp>
36#include <moveit_msgs/srv/get_cartesian_path.hpp>
62using ::warehouse_ros::MessageCollection;
63using ::warehouse_ros::MessageWithMetadata;
64using ::warehouse_ros::Metadata;
65using ::warehouse_ros::Query;
67using ::moveit::core::MoveItErrorCode;
68using ::moveit::planning_interface::MoveGroupInterface;
70using ::moveit_msgs::msg::MotionPlanRequest;
71using ::moveit_msgs::msg::RobotTrajectory;
72using ::moveit_msgs::srv::GetCartesianPath;
74using ::moveit_ros::trajectory_cache::BestSeenExecutionTimePolicy;
75using ::moveit_ros::trajectory_cache::CacheInsertPolicyInterface;
76using ::moveit_ros::trajectory_cache::CartesianBestSeenExecutionTimePolicy;
78using ::moveit_ros::trajectory_cache::FeaturesInterface;
83const std::string EXECUTION_TIME =
"execution_time_s";
91std::vector<std::unique_ptr<FeaturesInterface<MotionPlanRequest>>>
97std::unique_ptr<CacheInsertPolicyInterface<MotionPlanRequest, MoveGroupInterface::Plan, RobotTrajectory>>
100 return std::make_unique<BestSeenExecutionTimePolicy>();
103std::vector<std::unique_ptr<FeaturesInterface<GetCartesianPath::Request>>>
109std::unique_ptr<CacheInsertPolicyInterface<GetCartesianPath::Request, GetCartesianPath::Response, RobotTrajectory>>
112 return std::make_unique<CartesianBestSeenExecutionTimePolicy>();
117 return EXECUTION_TIME;
125 : node_(node), logger_(
moveit::
getLogger(
"moveit.ros.trajectory_cache"))
131 RCLCPP_DEBUG(logger_,
"Opening trajectory cache database at: %s (Port: %d, Precision: %f)", options.db_path.c_str(),
132 options.db_port, options.exact_match_precision);
139 db_->setParams(options.db_path, options.db_port);
140 return db_->connect();
149 MessageCollection<RobotTrajectory> coll =
150 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
156 MessageCollection<RobotTrajectory> coll =
157 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
163 return options_.db_path;
168 return options_.db_port;
173 return options_.exact_match_precision;
178 options_.exact_match_precision = exact_match_precision;
183 return options_.num_additional_trajectories_to_preserve_when_pruning_worse;
187 size_t num_additional_trajectories_to_preserve_when_pruning_worse)
189 options_.num_additional_trajectories_to_preserve_when_pruning_worse =
190 num_additional_trajectories_to_preserve_when_pruning_worse;
200 bool ascending,
bool metadata_only)
const
202 MessageCollection<RobotTrajectory> coll =
203 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
205 Query::Ptr query = coll.createQuery();
206 for (
const auto& feature : features)
209 feature->appendFeaturesAsFuzzyFetchQuery(*query, plan_request,
move_group,
210 options_.exact_match_precision);
213 RCLCPP_ERROR_STREAM(logger_,
"Could not construct trajectory query: " << ret.message);
217 return coll.queryList(query, metadata_only, sort_by, ascending);
223 bool ascending,
bool metadata_only)
const
226 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_trajectories =
229 if (matching_trajectories.empty())
231 RCLCPP_DEBUG(logger_,
"No matching trajectories found.");
235 MessageCollection<RobotTrajectory> coll =
236 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
239 int best_trajectory_id = matching_trajectories.at(0)->lookupInt(
"id");
240 Query::Ptr best_query = coll.createQuery();
241 best_query->append(
"id", best_trajectory_id);
243 return coll.findOne(best_query, metadata_only);
250 bool prune_worse_trajectories,
253 MessageCollection<RobotTrajectory> coll =
254 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
259 RCLCPP_ERROR_STREAM(logger_,
"Skipping trajectory insert, invalid inputs: " << ret.message);
260 cache_insert_policy.
reset();
264 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_entries =
268 if (prune_worse_trajectories)
270 size_t preserved_count = 0;
271 for (
const auto& matching_entry : matching_entries)
273 std::string prune_reason;
274 if (++preserved_count > options_.num_additional_trajectories_to_preserve_when_pruning_worse &&
277 int delete_id = matching_entry->lookupInt(
"id");
278 RCLCPP_DEBUG_STREAM(logger_,
"Pruning plan (id: `" << delete_id <<
"`): " << prune_reason);
280 Query::Ptr delete_query = coll.createQuery();
281 delete_query->append(
"id", delete_id);
282 coll.removeMessages(delete_query);
288 std::string insert_reason;
291 Metadata::Ptr insert_metadata = coll.createMetadata();
296 RCLCPP_ERROR_STREAM(logger_,
297 "Skipping trajectory insert: Could not construct insert metadata from cache_insert_policy: "
298 << cache_insert_policy.
getName() <<
": " << ret.message);
299 cache_insert_policy.
reset();
303 for (
const auto& additional_feature : additional_features)
306 additional_feature->appendFeaturesAsInsertMetadata(*insert_metadata, plan_request,
move_group);
309 RCLCPP_ERROR_STREAM(logger_,
310 "Skipping trajectory insert: Could not construct insert metadata additional_feature: "
311 << additional_feature->getName() <<
": " << ret.message);
312 cache_insert_policy.
reset();
317 RCLCPP_DEBUG_STREAM(logger_,
"Inserting trajectory:" << insert_reason);
318 coll.insert(plan.
trajectory, insert_metadata);
319 cache_insert_policy.
reset();
324 RCLCPP_DEBUG_STREAM(logger_,
"Skipping trajectory insert:" << insert_reason);
325 cache_insert_policy.
reset();
336 const GetCartesianPath::Request& plan_request,
338 const std::string& sort_by,
bool ascending,
bool metadata_only)
const
340 MessageCollection<RobotTrajectory> coll =
341 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
343 Query::Ptr query = coll.createQuery();
344 for (
const auto& feature : features)
347 feature->appendFeaturesAsFuzzyFetchQuery(*query, plan_request,
move_group,
348 options_.exact_match_precision);
351 RCLCPP_ERROR_STREAM(logger_,
"Could not construct cartesian trajectory query: " << ret.message);
355 return coll.queryList(query, metadata_only, sort_by, ascending);
360 const GetCartesianPath::Request& plan_request,
362 const std::string& sort_by,
bool ascending,
bool metadata_only)
const
365 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_trajectories =
368 if (matching_trajectories.empty())
370 RCLCPP_DEBUG(logger_,
"No matching cartesian trajectories found.");
374 MessageCollection<RobotTrajectory> coll =
375 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
378 int best_trajectory_id = matching_trajectories.at(0)->lookupInt(
"id");
379 Query::Ptr best_query = coll.createQuery();
380 best_query->append(
"id", best_trajectory_id);
382 return coll.findOne(best_query, metadata_only);
387 const GetCartesianPath::Request& plan_request,
const GetCartesianPath::Response& plan,
390 bool prune_worse_trajectories,
393 MessageCollection<RobotTrajectory> coll =
394 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
399 RCLCPP_ERROR_STREAM(logger_,
"Skipping cartesian trajectory insert, invalid inputs: " << ret.message);
400 cache_insert_policy.
reset();
404 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_entries =
408 if (prune_worse_trajectories)
410 size_t preserved_count = 0;
411 for (
const auto& matching_entry : matching_entries)
413 std::string prune_reason;
414 if (++preserved_count > options_.num_additional_trajectories_to_preserve_when_pruning_worse &&
417 int delete_id = matching_entry->lookupInt(
"id");
418 RCLCPP_DEBUG_STREAM(logger_,
"Pruning cartesian trajectory (id: `" << delete_id <<
"`): " << prune_reason);
420 Query::Ptr delete_query = coll.createQuery();
421 delete_query->append(
"id", delete_id);
422 coll.removeMessages(delete_query);
428 std::string insert_reason;
431 Metadata::Ptr insert_metadata = coll.createMetadata();
436 RCLCPP_ERROR_STREAM(logger_,
"Skipping cartesian trajectory insert: Could not construct insert metadata from "
437 "cache_insert_policy: "
438 << cache_insert_policy.
getName() <<
": " << ret.message);
439 cache_insert_policy.
reset();
443 for (
const auto& additional_feature : additional_features)
446 additional_feature->appendFeaturesAsInsertMetadata(*insert_metadata, plan_request,
move_group);
450 logger_,
"Skipping cartesian trajectory insert: Could not construct insert metadata additional_feature: "
451 << additional_feature->getName() <<
": " << ret.message);
452 cache_insert_policy.
reset();
457 RCLCPP_DEBUG_STREAM(logger_,
"Inserting cartesian trajectory:" << insert_reason);
458 coll.insert(plan.solution, insert_metadata);
459 cache_insert_policy.
reset();
464 RCLCPP_DEBUG_STREAM(logger_,
"Skipping cartesian insert:" << insert_reason);
465 cache_insert_policy.
reset();
A cache insertion policy that only decides to insert if the motion plan is the one with the shortest ...
Abstract template class for injecting logic for determining when to prune and insert a cache entry,...
a wrapper around moveit_msgs::MoveItErrorCodes to make it easier to return an error code message from...
Client class to conveniently use the ROS interfaces provided by the move_group node.
static std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::msg::MotionPlanRequest > > > getSupportedFeatures(double start_tolerance, double goal_tolerance)
Configures and returns a vector of feature extractors that can be used with this policy.
virtual bool shouldInsert(const moveit::planning_interface::MoveGroupInterface &move_group, const KeyT &key, const ValueT &value, std::string *reason)=0
Returns whether the insertion candidate should be inserted into the cache.
virtual bool shouldPruneMatchingEntry(const moveit::planning_interface::MoveGroupInterface &move_group, const KeyT &key, const ValueT &value, const typename warehouse_ros::MessageWithMetadata< CacheEntryT >::ConstPtr &matching_entry, std::string *reason)=0
Returns whether a matched cache entry should be pruned.
virtual moveit::core::MoveItErrorCode appendInsertMetadata(warehouse_ros::Metadata &metadata, const moveit::planning_interface::MoveGroupInterface &move_group, const KeyT &key, const ValueT &value)=0
Appends the insert metadata with the features supported by the policy.
virtual void reset()=0
Resets the state of the policy.
virtual std::vector< typename warehouse_ros::MessageWithMetadata< CacheEntryT >::ConstPtr > fetchMatchingEntries(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< CacheEntryT > &coll, const KeyT &key, const ValueT &value, double exact_match_precision)=0
Fetches all "matching" cache entries for comparison for pruning.
virtual std::string getName() const =0
Gets the name of the cache insert policy.
virtual moveit::core::MoveItErrorCode checkCacheInsertInputs(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< CacheEntryT > &coll, const KeyT &key, const ValueT &value)=0
Checks inputs to the cache insert call to see if we should abort instead.
static std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::srv::GetCartesianPath::Request > > > getSupportedFeatures(double start_tolerance, double goal_tolerance, double min_fraction)
Configures and returns a vector of feature extractors that can be used with this policy.
unsigned countCartesianTrajectories(const std::string &cache_namespace)
Count the number of cartesian trajectories for a particular cache namespace.
static std::unique_ptr< CacheInsertPolicyInterface< moveit_msgs::msg::MotionPlanRequest, moveit::planning_interface::MoveGroupInterface::Plan, moveit_msgs::msg::RobotTrajectory > > getDefaultCacheInsertPolicy()
Gets the default cache insert policy for MotionPlanRequest messages.
warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr fetchBestMatchingTrajectory(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::msg::MotionPlanRequest &plan_request, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::msg::MotionPlanRequest > > > &features, const std::string &sort_by, bool ascending=true, bool metadata_only=false) const
Fetches the best trajectory keyed on user-specified features, with respect to some cache feature.
size_t getNumAdditionalTrajectoriesToPreserveWhenPruningWorse() const
Get the number of trajectories to preserve when pruning worse trajectories.
unsigned countTrajectories(const std::string &cache_namespace)
Count the number of non-cartesian trajectories for a particular cache namespace.
static std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::srv::GetCartesianPath::Request > > > getDefaultCartesianFeatures(double start_tolerance, double goal_tolerance, double min_fraction)
Gets the default features for GetCartesianPath requests.
TrajectoryCache(const rclcpp::Node::SharedPtr &node)
Constructs a TrajectoryCache.
static std::string getDefaultSortFeature()
Gets the default sort feature.
double getExactMatchPrecision() const
Gets the exact match precision.
std::vector< warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr > fetchAllMatchingTrajectories(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::msg::MotionPlanRequest &plan_request, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::msg::MotionPlanRequest > > > &features, const std::string &sort_by, bool ascending=true, bool metadata_only=false) const
Fetches all trajectories keyed on user-specified features, returning them as a vector,...
bool insertCartesianTrajectory(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::srv::GetCartesianPath::Request &plan_request, const moveit_msgs::srv::GetCartesianPath::Response &plan, CacheInsertPolicyInterface< moveit_msgs::srv::GetCartesianPath::Request, moveit_msgs::srv::GetCartesianPath::Response, moveit_msgs::msg::RobotTrajectory > &cache_insert_policy, bool prune_worse_trajectories=true, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::srv::GetCartesianPath::Request > > > &additional_features={})
Inserts a cartesian trajectory into the database, with user-specified insert policy.
void setNumAdditionalTrajectoriesToPreserveWhenPruningWorse(size_t num_additional_trajectories_to_preserve_when_pruning_worse)
Set the number of additional trajectories to preserve when pruning worse trajectories.
static std::unique_ptr< CacheInsertPolicyInterface< moveit_msgs::srv::GetCartesianPath::Request, moveit_msgs::srv::GetCartesianPath::Response, moveit_msgs::msg::RobotTrajectory > > getDefaultCartesianCacheInsertPolicy()
Gets the default cache insert policy for GetCartesianPath requests.
void setExactMatchPrecision(double exact_match_precision)
Sets the exact match precision.
bool insertTrajectory(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::msg::MotionPlanRequest &plan_request, const moveit::planning_interface::MoveGroupInterface::Plan &plan, CacheInsertPolicyInterface< moveit_msgs::msg::MotionPlanRequest, moveit::planning_interface::MoveGroupInterface::Plan, moveit_msgs::msg::RobotTrajectory > &cache_insert_policy, bool prune_worse_trajectories=true, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::msg::MotionPlanRequest > > > &additional_features={})
Inserts a trajectory into the database, with user-specified insert policy.
std::string getDbPath() const
Gets the database path.
static std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::msg::MotionPlanRequest > > > getDefaultFeatures(double start_tolerance, double goal_tolerance)
Gets the default features for MotionPlanRequest messages.
bool init(const Options &options)
Initializes the TrajectoryCache.
warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr fetchBestMatchingCartesianTrajectory(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::srv::GetCartesianPath::Request &plan_request, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::srv::GetCartesianPath::Request > > > &features, const std::string &sort_by, bool ascending=true, bool metadata_only=false) const
Fetches the best cartesian trajectory keyed on user-specified features, with respect to some cache fe...
uint32_t getDbPort() const
Gets the database port.
std::vector< warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr > fetchAllMatchingCartesianTrajectories(const moveit::planning_interface::MoveGroupInterface &move_group, const std::string &cache_namespace, const moveit_msgs::srv::GetCartesianPath::Request &plan_request, const std::vector< std::unique_ptr< FeaturesInterface< moveit_msgs::srv::GetCartesianPath::Request > > > &features, const std::string &sort_by, bool ascending=true, bool metadata_only=false) const
Fetches all cartesian trajectories keyed on user-specified features, returning them as a vector,...
User-specified constant features to key the trajectory cache on.
Abstract template class for extracting features from some FeatureSourceT.
moveit_msgs::srv::GetCartesianPath::Request features to key the trajectory cache on.
moveit_msgs::msg::MotionPlanRequest features to key the trajectory cache on.
Utilities used by the trajectory_cache package.
warehouse_ros::DatabaseConnection::Ptr loadDatabase(const rclcpp::Node::SharedPtr &node)
Load a database connection.
Main namespace for MoveIt.
The representation of a motion plan (as ROS messages).
robot_trajectory::RobotTrajectoryPtr trajectory
rclcpp::Logger getLogger()
Fuzzy-Matching Trajectory Cache.