Skip to content

Commit 7da4b68

Browse files
iche033mderbaso-deepx
authored andcommitted
dartsim: Add support for category bitmask (gazebosim#885)
Signed-off-by: Ian Chen <ichen@openrobotics.org> Signed-off-by: Ian Chen <iche@intrinsic.ai> Co-authored-by: Ian Chen <iche@intrinsic.ai> Signed-off-by: Ian Chen <iche@intrinsic.ai> (cherry picked from commit e608ccf)
1 parent 79dc32e commit 7da4b68

3 files changed

Lines changed: 84 additions & 7 deletions

File tree

dartsim/src/EntityManagementFeatures.cc

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class BitmaskContactFilter : public dart::collision::BodyNodeCollisionFilter
4444
public: using DartShapeConstPtr = const dart::dynamics::ShapeNode*;
4545

4646
private: std::unordered_map<DartShapeConstPtr, uint16_t> bitmaskMap;
47+
private: std::unordered_map<DartShapeConstPtr, uint16_t> categoryBitmaskMap;
4748

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

5960
auto shape1Iter = bitmaskMap.find(shapeNode1);
6061
auto shape2Iter = bitmaskMap.find(shapeNode2);
61-
if (shape1Iter != bitmaskMap.end() && shape2Iter != bitmaskMap.end() &&
62-
((shape1Iter->second & shape2Iter->second) == 0))
63-
return true;
62+
if (shape1Iter != bitmaskMap.end() && shape2Iter != bitmaskMap.end())
63+
{
64+
// For backward compatibility, if category bitmask is not set, it
65+
// defaults to the same value as collide bitmask.
66+
auto category1Iter = categoryBitmaskMap.find(shapeNode1);
67+
auto category2Iter = categoryBitmaskMap.find(shapeNode2);
68+
uint16_t categoryMask1 = (category1Iter != categoryBitmaskMap.end()) ?
69+
category1Iter->second : shape1Iter->second;
70+
uint16_t categoryMask2 = (category2Iter != categoryBitmaskMap.end()) ?
71+
category2Iter->second : shape2Iter->second;
72+
73+
return !((categoryMask1 & shape2Iter->second) |
74+
(categoryMask2 & shape1Iter->second));
75+
}
6476

6577
return false;
6678
}
@@ -85,12 +97,35 @@ class BitmaskContactFilter : public dart::collision::BodyNodeCollisionFilter
8597
bitmaskMap.erase(shapeIter);
8698
}
8799

100+
public: void SetIgnoredCategory(DartShapeConstPtr _shapePtr, uint16_t _mask)
101+
{
102+
categoryBitmaskMap[_shapePtr] = _mask;
103+
}
104+
105+
public: uint16_t GetIgnoredCategory(DartShapeConstPtr _shapePtr) const
106+
{
107+
auto shapeIter = categoryBitmaskMap.find(_shapePtr);
108+
if (shapeIter != categoryBitmaskMap.end())
109+
return shapeIter->second;
110+
// For backward compatibility, if category bitmask is not set, it
111+
// defaults to the same value as collide bitmask.
112+
return GetIgnoredCollision(_shapePtr);
113+
}
114+
115+
public: void RemoveIgnoredCategory(DartShapeConstPtr _shapePtr)
116+
{
117+
auto shapeIter = categoryBitmaskMap.find(_shapePtr);
118+
if (shapeIter != categoryBitmaskMap.end())
119+
categoryBitmaskMap.erase(shapeIter);
120+
}
121+
88122
public: void RemoveSkeletonCollisions(dart::dynamics::SkeletonPtr _skelPtr)
89123
{
90124
for (std::size_t i = 0; i < _skelPtr->getNumShapeNodes(); ++i)
91125
{
92126
auto shapePtr = _skelPtr->getShapeNode(i);
93127
this->RemoveIgnoredCollision(shapePtr);
128+
this->RemoveIgnoredCategory(shapePtr);
94129
}
95130
}
96131

@@ -850,6 +885,33 @@ void EntityManagementFeatures::RemoveCollisionFilterMask(
850885
filterPtr->RemoveIgnoredCollision(shapeNode);
851886
}
852887

