GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
// |
||
2 |
// Copyright (c) 2015-2021 CNRS INRIA |
||
3 |
// |
||
4 |
|||
5 |
#ifndef __pinocchio_algo_geometry_hxx__ |
||
6 |
#define __pinocchio_algo_geometry_hxx__ |
||
7 |
|||
8 |
#include <boost/foreach.hpp> |
||
9 |
#include <sstream> |
||
10 |
|||
11 |
namespace pinocchio |
||
12 |
{ |
||
13 |
/* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */ |
||
14 |
/* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */ |
||
15 |
/* --- GEOMETRY PLACEMENTS -------------------------------------------------------- */ |
||
16 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType> |
||
17 |
16 |
inline void updateGeometryPlacements(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
|
18 |
DataTpl<Scalar,Options,JointCollectionTpl> & data, |
||
19 |
const GeometryModel & geom_model, |
||
20 |
GeometryData & geom_data, |
||
21 |
const Eigen::MatrixBase<ConfigVectorType> & q) |
||
22 |
{ |
||
23 |
✓✗ | 16 |
assert(model.check(data) && "data is not consistent with model."); |
24 |
|||
25 |
16 |
forwardKinematics(model, data, q); |
|
26 |
16 |
updateGeometryPlacements(model, data, geom_model, geom_data); |
|
27 |
16 |
} |
|
28 |
|||
29 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl> |
||
30 |
22 |
inline void updateGeometryPlacements(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
|
31 |
const DataTpl<Scalar,Options,JointCollectionTpl> & data, |
||
32 |
const GeometryModel & geom_model, |
||
33 |
GeometryData & geom_data) |
||
34 |
{ |
||
35 |
PINOCCHIO_UNUSED_VARIABLE(model); |
||
36 |
✓✗ | 22 |
assert(model.check(data) && "data is not consistent with model."); |
37 |
|||
38 |
✓✓ | 488 |
for(GeomIndex i=0; i < (GeomIndex) geom_model.ngeoms; ++i) |
39 |
{ |
||
40 |
466 |
const Model::JointIndex joint_id = geom_model.geometryObjects[i].parentJoint; |
|
41 |
✓✓ | 466 |
if (joint_id>0) geom_data.oMg[i] = (data.oMi[joint_id] * geom_model.geometryObjects[i].placement); |
42 |
11 |
else geom_data.oMg[i] = geom_model.geometryObjects[i].placement; |
|
43 |
} |
||
44 |
22 |
} |
|
45 |
#ifdef PINOCCHIO_WITH_HPP_FCL |
||
46 |
|||
47 |
/* --- COLLISIONS ----------------------------------------------------------------- */ |
||
48 |
/* --- COLLISIONS ----------------------------------------------------------------- */ |
||
49 |
/* --- COLLISIONS ----------------------------------------------------------------- */ |
||
50 |
|||
51 |
2131 |
inline bool computeCollision(const GeometryModel & geom_model, |
|
52 |
GeometryData & geom_data, |
||
53 |
const PairIndex pair_id) |
||
54 |
{ |
||
55 |
✗✓✗✗ |
2131 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( geom_model.collisionPairs.size() == geom_data.collisionResults.size() ); |
56 |
✗✓✗✗ |
2131 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair_id < geom_model.collisionPairs.size() ); |
57 |
2131 |
const CollisionPair & pair = geom_model.collisionPairs[pair_id]; |
|
58 |
|||
59 |
✗✓✗✗ |
2131 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair.first < geom_model.ngeoms ); |
60 |
✗✓✗✗ |
2131 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair.second < geom_model.ngeoms ); |
61 |
|||
62 |
2131 |
fcl::CollisionRequest & collision_request = geom_data.collisionRequests[pair_id]; |
|
63 |
2131 |
collision_request.distance_upper_bound = collision_request.security_margin + 1e-6; // TODO: change the margin |
|
64 |
|||
65 |
2131 |
fcl::CollisionResult & collision_result = geom_data.collisionResults[pair_id]; |
|
66 |
2131 |
collision_result.clear(); |
|
67 |
|||
68 |
✓✗ | 2131 |
fcl::Transform3f oM1 (toFclTransform3f(geom_data.oMg[pair.first ])), |
69 |
✓✗ | 2131 |
oM2 (toFclTransform3f(geom_data.oMg[pair.second])); |
70 |
|||
71 |
try |
||
72 |
{ |
||
73 |
2131 |
GeometryData::ComputeCollision & do_computations = geom_data.collision_functors[pair_id]; |
|
74 |
✓✗ | 2131 |
do_computations(oM1, oM2, collision_request, collision_result); |
75 |
} |
||
76 |
catch(std::invalid_argument & e) |
||
77 |
{ |
||
78 |
std::stringstream ss; |
||
79 |
ss << "Problem when trying to check the collision of collision pair #" << pair_id << " (" << pair.first << "," << pair.second << ")" << std::endl; |
||
80 |
ss << "hpp-fcl original error:\n" << e.what() << std::endl; |
||
81 |
throw std::invalid_argument(ss.str()); |
||
82 |
} |
||
83 |
|||
84 |
|||
85 |
4262 |
return collision_result.isCollision(); |
|
86 |
} |
||
87 |
|||
88 |
6 |
inline bool computeCollisions(const GeometryModel & geom_model, |
|
89 |
GeometryData & geom_data, |
||
90 |
const bool stopAtFirstCollision) |
||
91 |
{ |
||
92 |
6 |
bool isColliding = false; |
|
93 |
|||
94 |
2060 |
for (std::size_t cp_index = 0; |
|
95 |
✓✓ | 2060 |
cp_index < geom_model.collisionPairs.size(); ++cp_index) |
96 |
{ |
||
97 |
2054 |
const CollisionPair & cp = geom_model.collisionPairs[cp_index]; |
|
98 |
|||
99 |
2054 |
if(geom_data.activeCollisionPairs[cp_index] |
|
100 |
✓✗✓✗ ✓✗✓✗ |
2054 |
&& !(geom_model.geometryObjects[cp.first].disableCollision || geom_model.geometryObjects[cp.second].disableCollision)) |
101 |
{ |
||
102 |
2054 |
bool res = computeCollision(geom_model,geom_data,cp_index); |
|
103 |
✓✗✗✓ |
2054 |
if(!isColliding && res) |
104 |
{ |
||
105 |
isColliding = true; |
||
106 |
geom_data.collisionPairIndex = cp_index; // first pair to be in collision |
||
107 |
if(stopAtFirstCollision) |
||
108 |
return true; |
||
109 |
} |
||
110 |
} |
||
111 |
} |
||
112 |
|||
113 |
6 |
return isColliding; |
|
114 |
} |
||
115 |
|||
116 |
// WARNING, if stopAtFirstcollision = true, then the collisions vector will not be fulfilled. |
||
117 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType> |
||
118 |
4 |
inline bool computeCollisions(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
|
119 |
DataTpl<Scalar,Options,JointCollectionTpl> & data, |
||
120 |
const GeometryModel & geom_model, |
||
121 |
GeometryData & geom_data, |
||
122 |
const Eigen::MatrixBase<ConfigVectorType> & q, |
||
123 |
const bool stopAtFirstCollision) |
||
124 |
{ |
||
125 |
4 |
updateGeometryPlacements(model, data, geom_model, geom_data, q); |
|
126 |
4 |
return computeCollisions(geom_model,geom_data, stopAtFirstCollision); |
|
127 |
} |
||
128 |
|||
129 |
/* --- DISTANCES ----------------------------------------------------------------- */ |
||
130 |
/* --- DISTANCES ----------------------------------------------------------------- */ |
||
131 |
/* --- DISTANCES ----------------------------------------------------------------- */ |
||
132 |
|||
133 |
141 |
inline fcl::DistanceResult & computeDistance(const GeometryModel & geom_model, |
|
134 |
GeometryData & geom_data, |
||
135 |
const PairIndex pair_id) |
||
136 |
{ |
||
137 |
✗✓✗✗ |
141 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair_id < geom_model.collisionPairs.size() ); |
138 |
✗✓✗✗ |
141 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( geom_model.collisionPairs.size() == geom_data.collisionResults.size() ); |
139 |
141 |
const CollisionPair & pair = geom_model.collisionPairs[pair_id]; |
|
140 |
|||
141 |
✗✓✗✗ |
141 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair.first < geom_model.ngeoms ); |
142 |
✗✓✗✗ |
141 |
PINOCCHIO_CHECK_INPUT_ARGUMENT( pair.second < geom_model.ngeoms ); |
143 |
|||
144 |
141 |
fcl::DistanceRequest & distance_request = geom_data.distanceRequests[pair_id]; |
|
145 |
141 |
fcl::DistanceResult & distance_result = geom_data.distanceResults[pair_id]; |
|
146 |
✓✗ | 141 |
distance_result.clear(); |
147 |
|||
148 |
✓✗ | 141 |
fcl::Transform3f oM1 (toFclTransform3f(geom_data.oMg[pair.first ])), |
149 |
✓✗ | 141 |
oM2 (toFclTransform3f(geom_data.oMg[pair.second])); |
150 |
|||
151 |
try |
||
152 |
{ |
||
153 |
141 |
GeometryData::ComputeDistance & do_computations = geom_data.distance_functors[pair_id]; |
|
154 |
✓✗ | 141 |
do_computations(oM1, oM2, distance_request, distance_result); |
155 |
} |
||
156 |
catch(std::invalid_argument & e) |
||
157 |
{ |
||
158 |
std::stringstream ss; |
||
159 |
ss << "Problem when trying to compute the distance of collision pair #" << pair_id << " (" << pair.first << "," << pair.second << ")" << std::endl; |
||
160 |
ss << "hpp-fcl original error:\n" << e.what() << std::endl; |
||
161 |
throw std::invalid_argument(ss.str()); |
||
162 |
} |
||
163 |
|||
164 |
282 |
return geom_data.distanceResults[pair_id]; |
|
165 |
} |
||
166 |
|||
167 |
2 |
inline std::size_t computeDistances(const GeometryModel & geom_model, |
|
168 |
GeometryData & geom_data) |
||
169 |
{ |
||
170 |
2 |
std::size_t min_index = geom_model.collisionPairs.size(); |
|
171 |
2 |
double min_dist = std::numeric_limits<double>::infinity(); |
|
172 |
|||
173 |
142 |
for (std::size_t cp_index = 0; |
|
174 |
✓✓ | 142 |
cp_index < geom_model.collisionPairs.size(); ++cp_index) |
175 |
{ |
||
176 |
140 |
const CollisionPair & cp = geom_model.collisionPairs[cp_index]; |
|
177 |
|||
178 |
140 |
if( geom_data.activeCollisionPairs[cp_index] |
|
179 |
✓✗✓✗ ✓✗✓✗ |
140 |
&& !(geom_model.geometryObjects[cp.first].disableCollision || geom_model.geometryObjects[cp.second].disableCollision)) |
180 |
{ |
||
181 |
140 |
computeDistance(geom_model,geom_data,cp_index); |
|
182 |
✓✓ | 140 |
if(geom_data.distanceResults[cp_index].min_distance < min_dist) |
183 |
{ |
||
184 |
10 |
min_index = cp_index; |
|
185 |
10 |
min_dist = geom_data.distanceResults[cp_index].min_distance; |
|
186 |
} |
||
187 |
} |
||
188 |
} |
||
189 |
|||
190 |
2 |
return min_index; |
|
191 |
} |
||
192 |
|||
193 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl> |
||
194 |
inline std::size_t computeDistances(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
||
195 |
const DataTpl<Scalar,Options,JointCollectionTpl> & data, |
||
196 |
const GeometryModel & geom_model, |
||
197 |
GeometryData & geom_data) |
||
198 |
{ |
||
199 |
assert(model.check(data) && "data is not consistent with model."); |
||
200 |
updateGeometryPlacements(model,data,geom_model,geom_data); |
||
201 |
return computeDistances(geom_model,geom_data); |
||
202 |
} |
||
203 |
|||
204 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType> |
||
205 |
1 |
inline std::size_t computeDistances(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
|
206 |
DataTpl<Scalar,Options,JointCollectionTpl> & data, |
||
207 |
const GeometryModel & geom_model, |
||
208 |
GeometryData & geom_data, |
||
209 |
const Eigen::MatrixBase<ConfigVectorType> & q) |
||
210 |
{ |
||
211 |
✓✗ | 1 |
assert(model.check(data) && "data is not consistent with model."); |
212 |
1 |
updateGeometryPlacements(model, data, geom_model, geom_data, q); |
|
213 |
1 |
return computeDistances(geom_model,geom_data); |
|
214 |
} |
||
215 |
|||
216 |
/* --- RADIUS -------------------------------------------------------------------- */ |
||
217 |
/* --- RADIUS -------------------------------------------------------------------- */ |
||
218 |
/* --- RADIUS -------------------------------------------------------------------- */ |
||
219 |
|||
220 |
/// Given p1..3 being either "min" or "max", return one of the corners of the |
||
221 |
/// AABB cub of the FCL object. |
||
222 |
#define PINOCCHIO_GEOM_AABB(FCL,p1,p2,p3) \ |
||
223 |
SE3::Vector3( \ |
||
224 |
FCL->aabb_local.p1##_ [0], \ |
||
225 |
FCL->aabb_local.p2##_ [1], \ |
||
226 |
FCL->aabb_local.p3##_ [2]) |
||
227 |
|||
228 |
/// For all bodies of the model, compute the point of the geometry model |
||
229 |
/// that is the further from the center of the joint. This quantity is used |
||
230 |
/// in some continuous collision test. |
||
231 |
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl> |
||
232 |
1 |
inline void computeBodyRadius(const ModelTpl<Scalar,Options,JointCollectionTpl> & model, |
|
233 |
const GeometryModel & geom_model, |
||
234 |
GeometryData & geom_data) |
||
235 |
{ |
||
236 |
✓✗ | 1 |
geom_data.radius.resize(model.joints.size(),0); |
237 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✓✓✓ ✓✗✓✗ ✓✓✓✗ ✓✗ |
41 |
BOOST_FOREACH(const GeometryObject & geom_object,geom_model.geometryObjects) |
238 |
{ |
||
239 |
20 |
const GeometryObject::CollisionGeometryPtr & geometry |
|
240 |
= geom_object.geometry; |
||
241 |
|||
242 |
// Force computation of the Local AABB |
||
243 |
// TODO: change for a more elegant solution |
||
244 |
✓✗ | 20 |
const_cast<hpp::fcl::CollisionGeometry&>(*geometry).computeLocalAABB(); |
245 |
|||
246 |
20 |
const GeometryModel::SE3 & jMb = geom_object.placement; // placement in joint. |
|
247 |
20 |
const Model::JointIndex i = geom_object.parentJoint; |
|
248 |
✗✓ | 20 |
assert (i<geom_data.radius.size()); |
249 |
|||
250 |
20 |
double radius = geom_data.radius[i] * geom_data.radius[i]; |
|
251 |
|||
252 |
// The radius is simply the one of the 8 corners of the AABB cube, expressed |
||
253 |
// in the joint frame, whose norm is the highest. |
||
254 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,min,min,min)).squaredNorm(),radius); |
255 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,min,min,max)).squaredNorm(),radius); |
256 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,min,max,min)).squaredNorm(),radius); |
257 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,min,max,max)).squaredNorm(),radius); |
258 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,max,min,min)).squaredNorm(),radius); |
259 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,max,min,max)).squaredNorm(),radius); |
260 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,max,max,min)).squaredNorm(),radius); |
261 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
20 |
radius = std::max (jMb.act(PINOCCHIO_GEOM_AABB(geometry,max,max,max)).squaredNorm(),radius); |
262 |
|||
263 |
// Don't forget to sqroot the squared norm before storing it. |
||
264 |
20 |
geom_data.radius[i] = sqrt(radius); |
|
265 |
} |
||
266 |
1 |
} |
|
267 |
|||
268 |
#undef PINOCCHIO_GEOM_AABB |
||
269 |
#endif // PINOCCHIO_WITH_HPP_FCL |
||
270 |
|||
271 |
/* --- APPEND GEOMETRY MODEL ----------------------------------------------------------- */ |
||
272 |
|||
273 |
2 |
inline void appendGeometryModel(GeometryModel & geom_model1, |
|
274 |
const GeometryModel & geom_model2) |
||
275 |
{ |
||
276 |
✗✓ | 2 |
assert (geom_model1.ngeoms == geom_model1.geometryObjects.size()); |
277 |
2 |
Index nGeom1 = geom_model1.geometryObjects.size(); |
|
278 |
2 |
Index nColPairs1 = geom_model1.collisionPairs.size(); |
|
279 |
✗✓ | 2 |
assert (geom_model2.ngeoms == geom_model2.geometryObjects.size()); |
280 |
2 |
Index nGeom2 = geom_model2.geometryObjects.size(); |
|
281 |
2 |
Index nColPairs2 = geom_model2.collisionPairs.size(); |
|
282 |
|||
283 |
/// Append the geometry objects and geometry positions |
||
284 |
2 |
geom_model1.geometryObjects.insert(geom_model1.geometryObjects.end(), |
|
285 |
✓✗ | 4 |
geom_model2.geometryObjects.begin(), geom_model2.geometryObjects.end()); |
286 |
2 |
geom_model1.ngeoms += nGeom2; |
|
287 |
|||
288 |
/// 1. copy the collision pairs and update geom_data1 accordingly. |
||
289 |
2 |
geom_model1.collisionPairs.reserve(nColPairs1 + nColPairs2 + nGeom1 * nGeom2); |
|
290 |
✗✓ | 2 |
for (Index i = 0; i < nColPairs2; ++i) |
291 |
{ |
||
292 |
const CollisionPair& cp = geom_model2.collisionPairs[i]; |
||
293 |
geom_model1.collisionPairs.push_back( |
||
294 |
CollisionPair (cp.first + nGeom1, cp.second + nGeom1) |
||
295 |
); |
||
296 |
} |
||
297 |
|||
298 |
/// 2. add the collision pairs between geom_model1 and geom_model2. |
||
299 |
✓✓ | 22 |
for (Index i = 0; i < nGeom1; ++i) { |
300 |
20 |
Index parent_i = geom_model1.geometryObjects[i].parentJoint; |
|
301 |
✓✓ | 420 |
for (Index j = nGeom1; j < nGeom1 + nGeom2; ++j) { |
302 |
✓✓ | 400 |
if (parent_i != geom_model1.geometryObjects[j].parentJoint) |
303 |
✓✗ | 380 |
geom_model1.collisionPairs.push_back(CollisionPair(i, j)); |
304 |
} |
||
305 |
} |
||
306 |
2 |
} |
|
307 |
|||
308 |
} // namespace pinocchio |
||
309 |
|||
310 |
#endif // ifnded __pinocchio_algo_geometry_hxx__ |
Generated by: GCOVR (Version 4.2) |