Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix PlanningScene CollisionDetector diff handling #464

Merged
merged 3 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace collision_detection
{
bool CollisionDetectorBtPluginLoader::initialize(const planning_scene::PlanningScenePtr& scene, bool exclusive) const
{
scene->setActiveCollisionDetector(CollisionDetectorAllocatorBullet::create(), exclusive);
scene->allocateCollisionDetector(CollisionDetectorAllocatorBullet::create(), exclusive);
return true;
}
} // namespace collision_detection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace collision_detection
{
bool CollisionDetectorFCLPluginLoader::initialize(const planning_scene::PlanningScenePtr& scene) const
{
scene->setCollisionDetectorType(CollisionDetectorAllocatorFCL::create());
scene->allocateCollisionDetector(CollisionDetectorAllocatorFCL::create());
return true;
}
} // namespace collision_detection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from
/** \brief Clone a planning scene. Even if the scene \e scene depends on a parent, the cloned scene will not. */
static PlanningScenePtr clone(const PlanningSceneConstPtr& scene);

/** \brief Replace previous collision detector with a new collision detector type (or create new, if none previously).
/** \brief Allocate a new collision detector and replace the previous one if there was any.
*
* The collision detector type is specified with (a shared pointer to) an
* allocator which is a subclass of CollisionDetectorAllocator. This
Expand All @@ -922,10 +922,13 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from
* A new PlanningScene uses an FCL collision detector by default.
*
* example: to add FCL collision detection (normally not necessary) call
* planning_scene->setCollisionDetectorType(collision_detection::CollisionDetectorAllocatorFCL::create());
* planning_scene->allocateCollisionDetector(collision_detection::CollisionDetectorAllocatorFCL::create());
*
* */
void setCollisionDetectorType(const collision_detection::CollisionDetectorAllocatorPtr& allocator);
void allocateCollisionDetector(const collision_detection::CollisionDetectorAllocatorPtr& allocator)
{
allocateCollisionDetector(allocator, nullptr /* no parent_detector */);
}

private:
/* Private constructor used by the diff() methods. */
Expand All @@ -949,6 +952,10 @@ class PlanningScene : private boost::noncopyable, public std::enable_shared_from

MOVEIT_STRUCT_FORWARD(CollisionDetector)

/* Construct a new CollisionDector from allocator, copy-construct environments from parent_detector if not null */
void allocateCollisionDetector(const collision_detection::CollisionDetectorAllocatorPtr& allocator,
const CollisionDetectorPtr& parent_detector);
henningkayser marked this conversation as resolved.
Show resolved Hide resolved

/* \brief A set of compatible collision detectors */
struct CollisionDetector
{
Expand Down
58 changes: 28 additions & 30 deletions moveit_core/planning_scene/src/planning_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void PlanningScene::initialize()
for (const srdf::Model::DisabledCollision& it : dc)
acm_->setEntry(it.link1_, it.link2_, true);

setCollisionDetectorType(collision_detection::CollisionDetectorAllocatorFCL::create());
allocateCollisionDetector(collision_detection::CollisionDetectorAllocatorFCL::create());
}

/* return NULL on failure */
Expand Down Expand Up @@ -193,7 +193,7 @@ PlanningScene::PlanningScene(const PlanningSceneConstPtr& parent) : parent_(pare
// record changes to the world
world_diff_.reset(new collision_detection::WorldDiff(world_));

setCollisionDetectorType(parent_->collision_detector_->alloc_);
allocateCollisionDetector(parent_->collision_detector_->alloc_, parent_->collision_detector_);
collision_detector_->copyPadding(*parent_->collision_detector_);
}

Expand Down Expand Up @@ -223,36 +223,37 @@ void PlanningScene::CollisionDetector::copyPadding(const PlanningScene::Collisio
cenv_->setLinkScale(src.getCollisionEnv()->getLinkScale());
}

