| 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 |