Skip to content

Commit 788ca80

Browse files
authored
Add planner name to trajectory info (#5)
1 parent 5ea2140 commit 788ca80

File tree

13 files changed

+104
-40
lines changed

13 files changed

+104
-40
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
@@ -69,6 +69,8 @@ class CartesianPath : public PlannerInterface
6969
const Eigen::Isometry3d& offset, const Eigen::Isometry3d& target, const moveit::core::JointModelGroup* jmg,
7070
double timeout, robot_trajectory::RobotTrajectoryPtr& result,
7171
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
72+
73+
std::string getPlannerId() const override { return std::string("CartesianPath"); }
7274
};
7375
} // namespace solvers
7476
} // 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
@@ -148,6 +148,12 @@ class PipelinePlanner : public PlannerInterface
148148
robot_trajectory::RobotTrajectoryPtr& result,
149149
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) override;
150150

151+
/**
152+
* \brief Get planner name
153+
* \return Name of the last successful planner
154+
*/
155+
std::string getPlannerId() const override;
156+
151157
protected:
152158
/** \brief Function that actually uses the planning pipelines to solve the given planning problem. It is called by
153159
* the public plan function after the goal constraints are generated. This function uses a predefined number of
@@ -173,6 +179,8 @@ class PipelinePlanner : public PlannerInterface
173179

174180
rclcpp::Node::SharedPtr node_;
175181

182+
std::string last_successful_planner_;
183+
176184
/** \brief Map of pipeline names (ids) and their corresponding planner ids. The planning problem is solved for every
177185
* pipeline-planner pair in this map. If no pipelines are passed via constructor argument, the pipeline names are
178186
* used to initialize a set of planning pipelines. */

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ class PlannerInterface
9090
const moveit::core::JointModelGroup* jmg, double timeout,
9191
robot_trajectory::RobotTrajectoryPtr& result,
9292
const moveit_msgs::msg::Constraints& path_constraints = moveit_msgs::msg::Constraints()) = 0;
93+
94+
// get name of the planner
95+
virtual std::string getPlannerId() const = 0;
9396
};
9497
} // namespace solvers
9598
} // 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) {
@@ -89,10 +95,10 @@ class Connect : public Connecting
8995
void compute(const InterfaceState& from, const InterfaceState& to) override;
9096

9197
protected:
92-
SolutionSequencePtr makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
98+
SolutionSequencePtr makeSequential(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
9399
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
94100
const InterfaceState& from, const InterfaceState& to);
95-
SubTrajectoryPtr merge(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
101+
SubTrajectoryPtr merge(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
96102
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
97103
const moveit::core::RobotState& state);
98104

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
/// append this solution to Solution msg
@@ -324,14 +327,17 @@ class SolutionBase
324327
bool operator<(const SolutionBase& other) const { return this->cost_ < other.cost_; }
325328

326329
protected:
327-
SolutionBase(Stage* creator = nullptr, double cost = 0.0, std::string comment = "")
328-
: creator_(creator), cost_(cost), comment_(std::move(comment)) {}
330+
SolutionBase(Stage* creator = nullptr, double cost = 0.0, std::string comment = std::string(""),
331+
std::string planner_id = std::string(""))
332+
: creator_(creator), cost_(cost), planner_id_(std::move(planner_id)), comment_(std::move(comment)) {}
329333

330334
private:
331335
// back-pointer to creating stage, allows to access sub-solutions
332336
Stage* creator_;
333337
// associated cost
334338
double cost_;
339+
// name of the planner used to create this solution
340+
std::string planner_id_;
335341
// comment for this solution, e.g. explanation of failure
336342
std::string comment_;
337343
// markers for this solution, e.g. target frame or collision indicators
@@ -349,8 +355,8 @@ class SubTrajectory : public SolutionBase
349355
public:
350356
SubTrajectory(
351357
const robot_trajectory::RobotTrajectoryConstPtr& trajectory = robot_trajectory::RobotTrajectoryConstPtr(),
352-
double cost = 0.0, std::string comment = "")
353-
: SolutionBase(nullptr, cost, std::move(comment)), trajectory_(trajectory) {}
358+
double cost = 0.0, std::string comment = std::string(""), std::string planner_id = std::string(""))
359+
: SolutionBase(nullptr, cost, std::move(comment), std::move(planner_id)), trajectory_(trajectory) {}
354360

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

core/src/solvers/pipeline_planner.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@
4949
#include <tf2_eigen/tf2_eigen.h>
5050
#endif
5151

