5 #include <boost/lexical_cast.hpp>
8 #include <moveit/version.h>
29 class toMetricStringVisitor :
public boost::static_visitor<std::string>
44 double v = boost::get<double>(value);
47 return boost::lexical_cast<std::string>(
53 return boost::lexical_cast<std::string>(boost::get<bool>(value));
58 return boost::get<std::string>(value);
65 return boost::apply_visitor(toMetricStringVisitor(), metric);
76 : name(name),
scene(
scene), planner(planner), request(request)
90 auto xit = point.find(xprop);
91 if (xit == point.end())
94 const auto &xval = xit->second;
95 double xvald = boost::lexical_cast<double>(xval);
97 const auto &yit = point.find(yprop);
98 if (yit == point.end())
101 const auto &yval = yit->second;
102 double yvald = boost::lexical_cast<double>(yval);
117 auto it =
data.find(query_name);
118 if (it ==
data.end())
121 it->second.emplace_back(run);
127 for (
const auto &query :
data)
128 r.
insert(r.
end(), query.second.begin(), query.second.end());
143 bool complete =
false;
155 const auto &pp = planner->getProgressProperties(
scene, request);
156 prog_props.
insert(pp.begin(), pp.end());
160 prog_props.
emplace(allocator.first, allocator.second(planner,
scene, request));
169 const bool have_prog = not prog_props.
empty();
171 and (have_prog or not prog_call.
empty()))
176 for (
const auto &property : prog_props)
189 if (not at_least_once and complete)
201 for (
const auto &property : prog_props)
202 data[
property.first] =
property.second();
207 for (
const auto &
callback : prog_call)
210 at_least_once =
false;
240 progress_thread->join();
267 if (options & Metrics::WAYPOINTS)
270 if (options & Metrics::LENGTH)
273 if (options & Metrics::CORRECT)
276 if (options & Metrics::CLEARANCE)
279 if (options & Metrics::SMOOTHNESS)
309 double allowed_time,
std::size_t trials,
bool timeout)
310 : name_(name), allowed_time_(allowed_time), trials_(trials), timeout_(timeout), options_(options)
319 queries_.emplace_back(planner_name,
scene, planner, request);
386 auto dataset = std::make_shared<PlanDataSet>();
387 dataset->name =
name_;
392 dataset->run_till_timeout =
timeout_;
393 dataset->threads = n_threads;
398 ThreadInfo() =
default;
400 : query(query), trial(trial), index(index)
417 const auto &it =
std::find(dataset->query_names.begin(), dataset->query_names.end(), query.name);
418 if (it == dataset->query_names.end())
419 dataset->query_names.emplace_back(query.name);
430 threads.
emplace_back(std::make_shared<std::thread>([&]() {
431 std::size_t id = IO::getThreadID();
437 std::unique_lock<std::mutex> lock(mutex);
445 RBX_INFO(
"[Thread %1%] Running Query %3% `%2%` Trial [%4%/%5%]",
446 id, info.query->name, info.index, info.trial + 1, trials_);
449 double time_remaining =
450 (override_planning_time_) ? allowed_time_ : info.query->request.allowed_planning_time;
452 std::size_t timeout_trial = 0;
453 while (time_remaining > 0.)
455 planning_interface::MotionPlanRequest request = info.query->request;
456 request.allowed_planning_time = time_remaining;
458 if (enforce_single_thread_)
459 request.num_planning_attempts = 1;
462 info.query->planner->preRun(info.query->scene, request);
465 pre_callback_(*info.query);
468 auto data = std::make_shared<PlanData>();
469 profiler_.profilePlan(info.query->planner,
476 data->metrics.emplace(
"query_trial", (int)info.trial);
477 data->metrics.emplace(
"query_index", (int)info.index);
478 data->metrics.emplace(
"query_timeout_trial", (int)timeout_trial);
479 data->metrics.emplace(
"query_start_time", IO::getSeconds(dataset->start, data->start));
480 data->metrics.emplace(
"query_finish_time", IO::getSeconds(dataset->start, data->finish));
482 data->query.name = log::format(
"%1%:%2%:%3%", info.query->name, info.trial, info.index);
485 data->query.name = data->query.name + log::format(
":%4%", timeout_trial);
488 post_callback_(*data, *info.query);
491 std::unique_lock<std::mutex> lock(mutex);
493 dataset->addDataPoint(info.query->name, data);
496 if (complete_callback_)
497 complete_callback_(dataset, *info.query);
502 time_remaining -= data->time;
504 "[Thread %1%] Running Query %3% `%2%` till timeout, %4% seconds remaining...",
505 id, info.query->name, info.index, time_remaining);
512 RBX_INFO(
"[Thread %1%] Completed Query %3% `%2%` Trial [%4%/%5%] Total: [%6%/%7%]",
513 id, info.query->name, info.index,
514 info.trial + 1, trials_,
515 completed_queries, total_queries);
519 for (
const auto &thread : threads)
532 JSONPlanDataSetOutputter::JSONPlanDataSetOutputter(
const std::string &file) : file_(file)
559 for (
size_t i = 0; i < data.size(); i++)
561 const auto &run = data[i];
564 outfile_ <<
"\"name\": \"run_" << run->query.name <<
"\",";
565 outfile_ <<
"\"time\":" << run->time <<
",";
566 outfile_ <<
"\"success\":" << run->success;
568 for (
const auto &metric : run->metrics)
574 if (i != data.size() - 1)
586 : file_(file), bag_(file_)
595 if (data->trajectory)
616 out <<
"MoveIt! version " << MOVEIT_VERSION <<
std::endl;
625 out <<
"0 is the random seed" <<
std::endl;
637 out << results.
time <<
" seconds spent to collect the data" <<
std::endl;
648 const auto &runs = results.
data.find(name)->second;
651 out <<
"0 common properties" <<
std::endl;
653 out << (runs[0]->metrics.size() + 2) <<
" properties for each run" <<
std::endl;
658 for (
const auto &metric : runs[0]->metrics)
660 class ToString :
public boost::static_visitor<const std::string>
685 return "VARCHAR(128)";
689 const auto &name = metric.first;
692 out << name <<
" " << boost::apply_visitor(ToString(), metric.second) <<
std::endl;
695 out << runs.size() <<
" runs" <<
std::endl;
697 for (
const auto &run : runs)
699 out << run->time <<
"; "
700 << run->success <<
"; ";
702 for (
const auto &key : keys)
708 const auto &progress_names = runs[0]->property_names;
709 if (not progress_names.empty())
711 out << progress_names.size() <<
" progress properties for each run" <<
std::endl;
712 for (
const auto &name : progress_names)
715 out << runs.size() <<
" runs" <<
std::endl;
716 for (
const auto &run : runs)
718 for (
const auto &point : run->progress)
720 for (
const auto &name : progress_names)
722 auto it = point.find(name);
723 out << it->second <<
",";
void setPostRunCallback(const PostRunCallback &callback)
Set the post-query callback function.
std::vector< PlanningQuery > queries_
Queries to test.
Profiler::Options & getOptions()
Get the options used by the underlying profiler.
void setPostQueryCallback(const PostQueryCallback &callback)
Set the post-dataset callback function.
const std::vector< PlanningQuery > & getQueries() const
Get the queries added to this experiment.
PreRunCallback pre_callback_
Pre-run callback.
std::size_t trials_
Number of trials to run each query for.
bool enforce_single_thread_
Profiler profiler_
Profiler to use for extracting data.
Profiler::Options options_
Options for profiler.
PostRunCallback post_callback_
Post-run callback.
PlanDataSetPtr benchmark(std::size_t n_threads=1) const
Run benchmarking on this experiment. Note that, for some planners, multiple threads cannot be used wi...
double allowed_time_
Allotted time to use for each query.
void addQuery(const std::string &planner_name, const SceneConstPtr &scene, const PlannerPtr &planner, const planning_interface::MotionPlanRequest &request)
Add a query to the experiment for profiling.
void overridePlanningTime()
If called, instead of using global allotted planning time (provided in the constructor),...
void setPreRunCallback(const PreRunCallback &callback)
Set the pre-query callback function.
const Profiler & getProfilerConst() const
Get a reference to the profiler used by the experiment.
const std::string name_
Name of this experiment.
Experiment(const std::string &name, const Profiler::Options &options, double allowed_time=60.0, std::size_t trials=100, bool timeout=false)
Constructor.
Profiler & getProfiler()
Get a reference to the profiler used by the experiment. Add callback functions to this profiler for c...
PostQueryCallback complete_callback_
Post-run callback with dataset.
void enableMultipleRequests()
If called, will enable planners to use multiple threads. By default, planners are requested to only u...
bool override_planning_time_
bool addMessage(const std::string &topic, const T &msg)
Adds a message to the bag under topic.
bool is_init_
Have we initialized the outputter (on first result)?
~JSONPlanDataSetOutputter() override
Destructor. Closes outfile_.
const std::string file_
Filename to open.
std::ofstream outfile_
Output stream.
void dump(const PlanDataSet &results) override
Dumps results into outfile_, and opens outfile_ if not already done so.
A shared pointer wrapper for robowflex::MotionRequestBuilder.
A helper class to build motion planning requests for a robowflex::Planner.
const planning_interface::MotionPlanRequest & getRequestConst() const
Get a const reference to the currently built motion planning request.
const std::string prefix_
Log file prefix.
OMPLPlanDataSetOutputter(const std::string &prefix)
Constructor.
~OMPLPlanDataSetOutputter() override
Destructor, runs ompl_benchmark_statistics.py to generate benchmarking database.
void dump(const PlanDataSet &results) override
Dumps results into a OMPL benchmarking log file in prefix_ named after the request name_.
A shared pointer wrapper for robowflex::PlanData.
A shared pointer wrapper for robowflex::PlanDataSet.
Detailed statistics about a benchmark of multiple queries.
std::map< std::string, std::vector< PlanDataPtr > > data
Map of query name to collected data.
boost::posix_time::ptime start
Start time of dataset computation.
void addDataPoint(const std::string &query_name, const PlanDataPtr &run)
Add a computed plan data under a query as a data point.
std::vector< PlanDataPtr > getFlatData() const
Get the full data set as a flat vector.
std::vector< std::string > query_names
All unique names used by planning queries.
double allowed_time
Allowed planning time used per query.
std::string name
Name of this dataset.
double time
Total computation time for entire dataset.
Detailed statistics and metrics computed from profiling a planner's motion planning.
std::vector< std::pair< double, double > > getProgressPropertiesAsPoints(const std::string &xprop, const std::string &yprop) const
Retrieves the time series data of a planner progress property for a given X-,Y- pair of progress prop...
std::size_t process_id
Process ID of the process the profiler was run in.
boost::posix_time::ptime finish
Query end time.
std::vector< std::string > property_names
Planner progress value names.
planning_interface::MotionPlanResponse response
Planner response.
bool success
Was the plan successful?
PlanningQuery query
Query evaluated to create this data.
TrajectoryPtr trajectory
The resulting trajectory, if available.
std::map< std::string, PlannerMetric > metrics
Map of metric name to value.
std::vector< std::map< std::string, std::string > > progress
Planner progress data.
std::size_t thread_id
Thread ID of profiler execution.
boost::posix_time::ptime start
Query start time.
double time
Time that planning took in seconds.
std::string hostname
Hostname of the machine the plan was run on.
A shared pointer wrapper for robowflex::Planner.
void addProgressCallbackAllocator(const ProgressCallbackAllocator &allocator)
Add a function that is called in the planner progress property loop.
std::map< std::string, ProgressPropertyAllocator > prog_allocators_
User progress properties.
void computeBuiltinMetrics(uint32_t options, const SceneConstPtr &scene, PlanData &run) const
Compute the built-in metrics according to the provided bitmask options.
void addProgressCallback(const ProgressCallback &callback)
Add a function that is called in the planner progress property loop.
std::map< std::string, ComputeMetricCallback > callbacks_
User callback metrics.
std::vector< ProgressCallbackAllocator > prog_callback_allocators_
void addMetricCallback(const std::string &name, const ComputeMetricCallback &metric)
Add a callback function to compute a metric at the end of planning.
void computeCallbackMetrics(const PlannerPtr &planner, const SceneConstPtr &scene, const planning_interface::MotionPlanRequest &request, PlanData &run) const
Compute the custom user callback metrics.
void addProgressAllocator(const std::string &name, const ProgressPropertyAllocator &allocator)
Add a function that allocates a function that returns a planner progress property function.
bool profilePlan(const PlannerPtr &planner, const SceneConstPtr &scene, const planning_interface::MotionPlanRequest &request, const Options &options, PlanData &result) const
Profiling a single plan using a planner.
std::vector< ProgressCallback > prog_callbacks_
User progress callback functions.
A const shared pointer wrapper for robowflex::Scene.
TrajectoryPlanDataSetOutputter(const std::string &file)
Constructor.
void dump(const PlanDataSet &results) override
Dumps all trajectories in results to rosbag file file_. The topic the trajectories are saved under is...
IO::Bag bag_
Rosbag handler.
T emplace_back(T... args)
#define ROBOWFLEX_DEMANGLE(x)
moveit_msgs::MotionPlanRequest MotionPlanRequest
double getSeconds(boost::posix_time::ptime start, boost::posix_time::ptime finish)
Get a duration in seconds from two times.
boost::posix_time::ptime getDate()
Get the current time (up to milliseconds)
std::size_t getProcessID()
Get the process ID of this process.
std::string getHostname()
Get the hostname of the system.
std::size_t getThreadID()
Get the thread ID of the current thread.
void createFile(std::ofstream &out, const std::string &file)
Creates a file and opens an output stream. Creates directories if they do not exist.
void threadSleep(double seconds)
Put the current thread to sleep for a desired amount of seconds.
std::string format(const std::string &fmt, Args &&... args)
Recursion base case, return string form of formatted arguments.
Main namespace. Contains all library classes and functions.
std::string toMetricString(const PlannerMetric &metric)
Convert a planner metric into a string.
boost::variant< bool, double, int, std::size_t, std::string > PlannerMetric
Variant type of possible values a run metric could be.
Functions for loading and animating scenes in Blender.
moveit_msgs::MoveItErrorCodes error_code_
robot_trajectory::RobotTrajectoryPtr trajectory_
A container structure for all elements needed in a planning query, plus an identifying name.
planning_interface::MotionPlanRequest request
Request used for the query.
PlanningQuery()=default
Empty constructor.
SceneConstPtr scene
Scene used for the query.
PlannerPtr planner
Planner used for the query.
bool progress
If true, captures planner progress properties (if they exist).
bool progress_at_least_once
If true, will always run the progress loop at least once.
double progress_update_rate
Update rate for progress callbacks.
uint32_t metrics
Bitmask of which metrics to compute after planning.
void callback(movegroup::MoveGroupHelper::Action &action)