Skip to content

Commit 8d74d35

Browse files
sjahrrhaschke
authored andcommitted
Add planner name to trajectory info (moveit#490)
* Add planner name to trajectory info * Extend unittest
1 parent 8eb93dc commit 8d74d35

File tree

14 files changed

+106
-36
lines changed

14 files changed

+106
-36
lines changed

core/include/moveit/task_constructor/solvers/cartesian_path.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class CartesianPath : public PlannerInterface
7171
const Eigen::Isometry3d& offset, const Eigen::Isometry3d& target, const moveit::core::JointModelGroup* jmg,
7272
double timeout, robot_trajectory::RobotTrajectoryPtr& result,
7373
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
74+
75+
std::string getPlannerId() const override { return std::string("CartesianPath"); }
7476
};
7577
} // namespace solvers
7678
} // namespace task_constructor

core/include/moveit/task_constructor/solvers/joint_interpolation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class JointInterpolationPlanner : public PlannerInterface
6666
const Eigen::Isometry3d& offset, const Eigen::Isometry3d& target, const moveit::core::JointModelGroup* jmg,
6767
double timeout, robot_trajectory::RobotTrajectoryPtr& result,
6868
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
69+
70+
std::string getPlannerId() const override { return std::string("JointInterpolationPlanner"); }
6971
};
7072
} // namespace solvers
7173
} // namespace task_constructor

core/include/moveit/task_constructor/solvers/pipeline_planner.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ class PipelinePlanner : public PlannerInterface
137137
robot_trajectory::RobotTrajectoryPtr& result,
138138
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
139139

140+
/**
141+
* \brief Get planner name
142+
* \return Name of the last successful planner
143+
*/
144+
std::string getPlannerId() const override;
145+
140146
protected:
141147
/** \brief Actual plan() implementation, targeting the given goal_constraints.
142148
* \param [in] planning_scene Scene for which the planning should be solved
@@ -155,6 +161,8 @@ class PipelinePlanner : public PlannerInterface
155161

156162
rclcpp::Node::SharedPtr node_;
157163

164+
std::string last_successful_planner_;
165+
158166
/** \brief Map of instantiated (and named) planning pipelines. */
159167
std::unordered_map<std::string, planning_pipeline::PlanningPipelinePtr> planning_pipelines_;
160168

core/include/moveit/task_constructor/solvers/planner_interface.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ class PlannerInterface
9999
const moveit::core::JointModelGroup* jmg, double timeout,
100100
robot_trajectory::RobotTrajectoryPtr& result,
101101
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) = 0;
102+
103+
// get name of the planner
104+
virtual std::string getPlannerId() const = 0;
102105
};
103106
} // namespace solvers
104107
} // namespace task_constructor

core/include/moveit/task_constructor/stages/connect.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,13 @@ class Connect : public Connecting
7373
WAYPOINTS = 1
7474
};
7575

76-
using GroupPlannerVector = std::vector<std::pair<std::string, solvers::PlannerInterfacePtr> >;
76+
struct PlannerIdTrajectoryPair
77+
{
78+
std::string planner_name;
79+
robot_trajectory::RobotTrajectoryConstPtr robot_trajectory_ptr;
80+
};
81+
82+
using GroupPlannerVector = std::vector<std::pair<std::string, solvers::PlannerInterfacePtr>>;
7783
Connect(const std::string& name = "connect", const GroupPlannerVector& planners = {});
7884