void PlanningScene::setCollisionDetectorType(const collision_detection::CollisionDetectorAllocatorPtr& allocator)
void PlanningScene::allocateCollisionDetector(const collision_detection::CollisionDetectorAllocatorPtr& allocator,
const CollisionDetectorPtr& parent_detector)
{
// Temporary copy of the previous (if any), to copy padding
CollisionDetector prev_coll_detector;
bool have_previous_coll_detector = false;
if (collision_detector_)
{
have_previous_coll_detector = true;
prev_coll_detector = *collision_detector_;
}

// TODO(andyz): uncomment this for a small speed boost when another collision detector type is available in MoveIt2
// For now, it is useful in the switchCollisionDetectorType() unit test
// const std::string& name = allocator->getName();
// if (name == getCollisionDetectorName()) // already using this collision detector
// return;
// Temporarily keep pointer to the previous (if any) collision detector to copy padding from
CollisionDetectorPtr prev_coll_detector = collision_detector_;
AndyZe marked this conversation as resolved.
Show resolved Hide resolved

// Construct a fresh CollisionDetector and store allocator
collision_detector_.reset(new CollisionDetector());

collision_detector_->alloc_ = allocator;
collision_detector_->cenv_ = collision_detector_->alloc_->allocateEnv(world_, getRobotModel());
collision_detector_->cenv_const_ = collision_detector_->cenv_;
collision_detector_->cenv_unpadded_ = collision_detector_->alloc_->allocateEnv(world_, getRobotModel());
collision_detector_->cenv_unpadded_const_ = collision_detector_->cenv_unpadded_;

// Copy padding from the previous collision detector
if (have_previous_coll_detector)
// If parent_detector is specified, copy-construct collision environments (copies link shapes and attached objects)
// Otherwise, construct new collision environment from world and robot model
if (parent_detector)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the key part of this fix. The collision environment of the parent is used to copy-construct the child environment so that attached objects are available as well.

{
collision_detector_->copyPadding(prev_coll_detector);
collision_detector_->cenv_ = collision_detector_->alloc_->allocateEnv(parent_detector->cenv_, world_);
collision_detector_->cenv_unpadded_ =
collision_detector_->alloc_->allocateEnv(parent_detector->cenv_unpadded_, world_);
}
else
{
collision_detector_->cenv_ = collision_detector_->alloc_->allocateEnv(world_, getRobotModel());
collision_detector_->cenv_unpadded_ = collision_detector_->alloc_->allocateEnv(world_, getRobotModel());

// Copy padding to collision_detector_->cenv_
if (prev_coll_detector)
collision_detector_->copyPadding(*prev_coll_detector);
}

// Assign const pointers
collision_detector_->cenv_const_ = collision_detector_->cenv_;
collision_detector_->cenv_unpadded_const_ = collision_detector_->cenv_unpadded_;
}

const collision_detection::CollisionEnvConstPtr&
Expand Down Expand Up @@ -295,11 +296,8 @@ void PlanningScene::clearDiffs()
if (current_world_object_update_callback_)
current_world_object_update_observer_handle_ = world_->addObserver(current_world_object_update_callback_);

if (parent_)
{
collision_detector_->copyPadding(*parent_->collision_detector_);
}
collision_detector_->cenv_const_ = collision_detector_->cenv_;
// Reset collision detector to the the parent's version
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearDiffs() now also just allocates a fresh collision detector from parent

allocateCollisionDetector(parent_->collision_detector_->alloc_, parent_->collision_detector_);

scene_transforms_.reset();
robot_state_.reset();
Expand Down
2 changes: 1 addition & 1 deletion moveit_core/planning_scene/test/test_planning_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ TEST(PlanningScene, switchCollisionDetectorType)
EXPECT_FALSE(ps->isStateValid(current_state, "left_arm"));
}

ps->setCollisionDetectorType(collision_detection::CollisionDetectorAllocatorFCL::create());
ps->allocateCollisionDetector(collision_detection::CollisionDetectorAllocatorFCL::create());
if (ps->isStateColliding(current_state, "left_arm"))
{
EXPECT_FALSE(ps->isStateValid(current_state, "left_arm"));
Expand Down