5 #include <Box2D/Box2D.h> 16 using namespace se2ez;
31 world.SetAllowSleeping(
false);
32 world.SetAutoClearForces(
true);
33 world.SetContinuousPhysics(
false);
34 world.SetSubStepping(
false);
57 contact->GetWorldManifold(&world);
58 return contact->GetManifold();
78 : movable(movable), name(name), index(index), geometry_(geometry)
82 bodyDef_.type = b2_dynamicBody;
84 bodyDef_.type = b2_staticBody;
86 bodyDef_.userData =
this;
88 body_ = world->world.CreateBody(&bodyDef_);
92 shapeDef_.resize(shapes_.size());
94 for (
unsigned int i = 0; i < shapes_.size(); ++i)
96 shapeDef_[i].shape = shapes_[i];
97 shapeDef_[i].density = 1;
99 fixture_.emplace_back(body_->CreateFixture(&shapeDef_[i]));
105 for (
unsigned int i = 0; i < shapes_.size(); ++i)
108 for (
unsigned int i = 0; i < points_.size(); ++i)
109 delete[] points_[i].first;
117 const auto &x = pose.translation()[0];
118 const auto &y = pose.translation()[1];
127 const auto &pos = body_->GetPosition();
128 const auto &rot = body_->GetAngle();
137 return body_->GetTransform();
155 auto *poly =
new b2PolygonShape;
157 unsigned int count = geometry->points.size();
158 b2Vec2 *verts =
new b2Vec2[count];
161 for (
unsigned int i = 0; i < count; ++i)
164 verts[i].Set(geometry->points[i](0), geometry->points[i](1));
167 poly->Set(verts, count);
168 points_.emplace_back(verts, count);
177 switch (geometry_->type)
181 auto *box =
new b2PolygonShape;
186 box->SetAsBox(geometry_->dimensions[0] - b2_polygonRadius,
187 geometry_->dimensions[1] - b2_polygonRadius);
189 shapes_.emplace_back(box);
195 auto *circle =
new b2CircleShape;
196 circle->m_p.Set(0, 0);
197 circle->m_radius = geometry_->dimensions[0];
199 shapes_.emplace_back(circle);
206 if (geometry_->points.size() > b2_maxPolygonVertices)
209 for (
const auto &geo : geometries_)
210 shapes_.emplace_back(createPolygon(geo));
213 shapes_.emplace_back(createPolygon(geometry_));
222 for (
const auto &partition : partitions)
224 if (partition->points.size() > b2_maxPolygonVertices)
227 for (
const auto &geo : triangles)
229 geometries_.emplace_back(geo);
230 shapes_.emplace_back(createPolygon(geo));
235 geometries_.emplace_back(partition);
236 shapes_.emplace_back(createPolygon(partition));
278 world_ = std::make_shared<Box2DWorld>();
281 for (
const auto &name :
robot_->getFrameNames())
283 const auto &data =
robot_->getFrameDataConst(name);
284 const auto &frame = data->frame;
285 const auto &geometry = frame->getGeometry();
287 if (not geometry.empty())
289 auto en =
shapes_.emplace(std::piecewise_construct,
292 for (
unsigned int i = 0; i < geometry.size(); ++i)
293 en.first->second.emplace_back(
294 std::make_shared<Box2DShape>(name, i, geometry[i],
world_, data->movable));
307 const auto &poses = state->getGeometryPoses(
robot_, e.first);
308 for (
unsigned int i = 0; i < poses.size(); ++i)
309 e.second[i]->setPose(poses[i]);
312 world_->world.Step(1, 0, 0);
313 world_->world.Step(1, 0, 0);
318 b2Contact *contact =
world_->world.GetContactList();
319 while (contact !=
nullptr)
321 auto fa =
static_cast<Box2DShape *
>(contact->GetFixtureA()->GetBody()->GetUserData());
322 auto fb =
static_cast<Box2DShape *
>(contact->GetFixtureB()->GetBody()->GetUserData());
324 if (contact->IsTouching() and
acm_->collide(fa->name, fb->name))
327 if (not callback(fa, fb, container))
331 contact = contact->GetNext();
342 const auto &name_a = ita->first;
343 const auto &shapes_a = ita->second;
345 for (
auto itb = ita; itb !=
shapes_.end(); ++itb)
347 const auto &name_b = itb->first;
348 const auto &shapes_b = itb->second;
351 if (not
acm_->collide(name_a, name_b))
354 for (
const auto &sa : shapes_a)
356 for (
const auto &sb : shapes_b)
358 if (not sa->movable and not sb->movable)
361 if (not callback(sa.get(), sb.get()))
393 return frames.
empty();
402 b2DistanceInput input;
403 input.useRadii =
true;
415 b2SimplexCache cache;
416 bzero(&cache,
sizeof(cache));
419 input.proxyA.Set(faf->GetShape(), 0);
420 input.proxyB.Set(fbf->GetShape(), 0);
422 b2DistanceOutput output;
423 b2Distance(&output, &cache, &input);
428 sd.
point = {output.pointA.x, output.pointA.y};
429 sd.
normal = {output.pointB.x - output.pointA.x, output.pointB.y - output.pointA.y};
439 b2WorldManifold world;
443 sd.
normal = {world.normal.x, world.normal.y};
445 for (
int i = 0; i < manifold->pointCount; ++i)
446 if (world.separations[i] < sd.
distance)
449 sd.
point = {world.points[i].x, world.points[i].y};
467 sd.collider = fb->name;
469 else if (fb->movable)
472 sd.collider = fa->
name;
514 auto f = frames.
find(sd.frame);
515 if (f == frames.
end())
518 else if (sd.distance < f->second.distance)
525 sd.collider = fb->name;
529 sd.collider = fa->
name;
SignedDistance distance(StatePtr &state) override
Computes the signed distance of a scene to collision.
b2World world
Box2D world.
const b2Transform & getTransform() const
Get the current pose of this body in the Box2D world.
A shared pointer wrapper for se2ez::State.
Box2DCollisionManager(const RobotPtr &robot)
Constructor.
T forward_as_tuple(T... args)
Eigen::Vector2d normal
Normal vector to collision.
const GeometryPtr & geometry_
Original geometry.
std::vector< std::pair< b2Vec2 *, unsigned int > > points_
Polygon points.
std::vector< GeometryPtr > shatter(const GeometryPtr &geometry)
"Shatters" a convex polygon into a fan of triangles using the first point as the root for all triangl...
std::mutex mutex_
Mutex for collision checking.
double getRotation(const Eigen::Isometry2d &frame)
Gets rotation from a frame from the X-axis (t)
const std::string name
Name of the frame this geometry is attached to.
virtual ~Box2DCollisionManager()
Destructor.
const bool movable
Is this a moving frame piece of geometry?
A shared pointer wrapper for se2ez::Box2DWorld.
std::vector< b2Shape * > shapes_
Box2D geometries;.
A class that contains all information about the signed distance of a frame to another.
const unsigned int index
Index in frame this geometry is.
bool checkContacts(const ContactCallback &callback)
Check all Box2D contacts in the world, and call a callback function for each.
void compile() override
Compiles internal data structures for collision checking. Needs to be called if the robot is updated...
A shared pointer wrapper for se2ez::Geometry.
const RobotPtr robot_
Robot model used for collision checking.
Eigen::Isometry2d toIsometry(double x, double y, double theta)
Converts a translation (x, y) and rotation from X-axis (theta) into a transform.
Eigen::Isometry2d getPose() const
Get the current pose of this body in the Box2D world.
std::map< std::string, std::vector< Box2DShapePtr > > shapes_
Map of frames to Box2D shapes.
SignedDistance computeDistance(const Box2DContact &contact) const
Compute distance from a contact.
b2Body * body_
Box2D body.
const std::vector< b2Fixture * > & getFixtures() const
Get the list of fixtures attached to this body.
void createShapes()
Convert the geometry of this body into a Box2D shape.
A simple polygon (no holes).
void update(StatePtr &state)
Updates internal world structure based upon robot state.
Box2DWorldPtr world_
Box2D world model.
std::string frame
Frame closet to collision.
void setPose(const Eigen::Isometry2d &pose)
Sets the pose of this body.
std::vector< GeometryPtr > geometries_
Geometry (created from decompositions).
Eigen::Vector2d point
Point on fixture where normal begins.
std::vector< b2FixtureDef > shapeDef_
Box2d shape definitions to create fixtures.
std::vector< GeometryPtr > convexifyOptimal(const GeometryPtr &geometry)
Performs an optimal convex decomposition on the geometry.
std::vector< b2Fixture * > fixture_
Box2D fixtures.
A shared pointer wrapper for se2ez::Robot.
ACMPtr acm_
ACM for collision manager.
Container class that converts se2ez::Geometry into a Box2D geometry.
Container class for Box2D's world representation.
b2BodyDef bodyDef_
Box2D body definition to create body.
Box2DShape(const std::string &name, const unsigned int index, const GeometryPtr &geometry, Box2DWorldPtr world, bool movable)
Constructor.
bool checkPotentials(const PotentialCallback &callback)
Check all potential collisions in the world, and call a callback function for each.
SE2EZ_EIGEN_CLASS double distance
Distance to collision.
bool collide(StatePtr &state) override
Check if a state is in collision.
b2PolygonShape * createPolygon(const GeometryPtr &geometry)