13 #ifndef OMPLAPP_GEOMETRY_DETAIL_PQP_COLLISION_CHECKER_
14 #define OMPLAPP_GEOMETRY_DETAIL_PQP_COLLISION_CHECKER_
16 #include <ompl/base/SpaceInformation.h>
17 #include <ompl/base/spaces/SE2StateSpace.h>
18 #include <ompl/base/spaces/SE3StateSpace.h>
20 #include "omplapp/geometry/GeometrySpecification.h"
21 #include "omplapp/geometry/detail/assimpUtil.h"
38 template<MotionModel T>
52 m[0][0] = sqx - sqy - sqz + sqw;
53 m[1][1] = -sqx + sqy - sqz + sqw;
54 m[2][2] = -sqx - sqy + sqz + sqw;
56 double tmp1 = q.x*q.y;
57 double tmp2 = q.z*q.w;
58 m[1][0] = 2.0 * (tmp1 + tmp2);
59 m[0][1] = 2.0 * (tmp1 - tmp2);
62 m[2][0] = 2.0 * (tmp1 - tmp2);
63 m[0][2] = 2.0 * (tmp1 + tmp2);
66 m[2][1] = 2.0 * (tmp1 + tmp2);
67 m[1][2] = 2.0 * (tmp1 - tmp2);
70 void PQP_pose_from_state(PQP_REAL robTrans[3], PQP_REAL robRot[3][3],
const type &s)
const
72 robTrans[0] = s.getX();
73 robTrans[1] = s.getY();
74 robTrans[2] = s.getZ();
75 quaternionToMatrix(robRot, s.rotation());
80 struct OMPL_StateType<Motion_2D>
84 void PQP_pose_from_state(PQP_REAL robTrans[3], PQP_REAL robRot[3][3],
const type &s)
const
86 robTrans[0] = s.getX();
87 robTrans[1] = s.getY();
90 const double ca = cos(s.getYaw());
91 const double sa = sin(s.getYaw());
115 template<MotionModel T>
116 class PQPStateValidityChecker :
public base::StateValidityChecker
120 PQPStateValidityChecker(
const base::SpaceInformationPtr &si,
const GeometrySpecification &geom,
121 GeometricStateExtractor se,
bool selfCollision) : base::
StateValidityChecker(si), extractState_(std::move(se)),
122 selfCollision_(selfCollision)
128 bool isValid(
const base::State *state)
const override
130 using StateType =
typename OMPL_StateType<T>::type;
138 static PQP_REAL identityTranslation[3] = { 0.0, 0.0, 0.0 };
139 static PQP_REAL identityRotation[3][3] = { { 1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} };
141 std::lock_guard<std::mutex> slock(mutex_);
143 PQP_REAL robTrans[3];
144 PQP_REAL robRot[3][3];
146 for (std::size_t i = 0 ; i <
robotParts_.size() ; ++i)
148 stateConvertor_.PQP_pose_from_state(robTrans, robRot, *
static_cast<const StateType*
>(extractState_(state, i)));
149 PQP_CollideResult cr;
150 PQP_Collide(&cr, robRot, robTrans,
robotParts_[i].get(),
151 identityRotation, identityTranslation,
environment_.get(), PQP_FIRST_CONTACT);
152 if (cr.Colliding() != 0)
158 PQP_REAL robTrans2[3];
159 PQP_REAL robRot2[3][3];
160 for (std::size_t i = 0 ; i <
robotParts_.size() ; ++i)
162 stateConvertor_.PQP_pose_from_state(robTrans, robRot, *
static_cast<const StateType*
>(extractState_(state, i)));
163 for (std::size_t j = i + 1 ; j <
robotParts_.size() ; ++j)
165 stateConvertor_.PQP_pose_from_state(robTrans2, robRot2, *
static_cast<const StateType*
>(extractState_(state, j)));
166 PQP_CollideResult cr;
167 PQP_Collide(&cr, robRot, robTrans,
robotParts_[i].get(),
168 robRot2, robTrans2,
robotParts_[j].get(), PQP_FIRST_CONTACT);
169 if (cr.Colliding() != 0)
178 double clearance(
const base::State *state)
const override
180 using StateType =
typename OMPL_StateType<T>::type;
182 double dist = std::numeric_limits<double>::infinity();
185 static PQP_REAL identityTranslation[3] = { 0.0, 0.0, 0.0 };
186 static PQP_REAL identityRotation[3][3] = { { 1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} };
188 std::lock_guard<std::mutex> slock(mutex_);
190 PQP_REAL robTrans[3];
191 PQP_REAL robRot[3][3];
193 for (std::size_t i = 0 ; i <
robotParts_.size() ; ++i)
195 stateConvertor_.PQP_pose_from_state(robTrans, robRot, *
static_cast<const StateType*
>(extractState_(state, i)));
196 PQP_DistanceResult dr;
197 PQP_Distance(&dr, robRot, robTrans,
robotParts_[i].get(),
199 if (dist > dr.Distance())
200 dist = dr.Distance();
211 void configure(
const GeometrySpecification &geom)
213 std::pair<PQPModelPtr, double> p = getPQPModelFromScene(geom.obstacles, geom.obstaclesShift);
223 for (
unsigned int i = 0 ; i < geom.robot.size() ; ++i)
225 aiVector3D shift(0.0, 0.0, 0.0);
226 if (geom.robotShift.size() > i)
227 shift = geom.robotShift[i];
228 PQPModelPtr m = getPQPModelFromScene(geom.robot[i], shift).first;
232 OMPL_INFORM(
"Loaded robot model with %d triangles", m->num_tris);
237 std::pair<PQPModelPtr, double> getPQPModelFromScene(
const aiScene *scene,
const aiVector3D ¢er)
const
239 std::vector<const aiScene*> scenes(1, scene);
240 std::vector<aiVector3D> centers(1, center);
241 return getPQPModelFromScene(scenes, centers);
245 std::pair<PQPModelPtr, double> getPQPModelFromScene(
const std::vector<const aiScene*> &scenes,
const std::vector<aiVector3D> ¢er)
const
247 std::vector<aiVector3D> triangles;
248 for (
unsigned int i = 0 ; i < scenes.size() ; ++i)
249 if (scenes[i] !=
nullptr)
251 std::vector<aiVector3D> t;
252 scene::extractTriangles(scenes[i], t);
253 if (center.size() > i)
256 triangles.insert(triangles.end(), t.begin(), t.end());
262 std::pair<PQPModelPtr, double>
getPQPModelFromTris(
const std::vector<aiVector3D> &triangles)
const
263 #ifdef OMPLAPP_ADD_PADDING_FOR_DIMENSION
265 base::RealVectorBounds bounds(3);
266 scene::inferBounds(bounds, triangles, 1.0, 0.0);
267 const std::vector<double> &b = bounds.getDifference();
268 unsigned int d = b[0] > b[1] ? 1 : 0;
272 double other = (b[(d + 1) % 3] + b[(d + 2) % 3]) / 2.0;
273 if (b[d] * 1000.0 < other && b[d] < 0.1)
275 OMPL_DEBUG(
"Adding padding for dimension %u so that collision checking is more accurate", d);
276 std::vector<aiVector3D> extraTri;
277 extraTri.reserve(triangles.size() * 8);
278 const int N = triangles.size() / 3;
279 double padd = other / 10.0;
281 for (
int j = 0 ; j < N ; ++j)
283 const aiVector3D &v0 = triangles[j * 3];
284 const aiVector3D &v1 = triangles[j * 3 + 1];
285 const aiVector3D &v2 = triangles[j * 3 + 2];
286 aiVector3D x0 = v0; x0[d] += padd;
287 aiVector3D x1 = v1; x1[d] += padd;
288 aiVector3D x2 = v2; x2[d] += padd;
289 extraTri.push_back(v0); extraTri.push_back(v1); extraTri.push_back(v2);
290 extraTri.push_back(x0); extraTri.push_back(x2); extraTri.push_back(x1);
291 extraTri.push_back(x1); extraTri.push_back(v1); extraTri.push_back(v2);
292 extraTri.push_back(x1); extraTri.push_back(v2); extraTri.push_back(x2);
293 extraTri.push_back(x1); extraTri.push_back(v0); extraTri.push_back(v1);
294 extraTri.push_back(x1); extraTri.push_back(x0); extraTri.push_back(v0);
295 extraTri.push_back(v0); extraTri.push_back(v2); extraTri.push_back(x2);
296 extraTri.push_back(v0); extraTri.push_back(x2); extraTri.push_back(x0);
299 return getPQPModelFromTrisHelper(extraTri);
302 return getPQPModelFromTrisHelper(triangles);
306 std::pair<PQPModelPtr, double> getPQPModelFromTrisHelper(
const std::vector<aiVector3D> &triangles)
const
311 if (triangles.empty())
312 return std::make_pair(model, 0.0);
315 model = std::make_shared<PQP_Model>();
318 const int N = triangles.size() / 3;
319 double avgSide = 0.0;
320 for (
int j = 0 ; j < N ; ++j)
322 const aiVector3D &v0 = triangles[j * 3];
323 const aiVector3D &v1 = triangles[j * 3 + 1];
324 const aiVector3D &v2 = triangles[j * 3 + 2];
325 PQP_REAL dV0[3] = {v0.x, v0.y, v0.z};
326 PQP_REAL dV1[3] = {v1.x, v1.y, v1.z};
327 PQP_REAL dV2[3] = {v2.x, v2.y, v2.z};
328 avgSide += (v1 - v0).Length() + (v1 - v2).Length() + (v2 - v0).Length();
329 model->AddTri(dV0, dV1, dV2,
id++);
334 return std::make_pair(model, avgSide / (
double)triangles.size());
337 OMPL_StateType<T> stateConvertor_;
339 GeometricStateExtractor extractState_;
355 mutable std::mutex mutex_;