52-
namespace {
53-
const std::pair<std::string, std::string> DEFAULT_REQUESTED_PIPELINE =
54-
std::pair<std::string, std::string>("ompl", "RRTConnect");
55-
}
5652
namespace moveit {
5753
namespace task_constructor {
5854
namespace solvers {
@@ -71,6 +67,7 @@ PipelinePlanner::PipelinePlanner(
7167
const moveit::planning_pipeline_interfaces::StoppingCriterionFunction& stopping_criterion_callback,
7268
const moveit::planning_pipeline_interfaces::SolutionSelectionFunction& solution_selection_function)
7369
: node_(node)
70+
, last_successful_planner_("")
7471
, pipeline_id_planner_id_map_(pipeline_id_planner_id_map)
7572
, stopping_criterion_callback_(stopping_criterion_callback)
7673
, solution_selection_function_(solution_selection_function) {
@@ -156,6 +153,8 @@ bool PipelinePlanner::plan(const planning_scene::PlanningSceneConstPtr& from, co
156153
const moveit::core::JointModelGroup* joint_model_group, double timeout,
157154
robot_trajectory::RobotTrajectoryPtr& result,
158155
const moveit_msgs::msg::Constraints& path_constraints) {
156+
last_successful_planner_.clear();
157+
159158
// Construct a Cartesian target pose from the given target transform and offset
160159
geometry_msgs::msg::PoseStamped target;
161160
target.header.frame_id = from->getPlanningFrame();
@@ -215,11 +214,15 @@ bool PipelinePlanner::plan(const planning_scene::PlanningSceneConstPtr& planning
215214
if (solution) {
216215
// Choose the first solution trajectory as response
217216
result = solution.trajectory;
217+
last_successful_planner_ = solution.planner_id;
218218
return bool(result);
219219
}
220220
}
221221
return false;
222222
}
223+
std::string PipelinePlanner::getPlannerId() const {
224+
return last_successful_planner_.empty() ? std::string("Unknown") : last_successful_planner_;
225+
}
223226
} // namespace solvers
224227
} // namespace task_constructor
225228
} // namespace moveit

core/src/stages/connect.cpp

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

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

150150
std::vector<planning_scene::PlanningSceneConstPtr> intermediate_scenes;
151151
planning_scene::PlanningSceneConstPtr start = from.scene();
@@ -166,7 +166,7 @@ void Connect::compute(const InterfaceState& from, const InterfaceState& to) {
166166

167167
robot_trajectory::RobotTrajectoryPtr trajectory;
168168
success = pair.second->plan(start, end, jmg, timeout, trajectory, path_constraints);
169-
sub_trajectories.push_back(trajectory);
169+
trajectory_planner_vector.push_back(PlannerIdTrajectoryPair({ pair.second->getPlannerId(), trajectory }));
170170

171171
// Check if the end goal and the last waypoint are close. The trajectory should be marked as failure otherwise.
172172
if (success) {
@@ -189,39 +189,41 @@ void Connect::compute(const InterfaceState& from, const InterfaceState& to) {
189189

190190
SolutionBasePtr solution;
191191
if (success && mode != SEQUENTIAL) // try to merge
192-
solution = merge(sub_trajectories, intermediate_scenes, from.scene()->getCurrentState());
192+
solution = merge(trajectory_planner_vector, intermediate_scenes, from.scene()->getCurrentState());
193193
if (!solution) // success == false or merging failed: store sequentially
194-
solution = makeSequential(sub_trajectories, intermediate_scenes, from, to);
194+
solution = makeSequential(trajectory_planner_vector, intermediate_scenes, from, to);
195195
if (!success) // error during sequential planning
196196
solution->markAsFailure();
197+
197198
connect(from, to, solution);
198199
}
199200

200201
SolutionSequencePtr
201-
Connect::makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
202+
Connect::makeSequential(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
202203
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
203204
const InterfaceState& from, const InterfaceState& to) {
204-
assert(!sub_trajectories.empty());
205-
assert(sub_trajectories.size() + 1 == intermediate_scenes.size());
205+
assert(!trajectory_planner_vector.empty());
206+
assert(trajectory_planner_vector.size() + 1 == intermediate_scenes.size());
206207

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

211212
auto scene_it = intermediate_scenes.begin();
212213
SolutionSequence::container_type sub_solutions;
213-
for (const auto& sub : sub_trajectories) {
214+
for (const auto& pair : trajectory_planner_vector) {
214215
// persistently store sub solution
215-
auto inserted = subsolutions_.insert(subsolutions_.end(), SubTrajectory(sub));
216+
auto inserted = subsolutions_.insert(
217+
subsolutions_.end(), SubTrajectory(pair.robot_trajectory_ptr, 0.0, std::string(""), pair.planner_name));
216218
inserted->setCreator(this);
217-
if (!sub) // a null RobotTrajectoryPtr indicates a failure
219+
if (!pair.robot_trajectory_ptr) // a null RobotTrajectoryPtr indicates a failure
218220
inserted->markAsFailure();
219221
// push back solution pointer
220222
sub_solutions.push_back(&*inserted);
221223

222224
// create a new end state, either from intermediate or final planning scene
223225
planning_scene::PlanningSceneConstPtr end_ps =
224-
(sub_solutions.size() < sub_trajectories.size()) ? *++scene_it : to.scene();
226+
(sub_solutions.size() < trajectory_planner_vector.size()) ? *++scene_it : to.scene();
225227
const InterfaceState* end = &*states_.insert(states_.end(), InterfaceState(end_ps));
226228

227229
// provide newly created start/end states
@@ -234,26 +236,50 @@ Connect::makeSequential(const std::vector<robot_trajectory::RobotTrajectoryConst
234236
return std::make_shared<SolutionSequence>(std::move(sub_solutions));
235237
}
236238

237-
SubTrajectoryPtr Connect::merge(const std::vector<robot_trajectory::RobotTrajectoryConstPtr>& sub_trajectories,
239+
SubTrajectoryPtr Connect::merge(const std::vector<PlannerIdTrajectoryPair>& trajectory_planner_vector,
238240
const std::vector<planning_scene::PlanningSceneConstPtr>& intermediate_scenes,
239241
const moveit::core::RobotState& state) {
240242
// no need to merge if there is only a single sub trajectory
241-
if (sub_trajectories.size() == 1)
242-
return std::make_shared<SubTrajectory>(sub_trajectories[0]);
243+
if (trajectory_planner_vector.size() == 1)
244+
return std::make_shared<SubTrajectory>(trajectory_planner_vector.at(0).robot_trajectory_ptr, 0.0, std::string(""),
245+
trajectory_planner_vector.at(0).planner_name);
243246

244247
auto jmg = merged_jmg_.get();
245248
assert(jmg);
246249
auto timing = properties().get<TimeParameterizationPtr>("merge_time_parameterization");
247-
robot_trajectory::RobotTrajectoryPtr trajectory = task_constructor::merge(sub_trajectories, state, jmg, *timing);
248-
if (!trajectory)
250+
robot_trajectory::RobotTrajectoryPtr merged_trajectory = task_constructor::merge(
251+
[&]() {
252+
// Move trajectories into single vector
253+
std::vector<robot_trajectory::RobotTrajectoryConstPtr> robot_traj_vector;
254+
robot_traj_vector.reserve(trajectory_planner_vector.size());
255+
256+
// Copy second elements of robot planner vector into separate vector
257+
std::transform(begin(trajectory_planner_vector), end(trajectory_planner_vector),
258+
std::back_inserter(robot_traj_vector),
259+
[](auto const& pair) { return pair.robot_trajectory_ptr; });
260+
return robot_traj_vector;
261+
}(),
262+
state, jmg, *timing);
263+
264+
// check merged trajectory is empty or has collisions
265+
if (!merged_trajectory ||
266+
!intermediate_scenes.front()->isPathValid(*merged_trajectory,
267+
properties().get<moveit_msgs::msg::Constraints>("path_constraints"))) {
249268
return SubTrajectoryPtr();
269+
}
250270

251-
// check merged trajectory for collisions
252-
if (!intermediate_scenes.front()->isPathValid(*trajectory,
253-
properties().get<moveit_msgs::msg::Constraints>("path_constraints")))
254-
return SubTrajectoryPtr();
271+
// Copy first elements of robot planner vector into separate vector
272+
std::vector<std::string> planner_names;
273+
planner_names.reserve(trajectory_planner_vector.size());
274+
std::transform(begin(trajectory_planner_vector), end(trajectory_planner_vector), std::back_inserter(planner_names),
275+
[](auto const& pair) { return pair.planner_name; });
255276

256-
return std::make_shared<SubTrajectory>(trajectory);
277+
// Create a sequence of planner names
278+
std::string planner_name_sequence;
279+
for (auto const& name : planner_names) {
280+
planner_name_sequence += std::string(", " + name);
281+
}
282+
return std::make_shared<SubTrajectory>(merged_trajectory, 0.0, std::string(""), planner_name_sequence);
257283
}
258284
} // namespace stages
259285
} // namespace task_constructor

core/src/stages/move_relative.cpp

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

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

290292
moveit::core::RobotStatePtr& reached_state = robot_trajectory->getLastWayPointPtr();
291293
reached_state->updateLinkTransforms();

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)