24#include <rclcpp/rclcpp.hpp>
25#include <rclcpp/logging.hpp>
27#include <warehouse_ros/message_collection.h>
28#include <warehouse_ros/database_connection.h>
30#include <geometry_msgs/msg/pose.hpp>
31#include <geometry_msgs/msg/pose_stamped.hpp>
33#include <moveit_msgs/msg/motion_plan_request.hpp>
34#include <moveit_msgs/msg/robot_trajectory.hpp>
35#include <moveit_msgs/srv/get_cartesian_path.hpp>
58namespace trajectory_cache
61using ::warehouse_ros::MessageCollection;
62using ::warehouse_ros::MessageWithMetadata;
63using ::warehouse_ros::Metadata;
64using ::warehouse_ros::Query;
66using ::moveit::core::MoveItErrorCode;
67using ::moveit::planning_interface::MoveGroupInterface;
69using ::moveit_msgs::msg::MotionPlanRequest;
70using ::moveit_msgs::msg::RobotTrajectory;
71using ::moveit_msgs::srv::GetCartesianPath;
73using ::moveit_ros::trajectory_cache::BestSeenExecutionTimePolicy;
74using ::moveit_ros::trajectory_cache::CacheInsertPolicyInterface;
75using ::moveit_ros::trajectory_cache::CartesianBestSeenExecutionTimePolicy;
77using ::moveit_ros::trajectory_cache::FeaturesInterface;
82const std::string EXECUTION_TIME =
"execution_time_s";
83const std::string FRACTION =
"fraction";
84const std::string PLANNING_TIME =
"planning_time_s";
92std::vector<std::unique_ptr<FeaturesInterface<MotionPlanRequest>>>
98std::unique_ptr<CacheInsertPolicyInterface<MotionPlanRequest, MoveGroupInterface::Plan, RobotTrajectory>>
101 return std::make_unique<BestSeenExecutionTimePolicy>();
104std::vector<std::unique_ptr<FeaturesInterface<GetCartesianPath::Request>>>
110std::unique_ptr<CacheInsertPolicyInterface<GetCartesianPath::Request, GetCartesianPath::Response, RobotTrajectory>>
113 return std::make_unique<CartesianBestSeenExecutionTimePolicy>();
118 return EXECUTION_TIME;
126 : node_(node), logger_(
moveit::getLogger(
"moveit.ros.trajectory_cache"))
132 RCLCPP_DEBUG(logger_,
"Opening trajectory cache database at: %s (Port: %d, Precision: %f)", options.db_path.c_str(),
133 options.db_port, options.exact_match_precision);
140 db_->setParams(options.db_path, options.db_port);
141 return db_->connect();
150 MessageCollection<RobotTrajectory> coll =
151 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
157 MessageCollection<RobotTrajectory> coll =
158 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
188 size_t num_additional_trajectories_to_preserve_when_pruning_worse)
191 num_additional_trajectories_to_preserve_when_pruning_worse;
199 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
const MotionPlanRequest& plan_request,
201 bool ascending,
bool metadata_only)
const
203 MessageCollection<RobotTrajectory> coll =
204 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
206 Query::Ptr query = coll.createQuery();
207 for (
const auto& feature : features)
209 if (MoveItErrorCode ret =
210 feature->appendFeaturesAsFuzzyFetchQuery(*query, plan_request,
move_group,
214 RCLCPP_ERROR_STREAM(logger_,
"Could not construct trajectory query: " << ret.message);
218 return coll.queryList(query, metadata_only, sort_by, ascending);
222 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
const MotionPlanRequest& plan_request,
224 bool ascending,
bool metadata_only)
const
227 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_trajectories =
230 if (matching_trajectories.empty())
232 RCLCPP_DEBUG(logger_,
"No matching trajectories found.");
236 MessageCollection<RobotTrajectory> coll =
237 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
240 int best_trajectory_id = matching_trajectories.at(0)->lookupInt(
"id");
241 Query::Ptr best_query = coll.createQuery();
242 best_query->append(
"id", best_trajectory_id);
244 return coll.findOne(best_query, metadata_only);
248 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
const MotionPlanRequest& plan_request,
249 const MoveGroupInterface::Plan& plan,
251 bool prune_worse_trajectories,
254 MessageCollection<RobotTrajectory> coll =
255 db_->openCollection<RobotTrajectory>(
"move_group_trajectory_cache", cache_namespace);
260 RCLCPP_ERROR_STREAM(logger_,
"Skipping trajectory insert, invalid inputs: " << ret.message);
261 cache_insert_policy.
reset();
265 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_entries =
269 if (prune_worse_trajectories)
271 size_t preserved_count = 0;
272 for (
const auto& matching_entry : matching_entries)
274 std::string prune_reason;
278 int delete_id = matching_entry->lookupInt(
"id");
279 RCLCPP_DEBUG_STREAM(logger_,
"Pruning plan (id: `" << delete_id <<
"`): " << prune_reason);
281 Query::Ptr delete_query = coll.createQuery();
282 delete_query->append(
"id", delete_id);
283 coll.removeMessages(delete_query);
289 std::string insert_reason;
292 Metadata::Ptr insert_metadata = coll.createMetadata();
297 RCLCPP_ERROR_STREAM(logger_,
298 "Skipping trajectory insert: Could not construct insert metadata from cache_insert_policy: "
299 << cache_insert_policy.
getName() <<
": " << ret.message);
300 cache_insert_policy.
reset();
304 for (
const auto& additional_feature : additional_features)
306 if (MoveItErrorCode ret =
307 additional_feature->appendFeaturesAsInsertMetadata(*insert_metadata, plan_request,
move_group);
310 RCLCPP_ERROR_STREAM(logger_,
311 "Skipping trajectory insert: Could not construct insert metadata additional_feature: "
312 << additional_feature->getName() <<
": " << ret.message);
313 cache_insert_policy.
reset();
318 RCLCPP_DEBUG_STREAM(logger_,
"Inserting trajectory:" << insert_reason);
319 coll.insert(plan.
trajectory, insert_metadata);
320 cache_insert_policy.
reset();
325 RCLCPP_DEBUG_STREAM(logger_,
"Skipping trajectory insert:" << insert_reason);
326 cache_insert_policy.
reset();
336 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
337 const GetCartesianPath::Request& plan_request,
339 const std::string& sort_by,
bool ascending,
bool metadata_only)
const
341 MessageCollection<RobotTrajectory> coll =
342 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
344 Query::Ptr query = coll.createQuery();
345 for (
const auto& feature : features)
347 if (MoveItErrorCode ret =
348 feature->appendFeaturesAsFuzzyFetchQuery(*query, plan_request,
move_group,
352 RCLCPP_ERROR_STREAM(logger_,
"Could not construct cartesian trajectory query: " << ret.message);
356 return coll.queryList(query, metadata_only, sort_by, ascending);
360 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
361 const GetCartesianPath::Request& plan_request,
363 const std::string& sort_by,
bool ascending,
bool metadata_only)
const
366 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_trajectories =
369 if (matching_trajectories.empty())
371 RCLCPP_DEBUG(logger_,
"No matching cartesian trajectories found.");
375 MessageCollection<RobotTrajectory> coll =
376 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
379 int best_trajectory_id = matching_trajectories.at(0)->lookupInt(
"id");
380 Query::Ptr best_query = coll.createQuery();
381 best_query->append(
"id", best_trajectory_id);
383 return coll.findOne(best_query, metadata_only);
387 const MoveGroupInterface&
move_group,
const std::string& cache_namespace,
388 const GetCartesianPath::Request& plan_request,
const GetCartesianPath::Response& plan,
391 bool prune_worse_trajectories,
394 MessageCollection<RobotTrajectory> coll =
395 db_->openCollection<RobotTrajectory>(
"move_group_cartesian_trajectory_cache", cache_namespace);
400 RCLCPP_ERROR_STREAM(logger_,
"Skipping cartesian trajectory insert, invalid inputs: " << ret.message);
401 cache_insert_policy.
reset();
405 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> matching_entries =
409 if (prune_worse_trajectories)
411 size_t preserved_count = 0;
412 for (
const auto& matching_entry : matching_entries)
414 std::string prune_reason;
418 int delete_id = matching_entry->lookupInt(
"id");
419 RCLCPP_DEBUG_STREAM(logger_,
"Pruning cartesian trajectory (id: `" << delete_id <<
"`): " << prune_reason);
421 Query::Ptr delete_query = coll.createQuery();
422 delete_query->append(
"id", delete_id);
423 coll.removeMessages(delete_query);
429 std::string insert_reason;
432 Metadata::Ptr insert_metadata = coll.createMetadata();
437 RCLCPP_ERROR_STREAM(logger_,
"Skipping cartesian trajectory insert: Could not construct insert metadata from "
438 "cache_insert_policy: "
439 << cache_insert_policy.
getName() <<
": " << ret.message);
440 cache_insert_policy.
reset();
444 for (
const auto& additional_feature : additional_features)
446 if (MoveItErrorCode ret =
447 additional_feature->appendFeaturesAsInsertMetadata(*insert_metadata, plan_request,
move_group);
451 logger_,
"Skipping cartesian trajectory insert: Could not construct insert metadata additional_feature: "
452 << additional_feature->getName() <<
": " << ret.message);
453 cache_insert_policy.
reset();
458 RCLCPP_DEBUG_STREAM(logger_,
"Inserting cartesian trajectory:" << insert_reason);
459 coll.insert(plan.solution, insert_metadata);
460 cache_insert_policy.
reset();
465 RCLCPP_DEBUG_STREAM(logger_,
"Skipping cartesian insert:" << insert_reason);
466 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,...
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.
double exact_match_precision
size_t num_additional_trajectories_to_preserve_when_pruning_worse
robot_trajectory::RobotTrajectoryPtr trajectory
Fuzzy-Matching Trajectory Cache.