7985
void setPathConstraints(moveit_msgs::msg::Constraints path_constraints) {
@@ -85,10 +91,10 @@ class Connect : public Connecting
8591
void compute(const InterfaceState& from, const InterfaceState& to) override;
8692

8793
protected:
88-
SolutionSequencePtr makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
94+
SolutionSequencePtr makeSequential(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
8995
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
9096
const InterfaceState& from, const InterfaceState& to);
91-
SubTrajectoryPtr merge(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
97+
SubTrajectoryPtr merge(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
9298
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
9399
const moveit::core::RobotState& state);
94100

core/include/moveit/task_constructor/storage.h

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@ class SolutionBase
275275
public:
276276
virtual ~SolutionBase() = default;
277277

278-
inline const InterfaceState* start() const { return start_; }
279-
inline const InterfaceState* end() const { return end_; }
278+
[[nodiscard]] inline const InterfaceState* start() const { return start_; }
279+
[[nodiscard]] inline const InterfaceState* end() const { return end_; }
280280

281281
/** Set the solution's start_state_
282282
*
@@ -298,18 +298,21 @@ class SolutionBase
298298
const_cast<InterfaceState&>(state).addIncoming(this);
299299
}
300300

301-
inline const Stage* creator() const { return creator_; }
301+
[[nodiscard]] inline const Stage* creator() const { return creator_; }
302302
void setCreator(Stage* creator);
303303

304-
inline double cost() const { return cost_; }
304+
[[nodiscard]] inline double cost() const { return cost_; }
305305
void setCost(double cost);
306306
void markAsFailure(const std::string& msg = std::string());
307-
inline bool isFailure() const { return !std::isfinite(cost_); }
307+
[[nodiscard]] inline bool isFailure() const { return !std::isfinite(cost_); }
308308

309-
const std::string& comment() const { return comment_; }
309+
[[nodiscard]] const std::string& plannerId() const { return planner_id_; }
310+
void setPlannerId(const std::string& planner_id) { planner_id_ = planner_id; }
311+
312+
[[nodiscard]] const std::string& comment() const { return comment_; }
310313
void setComment(const std::string& comment) { comment_ = comment; }
311314

312-
auto& markers() { return markers_; }
315+
[[nodiscard]] auto& markers() { return markers_; }
313316
const auto& markers() const { return markers_; }
314317

315318
/// convert solution to message
@@ -326,14 +329,17 @@ class SolutionBase
326329
bool operator<(const SolutionBase& other) const { return this->cost_ < other.cost_; }
327330

328331
protected:
329-
SolutionBase(Stage* creator = nullptr, double cost = 0.0, std::string comment = "")
330-
: creator_(creator), cost_(cost), comment_(std::move(comment)) {}
332+
SolutionBase(Stage* creator = nullptr, double cost = 0.0, std::string comment = std::string(""),
333+
std::string planner_id = std::string(""))
334+
: creator_(creator), cost_(cost), planner_id_(std::move(planner_id)), comment_(std::move(comment)) {}
331335

332336
private:
333337
// back-pointer to creating stage, allows to access sub-solutions
334338
Stage* creator_;
335339
// associated cost
336340
double cost_;
341+
// name of the planner used to create this solution
342+
std::string planner_id_;
337343
// comment for this solution, e.g. explanation of failure
338344
std::string comment_;
339345
// markers for this solution, e.g. target frame or collision indicators
@@ -351,8 +357,8 @@ class SubTrajectory : public SolutionBase
351357
public:
352358
SubTrajectory(
353359
const robot_trajectory::RobotTrajectoryConstPtr& trajectory = robot_trajectory::RobotTrajectoryConstPtr(),
354-
double cost = 0.0, std::string comment = "")
355-
: SolutionBase(nullptr, cost, std::move(comment)), trajectory_(trajectory) {}
360+
double cost = 0.0, std::string comment = std::string(""), std::string planner_id = std::string(""))
361+
: SolutionBase(nullptr, cost, std::move(comment), std::move(planner_id)), trajectory_(trajectory) {}
356362

357363
robot_trajectory::RobotTrajectoryConstPtr trajectory() const { return trajectory_; }
358364
void setTrajectory(const robot_trajectory::RobotTrajectoryPtr& t) { trajectory_ = t; }

core/src/solvers/pipeline_planner.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ PipelinePlanner::PipelinePlanner(
6060
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback,
6161
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function)
6262
: node_(node)
63+
, last_successful_planner_("")
6364
, stopping_criterion_callback_(stopping_criterion_callback)
6465
, solution_selection_function_(solution_selection_function) {
6566
// Declare properties of the MotionPlanRequest
@@ -147,6 +148,8 @@ bool PipelinePlanner::plan(const planning_scene::PlanningSceneConstPtr& from, co
147148
const moveit::core::JointModelGroup* joint_model_group, double timeout,
148149
robot_trajectory::RobotTrajectoryPtr& result,
149150
const moveit_msgs::msg::Constraints& path_constraints) {
151+
last_successful_planner_.clear();
152+
150153
// Construct a Cartesian target pose from the given target transform and offset
151154
geometry_msgs::msg::PoseStamped target;
152155
target.header.frame_id = from->getPlanningFrame();
@@ -205,11 +208,15 @@ bool PipelinePlanner::plan(const planning_scene::PlanningSceneConstPtr& planning
205208
if (solution) {
206209
// Choose the first solution trajectory as response
207210
result = solution.trajectory;
211+
last_successful_planner_ = solution.planner_id;
208212
return bool(result);
209213
}
210214
}
211215
return false;
212216
}
217+
std::string PipelinePlanner::getPlannerId() const {
218+
return last_successful_planner_.empty() ? std::string("Unknown") : last_successful_planner_;
219+
}
213220
} // namespace solvers
214221
} // namespace task_constructor
215222
} // namespace moveit

core/src/stages/connect.cpp

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void Connect::compute(const InterfaceState& from, const InterfaceState& to) {
141141
const auto& path_constraints = props.get<moveit_msgs::msg::Constraints>("path_constraints");
142142

143143
const moveit::core::RobotState& final_goal_state = to.scene()->getCurrentState();
144-
std::vector<robot_trajectory::RobotTrajectoryConstPtr> sub_trajectories;
144+
std::vector<PlannerIdTrajectoryPair> trajectory_planner_vector;
145145

146146
std::vector<planning_scene::PlanningSceneConstPtr> intermediate_scenes;
147147
planning_scene::PlanningSceneConstPtr start = from.scene();
@@ -161,7 +161,7 @@ void Connect::compute(const InterfaceState& from, const InterfaceState& to) {
161161

162162
robot_trajectory::RobotTrajectoryPtr trajectory;
163163
success = pair.second->plan(start, end, jmg, timeout, trajectory, path_constraints);
164-
sub_trajectories.push_back(trajectory); // include failed trajectory
164+
trajectory_planner_vector.push_back(PlannerIdTrajectoryPair({ pair.second->getPlannerId(), trajectory }));
165165

166166
if (!success)
167167
break;
@@ -172,39 +172,41 @@ void Connect::compute(const InterfaceState& from, const InterfaceState& to) {
172172

173173
SolutionBasePtr solution;
174174
if (success && mode != SEQUENTIAL) // try to merge
175-
solution = merge(sub_trajectories, intermediate_scenes, from.scene()->getCurrentState());
175+
solution = merge(trajectory_planner_vector, intermediate_scenes, from.scene()->getCurrentState());
176176
if (!solution) // success == false or merging failed: store sequentially
177-
solution = makeSequential(sub_trajectories, intermediate_scenes, from, to);
177+
solution = makeSequential(trajectory_planner_vector, intermediate_scenes, from, to);
178178
if (!success) // error during sequential planning
179179
solution->markAsFailure();
180+
180181
connect(from, to, solution);
181182
}
182183

183184
SolutionSequencePtr
184-
Connect::makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
185+
Connect::makeSequential(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
185186
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
186187
const InterfaceState& from, const InterfaceState& to) {
187-
assert(!sub_trajectories.empty());
188-
assert(sub_trajectories.size() + 1 == intermediate_scenes.size());
188+
assert(!trajectory_planner_vector.empty());
189+
assert(trajectory_planner_vector.size() + 1 == intermediate_scenes.size());
189190

190191
/* We need to decouple the sequence of subsolutions, created here, from the external from and to states.
191192
Hence, we create new interface states for all subsolutions. */
192193
const InterfaceState* start = &*states_.insert(states_.end(), InterfaceState(from.scene()));
193194

194195
auto scene_it = intermediate_scenes.begin();
195196
SolutionSequence::container_type sub_solutions;
196-
for (const auto& sub : sub_trajectories) {
197+
for (const auto& pair : trajectory_planner_vector) {
197198
// persistently store sub solution
198-
auto inserted = subsolutions_.insert(subsolutions_.end(), SubTrajectory(sub));
199+
auto inserted = subsolutions_.insert(
200+
subsolutions_.end(), SubTrajectory(pair.robot_trajectory_ptr, 0.0, std::string(""), pair.planner_name));
199201
inserted->setCreator(this);
200-
if (!sub) // a null RobotTrajectoryPtr indicates a failure
202+
if (!pair.robot_trajectory_ptr) // a null RobotTrajectoryPtr indicates a failure
201203
inserted->markAsFailure();
202204
// push back solution pointer
203205
sub_solutions.push_back(&*inserted);
204206

205207
// create a new end state, either from intermediate or final planning scene
206208
planning_scene::PlanningSceneConstPtr end_ps =
207-
(sub_solutions.size() < sub_trajectories.size()) ? *++scene_it : to.scene();
209+
(sub_solutions.size() < trajectory_planner_vector.size()) ? *++scene_it : to.scene();
208210
const InterfaceState* end = &*states_.insert(states_.end(), InterfaceState(end_ps));
209211

210212
// provide newly created start/end states
@@ -217,26 +219,50 @@ Connect::makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConst
217219
return std::make_shared<SolutionSequence>(std::move(sub_solutions));
218220
}
219221

220-
SubTrajectoryPtr Connect::merge(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
222+
SubTrajectoryPtr Connect::merge(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
221223
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
222224
const moveit::core::RobotState& state) {
223225
// no need to merge if there is only a single sub trajectory
224-
if (sub_trajectories.size() == 1)
225-
return std::make_shared<SubTrajectory>(sub_trajectories[0]);
226+
if (trajectory_planner_vector.size() == 1)
227+
return std::make_shared<SubTrajectory>(trajectory_planner_vector.at(0).robot_trajectory_ptr, 0.0, std::string(""),
228+
trajectory_planner_vector.at(0).planner_name);
226229

227230
auto jmg = merged_jmg_.get();
228231
assert(jmg);
229232
auto timing = properties().get<TimeParameterizationPtr>("merge_time_parameterization");
230-
robot_trajectory::RobotTrajectoryPtr trajectory = task_constructor::merge(sub_trajectories, state, jmg, *timing);
231-
if (!trajectory)
233+
robot_trajectory::RobotTrajectoryPtr merged_trajectory = task_constructor::merge(
234+
[&]() {
235+
// Move trajectories into single vector
236+
std::vector<robot_trajectory::RobotTrajectoryConstPtr> robot_traj_vector;
237+
robot_traj_vector.reserve(trajectory_planner_vector.size());
238+
239+
// Copy second elements of robot planner vector into separate vector
240+
std::transform(begin(trajectory_planner_vector), end(trajectory_planner_vector),
241+
std::back_inserter(robot_traj_vector),
242+
[](auto const& pair) { return pair.robot_trajectory_ptr; });
243+
return robot_traj_vector;
244+
}(),
245+
state, jmg, *timing);
246+
247+
// check merged trajectory is empty or has collisions
248+
if (!merged_trajectory ||
249+
!intermediate_scenes.front()->isPathValid(*merged_trajectory,
250+
properties().get<moveit_msgs::msg::Constraints>("path_constraints"))) {
232251
return SubTrajectoryPtr();
252+
}
233253

234-
// check merged trajectory for collisions
235-
if (!intermediate_scenes.front()->isPathValid(*trajectory,
236-
properties().get<moveit_msgs::msg::Constraints>("path_constraints")))
237-
return SubTrajectoryPtr();
254+
// Copy first elements of robot planner vector into separate vector
255+
std::vector<std::string> planner_names;
256+
planner_names.reserve(trajectory_planner_vector.size());
257+
std::transform(begin(trajectory_planner_vector), end(trajectory_planner_vector), std::back_inserter(planner_names),
258+
[](auto const& pair) { return pair.planner_name; });
238259

239-
return std::make_shared<SubTrajectory>(trajectory);
260+
// Create a sequence of planner names
261+
std::string planner_name_sequence;
262+
for (auto const& name : planner_names) {
263+
planner_name_sequence += std::string(", " + name);
264+
}
265+
return std::make_shared<SubTrajectory>(merged_trajectory, 0.0, std::string(""), planner_name_sequence);
240266
}
241267
} // namespace stages
242268
} // namespace task_constructor

core/src/stages/move_relative.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
199199
if (getJointStateFromOffset(direction, dir, jmg, scene->getCurrentStateNonConst())) {
200200
// plan to joint-space target
201201
success = planner_->plan(state.scene(), scene, jmg, timeout, robot_trajectory, path_constraints);
202+
solution.setPlannerId(planner_->getPlannerId());
202203
} else {
203204
// Cartesian targets require an IK reference frame
204205
const moveit::core::LinkModel* link;
@@ -287,6 +288,7 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
287288

288289
success =
289290
planner_->plan(state.scene(), *link, offset, target_eigen, jmg, timeout, robot_trajectory, path_constraints);
291+
solution.setPlannerId(planner_->getPlannerId());
290292

291293
if (robot_trajectory) { // the following requires a robot_trajectory returned from planning
292294
moveit::core::RobotStatePtr& reached_state = robot_trajectory->getLastWayPointPtr();

core/src/stages/move_to.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ bool MoveTo::compute(const InterfaceState& state, planning_scene::PlanningSceneP
209209
if (getJointStateGoal(goal, jmg, scene->getCurrentStateNonConst())) {
210210
// plan to joint-space target
211211
success = planner_->plan(state.scene(), scene, jmg, timeout, robot_trajectory, path_constraints);
212+
solution.setPlannerId(planner_->getPlannerId());
212213
} else { // Cartesian goal
213214
// Where to go?
214215
Eigen::Isometry3d target;
@@ -241,6 +242,7 @@ bool MoveTo::compute(const InterfaceState& state, planning_scene::PlanningSceneP
241242

242243
// plan to Cartesian target
243244
success = planner_->plan(state.scene(), *link, offset, target, jmg, timeout, robot_trajectory, path_constraints);
245+
solution.setPlannerId(planner_->getPlannerId());
244246
}
245247

246248
// store result

0 commit comments

Comments
 (0)