Skip to content

Commit 63e7bfa

Browse files
fix: ensure attached objects update during motion execution (#3327) (#3414)
(cherry picked from commit 89acadd) Co-authored-by: Marco Magri <94347649+MarcoMagriDev@users.noreply.github.com>
1 parent db4944f commit 63e7bfa

4 files changed

Lines changed: 73 additions & 6 deletions

File tree

moveit_core/robot_state/include/moveit/robot_state/robot_state.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,9 @@ class RobotState
15191519
/** \brief Get all bodies attached to the model corresponding to this state */
15201520
void getAttachedBodies(std::vector<const AttachedBody*>& attached_bodies) const;
15211521

1522+
/** \brief Get all bodies attached to the model corresponding to this state */
1523+
void getAttachedBodies(std::map<std::string, const AttachedBody*>& attached_bodies) const;
1524+
15221525
/** \brief Get all bodies attached to a particular group the model corresponding to this state */
15231526
void getAttachedBodies(std::vector<const AttachedBody*>& attached_bodies, const JointModelGroup* group) const;
15241527

moveit_core/robot_state/src/robot_state.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,13 @@ void RobotState::getAttachedBodies(std::vector<const AttachedBody*>& attached_bo
12201220
attached_bodies.push_back(it.second.get());
12211221
}
12221222

1223+
void RobotState::getAttachedBodies(std::map<std::string, const AttachedBody*>& attached_bodies) const
1224+
{
1225+
attached_bodies.clear();
1226+
for (const auto& it : attached_body_map_)
1227+
attached_bodies[it.first] = it.second.get();
1228+
}
1229+
12231230
void RobotState::getAttachedBodies(std::vector<const AttachedBody*>& attached_bodies, const JointModelGroup* group) const
12241231
{
12251232
attached_bodies.clear();

moveit_ros/planning/plan_execution/include/moveit/plan_execution/plan_execution.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class PlanExecution
156156
planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor_;
157157
trajectory_execution_manager::TrajectoryExecutionManagerPtr trajectory_execution_manager_;
158158
planning_scene_monitor::TrajectoryMonitorPtr trajectory_monitor_;
159+
std::vector<std::map<std::string, const moveit::core::AttachedBody*>> plan_components_attached_objects_;
159160

160161
unsigned int default_max_replan_attempts_;
161162

moveit_ros/planning/plan_execution/src/plan_execution.cpp

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)