@@ -283,34 +283,64 @@ bool plan_execution::PlanExecution::isRemainingPathValid(const ExecutableMotionP
283283 collision_detection::CollisionRequest req;
284284 req.group_name = t.getGroupName ();
285285 req.pad_environment_collisions = false ;
286+ moveit::core::RobotState state = plan.planning_scene ->getCurrentState ();
287+ std::map<std::string, const moveit::core::AttachedBody*> current_attached_objects, waypoint_attached_objects;
288+ state.getAttachedBodies (current_attached_objects);
289+ waypoint_attached_objects = plan_components_attached_objects_[path_segment.first ];
286290 for (std::size_t i = std::max (path_segment.second - 1 , 0 ); i < wpc; ++i)
287291 {
288292 collision_detection::CollisionResult res;
293+ state = t.getWayPoint (i);
294+ if (plan_components_attached_objects_[path_segment.first ].empty ())
295+ {
296+ state.getAttachedBodies (waypoint_attached_objects);
297+ }
298+
299+ // If sample state has attached objects that are not in the current state, remove them from the sample state
300+ for (const auto & [name, object] : waypoint_attached_objects)
301+ {
302+ if (current_attached_objects.find (name) == current_attached_objects.end ())
303+ {
304+ RCLCPP_DEBUG (logger_, " Attached object '%s' is not in the current scene. Removing it." , name.c_str ());
305+ state.clearAttachedBody (name);
306+ }
307+ }
308+
309+ // If current state has attached objects that are not in the sample state, add them to the sample state
310+ for (const auto & [name, object] : current_attached_objects)
311+ {
312+ if (waypoint_attached_objects.find (name) == waypoint_attached_objects.end ())
313+ {
314+ RCLCPP_DEBUG (logger_, " Attached object '%s' is not in the robot state. Adding it." , name.c_str ());
315+ state.attachBody (std::make_unique<moveit::core::AttachedBody>(*object));
316+ }
317+ }
318+
289319 if (acm)
290320 {
291- plan.planning_scene ->checkCollision (req, res, t. getWayPoint (i) , *acm);
321+ plan.planning_scene ->checkCollision (req, res, state , *acm);
292322 }
293323 else
294324 {
295- plan.planning_scene ->checkCollision (req, res, t. getWayPoint (i) );
325+ plan.planning_scene ->checkCollision (req, res, state );
296326 }
297327
298- if (res.collision || !plan.planning_scene ->isStateFeasible (t. getWayPoint (i) , false ))
328+ if (res.collision || !plan.planning_scene ->isStateFeasible (state , false ))
299329 {
300330 RCLCPP_INFO (logger_, " Trajectory component '%s' is invalid for waypoint %ld out of %ld" ,
301331 plan.plan_components [path_segment.first ].description .c_str (), i, wpc);
302332
303333 // call the same functions again, in verbose mode, to show what issues have been detected
304- plan.planning_scene ->isStateFeasible (t. getWayPoint (i) , true );
334+ plan.planning_scene ->isStateFeasible (state , true );
305335 req.verbose = true ;
306336 res.clear ();
307337 if (acm)
308338 {
309- plan.planning_scene ->checkCollision (req, res, t. getWayPoint (i) , *acm);
339+ plan.planning_scene ->checkCollision (req, res, state , *acm);
310340 }
311341 else
312342 {
313- plan.planning_scene ->checkCollision (req, res, t. getWayPoint (i) );
343+ plan.planning_scene ->checkCollision (req, res, state );
314344 }
315345 return false ;
316346 }
@@ -430,6 +460,32 @@ moveit_msgs::msg::MoveItErrorCodes plan_execution::PlanExecution::executeAndMoni
430460 path_became_invalid_ = false ;
431461 bool preempt_requested = false ;
432462
463+ // Check that attached objects remain consistent throughout the trajectory and store them.
464+ // This avoids querying the scene for attached objects at each waypoint whenever possible.
465+ // If a change in attached objects is detected, they will be queried at each waypoint.
466+ plan_components_attached_objects_.clear ();
467+ plan_components_attached_objects_.reserve (plan.plan_components .size ());
468+ for (const auto & component : plan.plan_components )
469+ {
470+ const auto & trajectory = component.trajectory ;
471+ std::map<std::string, const moveit::core::AttachedBody*> trajectory_attached_objects;
472+ if (trajectory)
473+ {
474+ std::map<std::string, const moveit::core::AttachedBody*> attached_objects;
475+ trajectory->getWayPoint (0 ).getAttachedBodies (trajectory_attached_objects);
476+ for (std::size_t i = 1 ; i < trajectory->getWayPointCount (); ++i)
477+ {
478+ trajectory->getWayPoint (i).getAttachedBodies (attached_objects);
479+ if (attached_objects != trajectory_attached_objects)
480+ {
481+ trajectory_attached_objects.clear ();
482+ break ;
483+ }
484+ }
485+ }
486+ plan_components_attached_objects_.push_back (trajectory_attached_objects);
487+ }
488+
433489 while (rclcpp::ok () && !execution_complete_ && !path_became_invalid_)
434490 {
435491 r.sleep ();
0 commit comments