Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
68 changes: 65 additions & 3 deletions dartsim/src/EntityManagementFeatures.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class BitmaskContactFilter : public dart::collision::BodyNodeCollisionFilter
public: using DartShapeConstPtr = const dart::dynamics::ShapeNode*;

private: std::unordered_map<DartShapeConstPtr, uint16_t> bitmaskMap;
private: std::unordered_map<DartShapeConstPtr, uint16_t> categoryBitmaskMap;

public: bool ignoresCollision(
DartCollisionConstPtr _object1,
Expand All @@ -58,9 +59,20 @@ class BitmaskContactFilter : public dart::collision::BodyNodeCollisionFilter

auto shape1Iter = bitmaskMap.find(shapeNode1);
auto shape2Iter = bitmaskMap.find(shapeNode2);
if (shape1Iter != bitmaskMap.end() && shape2Iter != bitmaskMap.end() &&
((shape1Iter->second & shape2Iter->second) == 0))
return true;
if (shape1Iter != bitmaskMap.end() && shape2Iter != bitmaskMap.end())
{
// For backward compatibility, if category bitmask is not set, it
// defaults to the same value as collide bitmask.
auto category1Iter = categoryBitmaskMap.find(shapeNode1);
auto category2Iter = categoryBitmaskMap.find(shapeNode2);
uint16_t categoryMask1 = (category1Iter != categoryBitmaskMap.end()) ?
category1Iter->second : shape1Iter->second;
uint16_t categoryMask2 = (category2Iter != categoryBitmaskMap.end()) ?
category2Iter->second : shape2Iter->second;

return !((categoryMask1 & shape2Iter->second) |
(categoryMask2 & shape1Iter->second));
}

return false;
}
Expand All @@ -85,12 +97,35 @@ class BitmaskContactFilter : public dart::collision::BodyNodeCollisionFilter
bitmaskMap.erase(shapeIter);
}

public: void SetIgnoredCategory(DartShapeConstPtr _shapePtr, uint16_t _mask)
{
categoryBitmaskMap[_shapePtr] = _mask;
}

public: uint16_t GetIgnoredCategory(DartShapeConstPtr _shapePtr) const
{
auto shapeIter = categoryBitmaskMap.find(_shapePtr);
if (shapeIter != categoryBitmaskMap.end())
return shapeIter->second;
// For backward compatibility, if category bitmask is not yet, it
// defaults to the same value as collide bitmask.
return GetIgnoredCollision(_shapePtr);
}

public: void RemoveIgnoredCategory(DartShapeConstPtr _shapePtr)
{
auto shapeIter = categoryBitmaskMap.find(_shapePtr);
if (shapeIter != categoryBitmaskMap.end())
categoryBitmaskMap.erase(shapeIter);
Comment thread
iche033 marked this conversation as resolved.
}

public: void RemoveSkeletonCollisions(dart::dynamics::SkeletonPtr _skelPtr)
{
for (std::size_t i = 0; i < _skelPtr->getNumShapeNodes(); ++i)
{
auto shapePtr = _skelPtr->getShapeNode(i);
this->RemoveIgnoredCollision(shapePtr);
this->RemoveIgnoredCategory(shapePtr);
}
}

Expand Down Expand Up @@ -857,6 +892,33 @@ void EntityManagementFeatures::RemoveCollisionFilterMask(
filterPtr->RemoveIgnoredCollision(shapeNode);
}

void EntityManagementFeatures::SetCategoryFilterMask(
const Identity &_shapeID, uint16_t _mask)
{
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
const auto filterPtr = GetFilterPtr(this, worldID);
filterPtr->SetIgnoredCategory(shapeNode, _mask);
}

uint16_t EntityManagementFeatures::GetCategoryFilterMask(
const Identity &_shapeID) const
{
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
const auto filterPtr = GetFilterPtr(this, worldID);
return filterPtr->GetIgnoredCategory(shapeNode);
}

void EntityManagementFeatures::RemoveCategoryFilterMask(
const Identity &_shapeID)
{
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
const auto filterPtr = GetFilterPtr(this, worldID);
filterPtr->RemoveIgnoredCategory(shapeNode);
}

Identity EntityManagementFeatures::GetWorldModel(const Identity &_worldID) const
{
auto modelID = this->modelProxiesToWorld.MaybeAt(_worldID);
Expand Down
10 changes: 10 additions & 0 deletions dartsim/src/EntityManagementFeatures.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace dartsim {
struct EntityManagementFeatureList : FeatureList<
GetEntities,
RemoveEntities,
CategoryFilterMaskFeature,
ConstructEmptyWorldFeature,
ConstructEmptyModelFeature,
ConstructEmptyNestedModelFeature,
Expand Down Expand Up @@ -181,6 +182,15 @@ class GZ_PHYSICS_DARTSIM_PLUGIN_VISIBLE EntityManagementFeatures :

public: void RemoveCollisionFilterMask(const Identity &_shapeID) override;

// ----- Manage category filter masks -----
public: void SetCategoryFilterMask(
const Identity &_shapeID, uint16_t _mask) override;

public: uint16_t GetCategoryFilterMask(
const Identity &_shapeID) const override;

public: void RemoveCategoryFilterMask(const Identity &_shapeID) override;

// ----- World model feature -----
public: Identity GetWorldModel(const Identity &_worldID) const override;
};
Expand Down
13 changes: 9 additions & 4 deletions dartsim/src/SDFFeatures.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <cstddef>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>

Expand Down Expand Up @@ -916,6 +917,7 @@ Identity SDFFeatures::ConstructSdfCollision(
// TODO(addisu) We are using the coefficient specified in the <ode> tag.
// Either add parameters specific to DART or generic to all physics engines.
uint16_t collideBitmask = 0xFF;
std::optional<uint16_t> categoryBitmask;
if (_collision.Element())
{
const auto &odeFriction = _collision.Element()
Expand Down Expand Up @@ -989,12 +991,13 @@ Identity SDFFeatures::ConstructSdfCollision(
surfaceBounce->Get<double>("restitution_coefficient"));
}
#endif
// TODO(anyone) add category_bitmask as well
const auto bitmaskElement = _collision.Element()
const auto contactElement = _collision.Element()
->GetElement("surface")
->GetElement("contact");
if (bitmaskElement->HasElement("collide_bitmask"))
collideBitmask = bitmaskElement->Get<int>("collide_bitmask");
if (contactElement->HasElement("collide_bitmask"))
collideBitmask = contactElement->Get<int>("collide_bitmask");
if (contactElement->HasElement("category_bitmask"))
categoryBitmask = contactElement->Get<int>("category_bitmask");
}

node->setRelativeTransform(ResolveSdfPose(_collision.SemanticPose()) *
Expand All @@ -1005,6 +1008,8 @@ Identity SDFFeatures::ConstructSdfCollision(
auto identity = this->GenerateIdentity(shapeID, this->shapes.at(shapeID));

this->SetCollisionFilterMask(identity, collideBitmask);
if (categoryBitmask.has_value())
this->SetCategoryFilterMask(identity, categoryBitmask.value());
return identity;
}

Expand Down
Loading