37 #define BOOST_TEST_MODULE COAL_HEIGHT_FIELDS
38 #include <boost/test/included/unit_test.hpp>
39 #include <boost/filesystem.hpp>
41 #include "fcl_resources/config.h"
58 template <
typename BV>
60 const Eigen::DenseIndex ny,
64 const MatrixXs heights = MatrixXs::Constant(ny, nx, max_altitude);
68 BOOST_CHECK(hfield.
getXDim() == x_dim);
69 BOOST_CHECK(hfield.
getYDim() == y_dim);
72 BOOST_CHECK(x_grid[0] == -x_dim / 2.);
73 BOOST_CHECK(x_grid[nx - 1] == x_dim / 2.);
76 BOOST_CHECK(y_grid[0] == y_dim / 2.);
77 BOOST_CHECK(y_grid[ny - 1] == -y_dim / 2.);
82 for (Eigen::DenseIndex i = 0; i < nx; ++i) {
83 for (Eigen::DenseIndex j = 0; j < ny; ++j) {
84 Vec3s point(x_grid[i], y_grid[j], heights(j, i));
93 BOOST_CHECK(*hfield_clone == hfield);
99 const Box equivalent_box(x_dim, y_dim, max_altitude - min_altitude);
101 Matrix3s::Identity(),
Vec3s(0., 0., (max_altitude + min_altitude) / 2.));
107 const Box box(Vec3s::Ones());
113 const CoalScalar eps_no_collision = +0.1 * (max_altitude - min_altitude);
115 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
116 M_box.setTranslation(
117 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
127 request, result_check_sphere);
132 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
140 const CoalScalar eps_collision = -0.1 * (max_altitude - min_altitude);
142 Vec3s(0., 0., max_altitude +
sphere.radius + eps_collision));
143 M_box.setTranslation(
144 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_collision));
155 request, result_check);
160 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
168 MatrixXs::Constant(ny, nx, max_altitude / 2.));
172 const CoalScalar eps_no_collision = +0.1 * (max_altitude - min_altitude);
174 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
175 M_box.setTranslation(
176 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
186 request, result_check_sphere);
191 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
199 const CoalScalar eps_collision = -0.1 * (max_altitude - min_altitude);
201 Vec3s(0., 0., max_altitude +
sphere.radius + eps_collision));
202 M_box.setTranslation(
203 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_collision));
214 request, result_check);
219 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
227 MatrixXs::Constant(ny, nx, max_altitude));
231 const CoalScalar eps_collision = -0.1 * (max_altitude - min_altitude);
233 Vec3s(0., 0., max_altitude +
sphere.radius + eps_collision));
234 M_box.setTranslation(
235 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_collision));
246 request, result_check);
251 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
259 const CoalScalar max_altitude = 1., min_altitude = 0.;
261 test_constant_hfields<OBBRSS>(2, 2, min_altitude,
263 test_constant_hfields<OBBRSS>(20, 2, min_altitude, max_altitude);
264 test_constant_hfields<OBBRSS>(100, 100, min_altitude, max_altitude);
267 test_constant_hfields<AABB>(2, 2, min_altitude, max_altitude);
268 test_constant_hfields<AABB>(20, 2, min_altitude, max_altitude);
269 test_constant_hfields<AABB>(100, 100, min_altitude, max_altitude);
272 template <
typename BV>
274 const Eigen::DenseIndex ny,
278 const MatrixXs heights = MatrixXs::Constant(ny, nx, max_altitude);
283 const Box equivalent_box(x_dim, y_dim, max_altitude - min_altitude);
285 Matrix3s::Identity(),
Vec3s(0., 0., (max_altitude + min_altitude) / 2.));
291 const Box box(Vec3s::Ones());
297 const CoalScalar eps_no_collision = +0.1 * (max_altitude - min_altitude);
299 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
300 M_box.setTranslation(
301 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
311 request, result_check_sphere);
316 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
324 const CoalScalar eps_no_collision = +0.1 * (max_altitude - min_altitude);
326 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
327 M_box.setTranslation(
328 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
339 request, result_check_sphere);
344 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
352 const CoalScalar eps_no_collision = -0.1 * (max_altitude - min_altitude);
354 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
355 M_box.setTranslation(
356 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
366 request, result_check_sphere);
371 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
379 const CoalScalar eps_no_collision = -0.1 * (max_altitude - min_altitude);
381 Vec3s(0., 0., max_altitude +
sphere.radius + eps_no_collision));
382 M_box.setTranslation(
383 Vec3s(0., 0., max_altitude +
box.halfSide[2] + eps_no_collision));
394 request, result_check_sphere);
399 collide(&equivalent_box, IdTransform * box_placement, &
box,
M_box, request,
407 const CoalScalar max_altitude = 1., min_altitude = 0.;
411 test_negative_security_margin<AABB>(100, 100, min_altitude, max_altitude);
415 const Eigen::DenseIndex nx = 100, ny = 100;
419 Eigen::RowVectorXd::LinSpaced(nx, -1., 1.).replicate(ny, 1);
420 const MatrixXs Y = Eigen::VectorXd::LinSpaced(ny, 1., -1.).replicate(1, nx);
424 const Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> hole =
425 (
X.array().abs() < dim_square) && (
Y.array().abs() < dim_square);
428 MatrixXs::Ones(ny, nx) - hole.cast<
double>().matrix();
440 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
449 const Sphere sphere2(0.51);
450 collide(&hfield, hfield_pos, &sphere2, sphere_pos, request, result);
457 const Eigen::DenseIndex nx = 100, ny = 100;
463 Eigen::RowVectorXd::LinSpaced(nx, -1., 1.).replicate(ny, 1);
464 const MatrixXs Y = Eigen::VectorXd::LinSpaced(ny, 1., -1.).replicate(1, nx);
468 const Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> hole =
469 (
X.array().square() +
Y.array().square() <= dim_hole);
472 MatrixXs::Ones(ny, nx) - hole.cast<
double>().matrix();
476 BOOST_CHECK(hfield.
getXGrid()[0] == -1.);
477 BOOST_CHECK(hfield.
getXGrid()[nx - 1] == +1.);
479 BOOST_CHECK(hfield.
getYGrid()[0] == +1.);
480 BOOST_CHECK(hfield.
getYGrid()[ny - 1] == -1.);
486 const CoalScalar thresholds[3] = {0., 0.01, -0.005};
488 for (
int i = 0; i < 3; ++i) {
492 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
499 for (
int i = 0; i < 3; ++i) {
503 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
512 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
520 return std::fabs(v1 - v2) <= tol;
524 const std::vector<Vec3s>& points) {
525 const Vec3s pointA = points[triangle[0]];
526 const Vec3s pointB = points[triangle[1]];
527 const Vec3s pointC = points[triangle[2]];
529 return (pointB - pointA).cross(pointC - pointA).normalized();
537 altitutes.fill(altitude_value);
543 BOOST_CHECK(nodes.size() == 1);
548 int(FaceOrientation::BOTTOM));
550 int(FaceOrientation::TOP));
552 int(FaceOrientation::NORTH));
554 int(FaceOrientation::SOUTH));
556 int(FaceOrientation::EAST));
558 int(FaceOrientation::WEST));
561 int convex1_active_faces, convex2_active_faces;
562 details::buildConvexTriangles(node, hfield, convex1, convex1_active_faces,
563 convex2, convex2_active_faces);
567 const std::vector<Vec3s>& points = *(convex1.points);
596 const Vec3s south_east_normal =
Vec3s(1., -1., 0).normalized();
612 std::cout <<
"computeFaceNormal(triangle1,points): "
624 const std::vector<Vec3s>& points = *(convex2.points);
654 const Vec3s north_west_normal =
Vec3s(-1., 1., 0).normalized();
684 altitutes.fill(altitude_value);
690 BOOST_CHECK(nodes.size() == 7);
692 for (
const auto& node : nodes) {
694 BOOST_CHECK((node.contact_active_faces & FaceOrientation::BOTTOM) ==
695 int(FaceOrientation::BOTTOM));
696 BOOST_CHECK((node.contact_active_faces & FaceOrientation::TOP) ==
697 int(FaceOrientation::TOP));
700 BOOST_CHECK((node.contact_active_faces & FaceOrientation::WEST) ==
701 int(FaceOrientation::WEST));
703 BOOST_CHECK((node.contact_active_faces & FaceOrientation::NORTH) ==
704 int(FaceOrientation::NORTH));
707 BOOST_CHECK((node.contact_active_faces & FaceOrientation::EAST) ==
708 int(FaceOrientation::EAST));
710 BOOST_CHECK((node.contact_active_faces & FaceOrientation::SOUTH) ==
711 int(FaceOrientation::SOUTH));
721 altitutes.fill(altitude_value);
727 BOOST_CHECK(nodes.size() == 1);
737 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
752 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
772 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
784 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
805 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
818 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
837 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
850 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
870 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
883 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
903 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);
916 collide(&hfield, hfield_pos, &
sphere, sphere_pos, request, result);