@@ -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
200201SolutionSequencePtr
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
0 commit comments