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