Directory: | ./ |
---|---|
File: | src/obstacle-user.cc |
Date: | 2025-03-10 11:18:21 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 30 | 123 | 24.4% |
Branches: | 31 | 226 | 13.7% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2019 CNRS | ||
2 | // Authors: Joseph Mirabel | ||
3 | // | ||
4 | |||
5 | // Redistribution and use in source and binary forms, with or without | ||
6 | // modification, are permitted provided that the following conditions are | ||
7 | // met: | ||
8 | // | ||
9 | // 1. Redistributions of source code must retain the above copyright | ||
10 | // notice, this list of conditions and the following disclaimer. | ||
11 | // | ||
12 | // 2. Redistributions in binary form must reproduce the above copyright | ||
13 | // notice, this list of conditions and the following disclaimer in the | ||
14 | // documentation and/or other materials provided with the distribution. | ||
15 | // | ||
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
20 | // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | ||
27 | // DAMAGE. | ||
28 | |||
29 | #include <coal/collision.h> | ||
30 | |||
31 | #include <hpp/core/obstacle-user.hh> | ||
32 | #include <hpp/pinocchio/body.hh> | ||
33 | #include <hpp/pinocchio/collision-object.hh> | ||
34 | #include <hpp/pinocchio/device.hh> | ||
35 | #include <hpp/util/exception-factory.hh> | ||
36 | #include <pinocchio/multibody/geometry.hpp> | ||
37 | #include <pinocchio/spatial/fcl-pinocchio-conversions.hpp> | ||
38 | |||
39 | namespace hpp { | ||
40 | namespace core { | ||
41 | using ::pinocchio::toFclTransform3f; | ||
42 | 49647 | bool ObstacleUser::collide(const CollisionPairs_t& pairs, | |
43 | CollisionRequests_t& reqs, | ||
44 | coal::CollisionResult& res, std::size_t& i, | ||
45 | pinocchio::DeviceData& data) { | ||
46 |
2/2✓ Branch 1 taken 185552 times.
✓ Branch 2 taken 49540 times.
|
235123 | for (i = 0; i < pairs.size(); ++i) { |
47 | 185552 | res.clear(); | |
48 |
2/2✓ Branch 3 taken 109 times.
✓ Branch 4 taken 185476 times.
|
185869 | if (pairs[i].collide(data, reqs[i], res) != 0) return true; |
49 | } | ||
50 | 49540 | return false; | |
51 | } | ||
52 | |||
53 | 10 | void ObstacleUser::addObstacle(const CollisionObjectConstPtr_t& object) { | |
54 |
3/4✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 10 times.
|
32 | for (size_type j = 0; j < robot_->nbJoints(); ++j) { |
55 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
22 | JointPtr_t joint = robot_->jointAt(j); |
56 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | addObstacleToJoint(object, joint, false); |
57 | 22 | } | |
58 | 10 | } | |
59 | |||
60 | 22 | void ObstacleUser::addObstacleToJoint(const CollisionObjectConstPtr_t& object, | |
61 | const JointPtr_t& joint, | ||
62 | const bool includeChildren) { | ||
63 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
22 | BodyPtr_t body = joint->linkedBody(); |
64 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | if (body) { |
65 |
3/4✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 22 times.
|
44 | for (size_type o = 0; o < body->nbInnerObjects(); ++o) { |
66 | // TODO: check the objects are not in same joint | ||
67 |
3/6✓ Branch 3 taken 22 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 22 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 22 times.
✗ Branch 11 not taken.
|
22 | cPairs_.push_back(CollisionPair_t(body->innerObjectAt(o), object)); |
68 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | cRequests_.push_back(defaultRequest_); |
69 | } | ||
70 | } | ||
71 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (includeChildren) { |
72 | ✗ | for (std::size_t i = 0; i < joint->numberChildJoints(); ++i) { | |
73 | ✗ | addObstacleToJoint(object, joint->childJoint(i), includeChildren); | |
74 | } | ||
75 | } | ||
76 | 22 | } | |
77 | |||
78 | struct CollisionPairComparision { | ||
79 | CollisionPair_t a; | ||
80 | ✗ | CollisionPairComparision(const CollisionPair_t& p) : a(p) {} | |
81 | ✗ | bool operator()(const CollisionPair_t& b) { | |
82 | ✗ | return (&(a.first->pinocchio()) == &(b.first->pinocchio())) && | |
83 | ✗ | (&(a.second->pinocchio()) == &(b.second->pinocchio())); | |
84 | } | ||
85 | }; | ||
86 | |||
87 | ✗ | void ObstacleUser::removeObstacleFromJoint( | |
88 | const JointPtr_t& joint, const CollisionObjectConstPtr_t& obstacle) { | ||
89 | ✗ | BodyPtr_t body = joint->linkedBody(); | |
90 | ✗ | if (body) { | |
91 | ✗ | for (size_type o = 0; o < body->nbInnerObjects(); ++o) { | |
92 | ✗ | CollisionPair_t colPair(body->innerObjectAt(o), obstacle); | |
93 | ✗ | CollisionPairComparision compare(colPair); | |
94 | ✗ | std::size_t nbDelPairs = 0; | |
95 | ✗ | for (std::size_t i = 0; i < cPairs_.size();) { | |
96 | ✗ | if (compare(cPairs_[i])) { | |
97 | ✗ | cPairs_.erase(cPairs_.begin() + i); | |
98 | ✗ | cRequests_.erase(cRequests_.begin() + i); | |
99 | ✗ | ++nbDelPairs; | |
100 | } else | ||
101 | ✗ | ++i; | |
102 | } | ||
103 | ✗ | if (nbDelPairs == 0) { | |
104 | ✗ | std::ostringstream oss; | |
105 | oss << "ObstacleUser::removeObstacleFromJoint: obstacle \"" | ||
106 | ✗ | << obstacle->name() | |
107 | ✗ | << "\" is not registered as obstacle for joint \"" << joint->name() | |
108 | ✗ | << "\"."; | |
109 | ✗ | throw std::runtime_error(oss.str()); | |
110 | ✗ | } else if (nbDelPairs >= 2) { | |
111 | hppDout(error, "obstacle " << obstacle->name() << " was registered " | ||
112 | << nbDelPairs | ||
113 | << " times as obstacle for joint " | ||
114 | << joint->name() << "."); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | ✗ | void ObstacleUser::filterCollisionPairs( | |
121 | const RelativeMotion::matrix_type& matrix) { | ||
122 | // Loop over collision pairs and remove disabled ones. | ||
123 | pinocchio::JointIndex j1, j2; | ||
124 | ✗ | coal::CollisionResult unused; | |
125 | ✗ | for (std::size_t i = 0; i < cPairs_.size();) { | |
126 | ✗ | const CollisionPair_t& pair = cPairs_[i]; | |
127 | |||
128 | ✗ | j1 = pair.first->jointIndex(); | |
129 | ✗ | j2 = pair.second->jointIndex(); | |
130 | |||
131 | ✗ | switch (matrix(j1, j2)) { | |
132 | ✗ | case RelativeMotion::Parameterized: | |
133 | hppDout(info, "Parameterized collision pairs between " | ||
134 | << pair.first->name() << " and " | ||
135 | << pair.second->name()); | ||
136 | ✗ | pPairs_.push_back(pair); | |
137 | ✗ | pRequests_.push_back(cRequests_[i]); | |
138 | ✗ | cPairs_.erase(cPairs_.begin() + i); | |
139 | ✗ | cRequests_.erase(cRequests_.begin() + i); | |
140 | ✗ | break; | |
141 | ✗ | case RelativeMotion::Constrained: | |
142 | hppDout(info, "Disabling collision between " << pair.first->name() | ||
143 | << " and " | ||
144 | << pair.second->name()); | ||
145 | ✗ | if (pair.collide(cRequests_[i], unused) != 0) { | |
146 | hppDout(warning, | ||
147 | "Disabling collision detection between two " | ||
148 | "bodies in collision."); | ||
149 | } | ||
150 | ✗ | dPairs_.push_back(pair); | |
151 | ✗ | dRequests_.push_back(cRequests_[i]); | |
152 | ✗ | cPairs_.erase(cPairs_.begin() + i); | |
153 | ✗ | cRequests_.erase(cRequests_.begin() + i); | |
154 | ✗ | break; | |
155 | ✗ | case RelativeMotion::Unconstrained: | |
156 | ✗ | ++i; | |
157 | ✗ | break; | |
158 | ✗ | default: | |
159 | hppDout(warning, "RelativeMotionType not understood"); | ||
160 | ✗ | ++i; | |
161 | ✗ | break; | |
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | ✗ | void ObstacleUser::setSecurityMargins(const matrix_t& securityMatrix) { | |
167 | ✗ | if (securityMatrix.rows() != robot_->nbJoints() + 1 || | |
168 | ✗ | securityMatrix.cols() != robot_->nbJoints() + 1) { | |
169 | ✗ | HPP_THROW(std::invalid_argument, | |
170 | "Wrong size of security margin matrix." | ||
171 | " Expected " | ||
172 | << robot_->nbJoints() + 1 << 'x' << robot_->nbJoints() + 1 | ||
173 | << ". Got " << securityMatrix.rows() << 'x' | ||
174 | << securityMatrix.cols()); | ||
175 | } | ||
176 | pinocchio::JointIndex j1, j2; | ||
177 | ✗ | coal::CollisionResult unused; | |
178 | ✗ | for (std::size_t i = 0; i < cPairs_.size(); ++i) { | |
179 | ✗ | const CollisionPair_t& pair = cPairs_[i]; | |
180 | ✗ | j1 = pair.first->jointIndex(); | |
181 | ✗ | j2 = pair.second->jointIndex(); | |
182 | ✗ | cRequests_[i].security_margin = securityMatrix(j1, j2); | |
183 | } | ||
184 | ✗ | for (std::size_t i = 0; i < pPairs_.size(); ++i) { | |
185 | ✗ | const CollisionPair_t& pair = pPairs_[i]; | |
186 | ✗ | j1 = pair.first->jointIndex(); | |
187 | ✗ | j2 = pair.second->jointIndex(); | |
188 | ✗ | pRequests_[i].security_margin = securityMatrix(j1, j2); | |
189 | } | ||
190 | ✗ | for (std::size_t i = 0; i < dPairs_.size(); ++i) { | |
191 | ✗ | const CollisionPair_t& pair = dPairs_[i]; | |
192 | ✗ | j1 = pair.first->jointIndex(); | |
193 | ✗ | j2 = pair.second->jointIndex(); | |
194 | ✗ | dRequests_[i].security_margin = securityMatrix(j1, j2); | |
195 | } | ||
196 | } | ||
197 | |||
198 | ✗ | void ObstacleUser::setSecurityMarginBetweenBodies(const std::string& body_a, | |
199 | const std::string& body_b, | ||
200 | const value_type& margin) { | ||
201 | ✗ | auto setMargin = [&body_a, &body_b, &margin](const CollisionPairs_t& pairs, | |
202 | ✗ | CollisionRequests_t& requests) { | |
203 | ✗ | for (std::size_t i = 0; i < pairs.size(); ++i) { | |
204 | ✗ | const CollisionPair_t& pair = pairs[i]; | |
205 | ✗ | if ((pair.first->name() == body_a && pair.second->name() == body_b) || | |
206 | ✗ | (pair.first->name() == body_b && pair.second->name() == body_a)) { | |
207 | ✗ | requests[i].security_margin = margin; | |
208 | ✗ | return true; | |
209 | } | ||
210 | } | ||
211 | ✗ | return false; | |
212 | ✗ | }; | |
213 | ✗ | if (setMargin(cPairs_, cRequests_) || setMargin(pPairs_, pRequests_) || | |
214 | ✗ | setMargin(dPairs_, dRequests_)) | |
215 | ✗ | return; | |
216 | ✗ | throw std::invalid_argument( | |
217 | "Could not find a collision pair between body" | ||
218 | ✗ | " " + | |
219 | ✗ | body_a + " and " + body_b); | |
220 | } | ||
221 | |||
222 | 75 | void ObstacleUser::addRobotCollisionPairs() { | |
223 | 75 | const pinocchio::GeomModel& model = robot_->geomModel(); | |
224 | 75 | const pinocchio::GeomData& data = robot_->geomData(); | |
225 | |||
226 |
2/2✓ Branch 1 taken 5192 times.
✓ Branch 2 taken 75 times.
|
5267 | for (std::size_t i = 0; i < model.collisionPairs.size(); ++i) |
227 |
1/2✓ Branch 1 taken 5192 times.
✗ Branch 2 not taken.
|
5192 | if (data.activeCollisionPairs[i]) { |
228 | CollisionObjectConstPtr_t o1(new pinocchio::CollisionObject( | ||
229 |
3/6✓ Branch 3 taken 5192 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5192 times.
✗ Branch 10 not taken.
|
5192 | robot_, model.collisionPairs[i].first)); |
230 | CollisionObjectConstPtr_t o2(new pinocchio::CollisionObject( | ||
231 |
3/6✓ Branch 3 taken 5192 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 5192 times.
✗ Branch 10 not taken.
|
5192 | robot_, model.collisionPairs[i].second)); |
232 |
2/4✓ Branch 3 taken 5192 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5192 times.
✗ Branch 7 not taken.
|
5192 | cPairs_.push_back(CollisionPair_t(o1, o2)); |
233 |
1/2✓ Branch 1 taken 5192 times.
✗ Branch 2 not taken.
|
5192 | cRequests_.push_back(defaultRequest_); |
234 | 5192 | } | |
235 | 75 | } | |
236 | |||
237 | ✗ | void ObstacleUser::setRequests(const coal::CollisionRequest& r) { | |
238 | ✗ | for (std::size_t i = 0; i < cRequests_.size(); ++i) cRequests_[i] = r; | |
239 | ✗ | for (std::size_t i = 0; i < pRequests_.size(); ++i) pRequests_[i] = r; | |
240 | ✗ | for (std::size_t i = 0; i < dRequests_.size(); ++i) dRequests_[i] = r; | |
241 | } | ||
242 | } // namespace core | ||
243 | } // namespace hpp | ||
244 |