888+
void EntityManagementFeatures::SetCategoryFilterMask(
889+
const Identity &_shapeID, uint16_t _mask)
890+
{
891+
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
892+
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
893+
const auto filterPtr = GetFilterPtr(this, worldID);
894+
filterPtr->SetIgnoredCategory(shapeNode, _mask);
895+
}
896+
897+
uint16_t EntityManagementFeatures::GetCategoryFilterMask(
898+
const Identity &_shapeID) const
899+
{
900+
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
901+
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
902+
const auto filterPtr = GetFilterPtr(this, worldID);
903+
return filterPtr->GetIgnoredCategory(shapeNode);
904+
}
905+
906+
void EntityManagementFeatures::RemoveCategoryFilterMask(
907+
const Identity &_shapeID)
908+
{
909+
const auto shapeNode = this->ReferenceInterface<ShapeInfo>(_shapeID)->node;
910+
const std::size_t worldID = GetWorldOfShapeNode(this, shapeNode);
911+
const auto filterPtr = GetFilterPtr(this, worldID);
912+
filterPtr->RemoveIgnoredCategory(shapeNode);
913+
}
914+
853915
Identity EntityManagementFeatures::GetWorldModel(const Identity &_worldID) const
854916
{
855917
auto modelID = this->modelProxiesToWorld.MaybeAt(_worldID);

dartsim/src/EntityManagementFeatures.hh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace dartsim {
3737
struct EntityManagementFeatureList : FeatureList<
3838
GetEntities,
3939
RemoveEntities,
40+
CategoryFilterMaskFeature,
4041
ConstructEmptyWorldFeature,
4142
ConstructEmptyModelFeature,
4243
ConstructEmptyNestedModelFeature,
@@ -178,6 +179,15 @@ class GZ_PHYSICS_DARTSIM_PLUGIN_VISIBLE EntityManagementFeatures :
178179

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

182+
// ----- Manage category filter masks -----
183+
public: void SetCategoryFilterMask(
184+
const Identity &_shapeID, uint16_t _mask) override;
185+
186+
public: uint16_t GetCategoryFilterMask(
187+
const Identity &_shapeID) const override;
188+
189+
public: void RemoveCategoryFilterMask(const Identity &_shapeID) override;
190+
181191
// ----- World model feature -----
182192
public: Identity GetWorldModel(const Identity &_worldID) const override;
183193
};

dartsim/src/SDFFeatures.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <cmath>
2121
#include <limits>
2222
#include <memory>
23+
#include <optional>
2324
#include <string>
2425
#include <utility>
2526

@@ -885,6 +886,7 @@ Identity SDFFeatures::ConstructSdfCollision(
885886
// TODO(addisu) We are using the coefficient specified in the <ode> tag.
886887
// Either add parameters specific to DART or generic to all physics engines.
887888
uint16_t collideBitmask = 0xFF;
889+
std::optional<uint16_t> categoryBitmask;
888890
if (_collision.Element())
889891
{
890892
const auto &odeFriction = _collision.Element()
@@ -958,12 +960,13 @@ Identity SDFFeatures::ConstructSdfCollision(
958960
surfaceBounce->Get<double>("restitution_coefficient"));
959961
}
960962
#endif
961-
// TODO(anyone) add category_bitmask as well
962-
const auto bitmaskElement = _collision.Element()
963+
const auto contactElement = _collision.Element()
963964
->GetElement("surface")
964965
->GetElement("contact");
965-
if (bitmaskElement->HasElement("collide_bitmask"))
966-
collideBitmask = bitmaskElement->Get<int>("collide_bitmask");
966+
if (contactElement->HasElement("collide_bitmask"))
967+
collideBitmask = contactElement->Get<int>("collide_bitmask");
968+
if (contactElement->HasElement("category_bitmask"))
969+
categoryBitmask = contactElement->Get<int>("category_bitmask");
967970
}
968971

969972
node->setRelativeTransform(ResolveSdfPose(_collision.SemanticPose()) *
@@ -974,6 +977,8 @@ Identity SDFFeatures::ConstructSdfCollision(
974977
auto identity = this->GenerateIdentity(shapeID, this->shapes.at(shapeID));
975978

976979
this->SetCollisionFilterMask(identity, collideBitmask);
980+
if (categoryBitmask.has_value())
981+
this->SetCategoryFilterMask(identity, categoryBitmask.value());
977982
return identity;
978983
}
979984

0 commit comments

Comments
 (0)