Added plane vs sphere penetration test.
parent
7e7b08b919
commit
c02255d64c
|
@ -15,10 +15,13 @@ struct SimShape;
|
||||||
struct SimBody;
|
struct SimBody;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
|
|
||||||
|
const double cCollisionEps = 1.0e-4;
|
||||||
|
|
||||||
struct SimShape {
|
struct SimShape {
|
||||||
enum ShapeType {
|
enum ShapeType {
|
||||||
Box = 0,
|
Box = 0,
|
||||||
Sphere = 1,
|
Sphere = 1,
|
||||||
|
Plane = 2
|
||||||
};
|
};
|
||||||
ShapeType mType;
|
ShapeType mType;
|
||||||
Vector3d pos;
|
Vector3d pos;
|
||||||
|
@ -68,6 +71,11 @@ bool CheckPenetration(
|
||||||
const SimShape& shape_b,
|
const SimShape& shape_b,
|
||||||
CollisionInfo& cinfo);
|
CollisionInfo& cinfo);
|
||||||
|
|
||||||
|
bool CheckPenetrationSphereVsPlane(
|
||||||
|
const SimShape& shape_a,
|
||||||
|
const SimShape& shape_b,
|
||||||
|
CollisionInfo& cinfo);
|
||||||
|
|
||||||
SimBody CreateSphereBody(
|
SimBody CreateSphereBody(
|
||||||
double mass,
|
double mass,
|
||||||
double radius,
|
double radius,
|
||||||
|
|
|
@ -12,10 +12,10 @@ void simplesim() {
|
||||||
world.mBodies.push_back(sphere_body);
|
world.mBodies.push_back(sphere_body);
|
||||||
|
|
||||||
SimShape ground_shape;
|
SimShape ground_shape;
|
||||||
ground_shape.mType = SimShape::Box;
|
ground_shape.mType = SimShape::Plane;
|
||||||
ground_shape.pos.set(0., -5.0, 0.);
|
ground_shape.pos.set(0., 0., 0.);
|
||||||
ground_shape.orientation.set(0., 0., 0., 1.);
|
ground_shape.orientation.set(0., 0., 0., 1.);
|
||||||
ground_shape.scale.set(25.0, 10.0, 25.0);
|
ground_shape.scale.set(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
world.mStaticShapes.push_back(ground_shape);
|
world.mStaticShapes.push_back(ground_shape);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ void simplesim() {
|
||||||
world.detectCollisions();
|
world.detectCollisions();
|
||||||
world.resolveCollisions(dt);
|
world.resolveCollisions(dt);
|
||||||
world.integrateWorld(dt);
|
world.integrateWorld(dt);
|
||||||
} while (world.mSimTime < 1.01);
|
} while (world.mSimTime < 10.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
|
|
@ -82,6 +82,9 @@ void SimShapeSupport(
|
||||||
} else {
|
} else {
|
||||||
ccdVec3Set(v, CCD_ZERO, CCD_ZERO, CCD_ZERO);
|
ccdVec3Set(v, CCD_ZERO, CCD_ZERO, CCD_ZERO);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cerr << "Unknown shape type: " << shape->mType << endl;
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform support point according to position and rotation of object
|
// transform support point according to position and rotation of object
|
||||||
|
@ -93,6 +96,15 @@ bool CheckPenetration(
|
||||||
const SimShape& shape_a,
|
const SimShape& shape_a,
|
||||||
const SimShape& shape_b,
|
const SimShape& shape_b,
|
||||||
CollisionInfo& cinfo) {
|
CollisionInfo& cinfo) {
|
||||||
|
if (shape_a.mType == SimShape::Sphere && shape_b.mType == SimShape::Plane) {
|
||||||
|
return CheckPenetrationSphereVsPlane(shape_a, shape_b, cinfo);
|
||||||
|
}
|
||||||
|
if (shape_b.mType == SimShape::Sphere && shape_a.mType == SimShape::Plane) {
|
||||||
|
bool result = CheckPenetrationSphereVsPlane(shape_b, shape_a, cinfo);
|
||||||
|
cinfo.dir *= -1.;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ccd_t ccd;
|
ccd_t ccd;
|
||||||
CCD_INIT(&ccd);
|
CCD_INIT(&ccd);
|
||||||
ccd.support1 = SimShapeSupport;
|
ccd.support1 = SimShapeSupport;
|
||||||
|
@ -114,6 +126,31 @@ bool CheckPenetration(
|
||||||
return !intersect;
|
return !intersect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckPenetrationSphereVsPlane(
|
||||||
|
const SimShape& shape_a,
|
||||||
|
const SimShape& shape_b,
|
||||||
|
CollisionInfo& cinfo) {
|
||||||
|
assert(shape_a.mType == SimShape::Sphere);
|
||||||
|
assert(shape_b.mType == SimShape::Plane);
|
||||||
|
|
||||||
|
// For now only support aligned spheres
|
||||||
|
assert((shape_a.orientation - Quaternion(0., 0., 0., 1.)).squaredNorm() < cCollisionEps);
|
||||||
|
|
||||||
|
Vector3d plane_normal = shape_b.orientation.toMatrix().block(0,1,3,1);
|
||||||
|
Vector3d plane_point = shape_b.pos;
|
||||||
|
Vector3d sphere_point_to_plane = shape_a.pos - plane_normal * shape_a.scale[0];
|
||||||
|
|
||||||
|
double sphere_center_height = plane_normal.transpose() * (sphere_point_to_plane - plane_point);
|
||||||
|
if (sphere_center_height < cCollisionEps) {
|
||||||
|
cinfo.pos = sphere_point_to_plane;
|
||||||
|
cinfo.dir = plane_normal;
|
||||||
|
cinfo.depth = sphere_center_height;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void SimBody::updateCollisionShapes() {
|
void SimBody::updateCollisionShapes() {
|
||||||
UpdateKinematicsCustom(mModel, &q, nullptr, nullptr);
|
UpdateKinematicsCustom(mModel, &q, nullptr, nullptr);
|
||||||
|
|
||||||
|
@ -241,7 +278,7 @@ void SimBody::resolveCollisions(
|
||||||
|
|
||||||
// Solve for the impules hlambda
|
// Solve for the impules hlambda
|
||||||
A = G * Minv * G.transpose();
|
A = G * Minv * G.transpose();
|
||||||
b = (constr_value + VectorNd::Constant(nconstraints, 0.0001) ) * 1. / dt + G * (qdot + Minv * dt * (tau - N)) * -1.0;
|
b = (constr_value ) * 1. / dt + G * (qdot + Minv * dt * (tau - N));
|
||||||
|
|
||||||
VectorNd hlambda (VectorNd::Zero(nconstraints));
|
VectorNd hlambda (VectorNd::Zero(nconstraints));
|
||||||
VectorNd hlambda_lo (VectorNd::Constant(nconstraints, 0.));
|
VectorNd hlambda_lo (VectorNd::Constant(nconstraints, 0.));
|
||||||
|
@ -438,4 +475,6 @@ SimBody CreateBoxBody(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace RBDLSim
|
} // namespace RBDLSim
|
|
@ -44,3 +44,41 @@ TEST_CASE("Simple Box vs Sphere Collision", "[Collision]") {
|
||||||
REQUIRE(cresult == false);
|
REQUIRE(cresult == false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE ("CheckCollisionSphereVsPlane", "[Collision]") {
|
||||||
|
SimShape plane;
|
||||||
|
plane.mType = SimShape::Plane;
|
||||||
|
plane.pos = Vector3d (0., 0., 0.);
|
||||||
|
plane.orientation = Quaternion (0., 1., 0., 1.);
|
||||||
|
plane.scale = Vector3d (1., 1., 1.);
|
||||||
|
|
||||||
|
SimShape sphere;
|
||||||
|
sphere.mType = SimShape::Sphere;
|
||||||
|
|
||||||
|
sphere.scale = Vector3d (1.5, 1.5, 1.5);
|
||||||
|
sphere.orientation = Quaternion(0., 0., 0., 1.);
|
||||||
|
|
||||||
|
CollisionInfo cinfo;
|
||||||
|
bool cresult = false;
|
||||||
|
|
||||||
|
SECTION ("Sphere above plane") {
|
||||||
|
sphere.pos = Vector3d (0., 2.0, 0.);
|
||||||
|
cresult = CheckPenetrationSphereVsPlane(sphere, plane, cinfo);
|
||||||
|
|
||||||
|
REQUIRE(cresult == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION ("Sphere touching") {
|
||||||
|
sphere.pos = Vector3d (0., 1.5, 0.);
|
||||||
|
cresult = CheckPenetrationSphereVsPlane(sphere, plane, cinfo);
|
||||||
|
|
||||||
|
REQUIRE(cresult == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION ("Sphere penetration") {
|
||||||
|
sphere.pos = Vector3d (0., -1., 0.);
|
||||||
|
cresult = CheckPenetrationSphereVsPlane(sphere, plane, cinfo);
|
||||||
|
|
||||||
|
REQUIRE(cresult == false);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue