29#include <warehouse_ros/message_collection.h>
32#include <moveit_msgs/msg/motion_plan_request.hpp>
33#include <moveit_msgs/msg/robot_trajectory.hpp>
34#include <moveit_msgs/srv/get_cartesian_path.hpp>
44namespace trajectory_cache
47using ::warehouse_ros::MessageCollection;
48using ::warehouse_ros::MessageWithMetadata;
49using ::warehouse_ros::Metadata;
50using ::warehouse_ros::Query;
52using ::moveit::core::MoveItErrorCode;
53using ::moveit::planning_interface::MoveGroupInterface;
55using ::moveit_msgs::msg::MotionPlanRequest;
56using ::moveit_msgs::msg::RobotTrajectory;
57using ::moveit_msgs::srv::GetCartesianPath;
59using ::moveit_ros::trajectory_cache::FeaturesInterface;
64const std::string EXECUTION_TIME =
"execution_time_s";
65const std::string FRACTION =
"fraction";
66const std::string PLANNING_TIME =
"planning_time_s";
76 : name_(
"BestSeenExecutionTimePolicy"), best_seen_execution_time_(std::numeric_limits<double>::infinity())
82std::vector<std::unique_ptr<FeaturesInterface<MotionPlanRequest>>>
85 std::vector<std::unique_ptr<FeaturesInterface<MotionPlanRequest>>> out;
89 out.push_back(std::make_unique<WorkspaceFeatures>());
90 out.push_back(std::make_unique<StartStateJointStateFeatures>(start_tolerance));
93 out.push_back(std::make_unique<MaxSpeedAndAccelerationFeatures>());
94 out.push_back(std::make_unique<GoalConstraintsFeatures>(goal_tolerance));
95 out.push_back(std::make_unique<PathConstraintsFeatures>(goal_tolerance));
96 out.push_back(std::make_unique<TrajectoryConstraintsFeatures>(goal_tolerance));
107 const MessageCollection<RobotTrajectory>& ,
108 const MotionPlanRequest& key,
109 const MoveGroupInterface::Plan& value)
114 if (workspace_frame_id.empty())
116 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
117 name_ +
": Skipping insert: Workspace frame ID cannot be empty.");
119 if (key.goal_constraints.empty())
121 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, name_ +
": Skipping insert: No goal.");
125 if (value.trajectory.joint_trajectory.points.empty())
127 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, name_ +
": Empty joint trajectory points.");
129 if (value.trajectory.joint_trajectory.joint_names.empty())
131 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
132 name_ +
": Skipping insert: Empty joint trajectory joint names.");
134 if (!value.trajectory.multi_dof_joint_trajectory.points.empty())
136 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
137 name_ +
": Skipping insert: Multi-DOF trajectory plans are not supported.");
139 if (value.trajectory.joint_trajectory.header.frame_id.empty())
141 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
142 name_ +
": Skipping insert: Trajectory frame ID cannot be empty.");
144 if (workspace_frame_id != value.trajectory.joint_trajectory.header.frame_id)
146 std::stringstream ss;
147 ss <<
"Skipping insert: Plan request frame (" << workspace_frame_id <<
") does not match plan frame ("
148 << value.trajectory.joint_trajectory.header.frame_id <<
").";
149 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, ss.str());
152 return MoveItErrorCode::SUCCESS;
156 const MoveGroupInterface&
move_group,
const MessageCollection<RobotTrajectory>& coll,
const MotionPlanRequest& key,
157 const MoveGroupInterface::Plan& ,
double exact_match_precision)
159 Query::Ptr query = coll.createQuery();
160 for (
const auto& feature : exact_matching_supported_features_)
162 if (MoveItErrorCode ret = feature->appendFeaturesAsExactFetchQuery(*query, key,
move_group, exact_match_precision);
169 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> out =
170 coll.queryList(query,
true, EXECUTION_TIME,
true);
173 best_seen_execution_time_ = out[0]->lookupDouble(EXECUTION_TIME);
180 const MoveGroupInterface& ,
const MotionPlanRequest& ,
const MoveGroupInterface::Plan& value,
181 const MessageWithMetadata<RobotTrajectory>::ConstPtr& matching_entry, std::string* reason)
183 double matching_entry_execution_time_s = matching_entry->lookupDouble(EXECUTION_TIME);
186 if (matching_entry_execution_time_s >= candidate_execution_time_s)
188 if (reason !=
nullptr)
190 std::stringstream ss;
191 ss <<
"Matching trajectory execution_time_s `" << matching_entry_execution_time_s <<
"s` "
192 <<
"is worse than candidate trajectory's execution_time_s `" << candidate_execution_time_s <<
"s`";
199 if (reason !=
nullptr)
201 std::stringstream ss;
202 ss <<
"Matching trajectory execution_time_s `" << matching_entry_execution_time_s <<
"s` "
203 <<
"is better than candidate trajectory's execution_time_s `" << candidate_execution_time_s <<
"s`";
211 const MotionPlanRequest& ,
const MoveGroupInterface::Plan& value,
216 if (execution_time_s < best_seen_execution_time_)
218 if (reason !=
nullptr)
220 std::stringstream ss;
221 ss <<
"New trajectory execution_time_s `" << execution_time_s <<
"s` "
222 <<
"is better than best trajectory's execution_time_s `" << best_seen_execution_time_ <<
"s`";
229 if (reason !=
nullptr)
231 std::stringstream ss;
232 ss <<
"New trajectory execution_time `" << execution_time_s <<
"s` "
233 <<
"is worse than best trajectory's execution_time `" << best_seen_execution_time_ <<
"s`";
242 const MotionPlanRequest& key,
243 const MoveGroupInterface::Plan& value)
245 for (
const auto& feature : exact_matching_supported_features_)
247 if (MoveItErrorCode ret = feature->appendFeaturesAsInsertMetadata(metadata, key,
move_group); !ret)
255 metadata.append(PLANNING_TIME, value.planning_time);
257 return MoveItErrorCode::SUCCESS;
262 best_seen_execution_time_ = std::numeric_limits<double>::infinity();
272 : name_(
"CartesianBestSeenExecutionTimePolicy"), best_seen_execution_time_(std::numeric_limits<double>::infinity())
274 exact_matching_supported_features_ =
279std::vector<std::unique_ptr<FeaturesInterface<GetCartesianPath::Request>>>
283 std::vector<std::unique_ptr<FeaturesInterface<GetCartesianPath::Request>>> out;
287 out.push_back(std::make_unique<CartesianWorkspaceFeatures>());
288 out.push_back(std::make_unique<CartesianStartStateJointStateFeatures>(start_tolerance));
291 out.push_back(std::make_unique<CartesianMaxSpeedAndAccelerationFeatures>());
292 out.push_back(std::make_unique<CartesianMaxStepAndJumpThresholdFeatures>());
293 out.push_back(std::make_unique<CartesianWaypointsFeatures>(goal_tolerance));
294 out.push_back(std::make_unique<CartesianPathConstraintsFeatures>(goal_tolerance));
308 const MoveGroupInterface&
move_group,
const MessageCollection<RobotTrajectory>& ,
309 const GetCartesianPath::Request& key,
const GetCartesianPath::Response& value)
314 if (frame_id.empty())
316 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
317 name_ +
": Skipping insert: Workspace frame ID cannot be empty.");
319 if (key.waypoints.empty())
321 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, name_ +
": Skipping insert: No waypoints.");
325 if (value.solution.joint_trajectory.points.empty())
327 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, name_ +
": Empty joint trajectory points.");
329 if (value.solution.joint_trajectory.joint_names.empty())
331 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
332 name_ +
": Skipping insert: Empty joint trajectory joint names.");
334 if (!value.solution.multi_dof_joint_trajectory.points.empty())
336 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
337 name_ +
": Skipping insert: Multi-DOF trajectory plans are not supported.");
339 if (value.solution.joint_trajectory.header.frame_id.empty())
341 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN,
342 name_ +
": Skipping insert: Trajectory frame ID cannot be empty.");
344 if (frame_id != value.solution.joint_trajectory.header.frame_id)
346 std::stringstream ss;
347 ss <<
"Skipping insert: Plan request frame `" << frame_id <<
"` does not match plan frame `"
348 << value.solution.joint_trajectory.header.frame_id <<
"`.";
349 return MoveItErrorCode(MoveItErrorCode::INVALID_MOTION_PLAN, ss.str());
352 return MoveItErrorCode::SUCCESS;
356 const MoveGroupInterface&
move_group,
const MessageCollection<RobotTrajectory>& coll,
357 const GetCartesianPath::Request& key,
const GetCartesianPath::Response& ,
double exact_match_precision)
359 Query::Ptr query = coll.createQuery();
360 for (
const auto& feature : exact_matching_supported_features_)
362 if (MoveItErrorCode ret = feature->appendFeaturesAsExactFetchQuery(*query, key,
move_group, exact_match_precision);
369 std::vector<MessageWithMetadata<RobotTrajectory>::ConstPtr> out =
370 coll.queryList(query,
true, EXECUTION_TIME,
true);
373 best_seen_execution_time_ = out[0]->lookupDouble(EXECUTION_TIME);
380 const MoveGroupInterface& ,
const GetCartesianPath::Request& ,
381 const GetCartesianPath::Response& value,
const MessageWithMetadata<RobotTrajectory>::ConstPtr& matching_entry,
384 double matching_entry_execution_time_s = matching_entry->lookupDouble(EXECUTION_TIME);
387 if (matching_entry_execution_time_s >= candidate_execution_time_s)
389 if (reason !=
nullptr)
391 std::stringstream ss;
392 ss <<
"Matching trajectory execution_time_s `" << matching_entry_execution_time_s <<
"s` "
393 <<
"is worse than candidate trajectory's execution_time_s `" << candidate_execution_time_s <<
"s`";
400 if (reason !=
nullptr)
402 std::stringstream ss;
403 ss <<
"Matching trajectory execution_time_s `" << matching_entry_execution_time_s <<
"s` "
404 <<
"is better than candidate trajectory's execution_time_s `" << candidate_execution_time_s <<
"s`";
412 const GetCartesianPath::Request& ,
413 const GetCartesianPath::Response& value, std::string* reason)
417 if (execution_time_s < best_seen_execution_time_)
419 if (reason !=
nullptr)
421 std::stringstream ss;
422 ss <<
"New cartesian trajectory execution_time_s `" << execution_time_s <<
"s` "
423 <<
"is better than best cartesian trajectory's execution_time_s `" << best_seen_execution_time_ <<
"s`";
430 if (reason !=
nullptr)
432 std::stringstream ss;
433 ss <<
"New cartesian trajectory execution_time `" << execution_time_s <<
"s` "
434 <<
"is worse than best cartesian trajectory's execution_time `" << best_seen_execution_time_ <<
"s`";
443 const GetCartesianPath::Request& key,
444 const GetCartesianPath::Response& value)
446 for (
const auto& feature : exact_matching_supported_features_)
448 if (MoveItErrorCode ret = feature->appendFeaturesAsInsertMetadata(metadata, key,
move_group); !ret)
456 metadata.append(FRACTION, value.fraction);
458 return MoveItErrorCode::SUCCESS;
463 best_seen_execution_time_ = std::numeric_limits<double>::infinity();
A cache insertion policy that only decides to insert if the motion plan is the one with the shortest ...
std::string getName() const override
Gets the name of the cache insert policy.
moveit::core::MoveItErrorCode appendInsertMetadata(warehouse_ros::Metadata &metadata, const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::msg::MotionPlanRequest &key, const moveit::planning_interface::MoveGroupInterface::Plan &value) override
Appends the insert metadata with the features supported by the policy.
moveit::core::MoveItErrorCode checkCacheInsertInputs(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< moveit_msgs::msg::RobotTrajectory > &coll, const moveit_msgs::msg::MotionPlanRequest &key, const moveit::planning_interface::MoveGroupInterface::Plan &value) override
Checks inputs to the cache insert call to see if we should abort instead.
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.
BestSeenExecutionTimePolicy()
void reset() override
Resets the state of the policy.
bool shouldInsert(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::msg::MotionPlanRequest &key, const moveit::planning_interface::MoveGroupInterface::Plan &value, std::string *reason=nullptr) override
Returns whether the insertion candidate should be inserted into the cache.
std::vector< warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr > fetchMatchingEntries(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< moveit_msgs::msg::RobotTrajectory > &coll, const moveit_msgs::msg::MotionPlanRequest &key, const moveit::planning_interface::MoveGroupInterface::Plan &value, double exact_match_precision) override
Fetches all "matching" cache entries for comparison for pruning.
bool shouldPruneMatchingEntry(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::msg::MotionPlanRequest &key, const moveit::planning_interface::MoveGroupInterface::Plan &value, const warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr &matching_entry, std::string *reason=nullptr) override
moveit::core::MoveItErrorCode appendInsertMetadata(warehouse_ros::Metadata &metadata, const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::srv::GetCartesianPath::Request &key, const moveit_msgs::srv::GetCartesianPath::Response &value) override
Appends the insert metadata with the features supported by the policy.
void reset() override
Resets the state of the policy.
CartesianBestSeenExecutionTimePolicy()
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.
moveit::core::MoveItErrorCode checkCacheInsertInputs(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< moveit_msgs::msg::RobotTrajectory > &coll, const moveit_msgs::srv::GetCartesianPath::Request &key, const moveit_msgs::srv::GetCartesianPath::Response &value) override
Checks inputs to the cache insert call to see if we should abort instead.
std::vector< warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr > fetchMatchingEntries(const moveit::planning_interface::MoveGroupInterface &move_group, const warehouse_ros::MessageCollection< moveit_msgs::msg::RobotTrajectory > &coll, const moveit_msgs::srv::GetCartesianPath::Request &key, const moveit_msgs::srv::GetCartesianPath::Response &value, double exact_match_precision) override
Fetches all "matching" cache entries for comparison for pruning.
std::string getName() const override
Gets the name of the cache insert policy.
bool shouldInsert(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::srv::GetCartesianPath::Request &key, const moveit_msgs::srv::GetCartesianPath::Response &value, std::string *reason=nullptr) override
Returns whether the insertion candidate should be inserted into the cache.
bool shouldPruneMatchingEntry(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::srv::GetCartesianPath::Request &key, const moveit_msgs::srv::GetCartesianPath::Response &value, const warehouse_ros::MessageWithMetadata< moveit_msgs::msg::RobotTrajectory >::ConstPtr &matching_entry, std::string *reason=nullptr) override
User-specified constant features to key the trajectory cache on.
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.
std::string getWorkspaceFrameId(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::msg::WorkspaceParameters &workspace_parameters)
Gets workspace frame ID. If workspace_parameters has no frame ID, fetch it from move_group.
double getExecutionTime(const moveit_msgs::msg::RobotTrajectory &trajectory)
Returns the execution time of the trajectory in double seconds.
std::string getCartesianPathRequestFrameId(const moveit::planning_interface::MoveGroupInterface &move_group, const moveit_msgs::srv::GetCartesianPath::Request &path_request)
Gets cartesian path request frame ID. If path_request has no frame ID, fetch it from move_group.