| Directory: | ./ |
|---|---|
| File: | include/hpp/constraints/convex-shape.hh |
| Date: | 2025-05-05 12:19:30 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 111 | 145 | 76.6% |
| Branches: | 94 | 204 | 46.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2015, LAAS-CNRS | ||
| 2 | // Authors: Joseph Mirabel (joseph.mirabel@laas.fr) | ||
| 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 | #ifndef HPP_CONSTRAINTS_CONVEX_SHAPE_HH | ||
| 30 | #define HPP_CONSTRAINTS_CONVEX_SHAPE_HH | ||
| 31 | |||
| 32 | #include <coal/shape/geometric_shapes.h> | ||
| 33 | |||
| 34 | #include <vector> | ||
| 35 | |||
| 36 | // Only for specialization of vector3_t. This is a bad design of Pinocchio. | ||
| 37 | #include <hpp/constraints/config.hh> | ||
| 38 | #include <hpp/constraints/fwd.hh> | ||
| 39 | #include <hpp/pinocchio/joint.hh> | ||
| 40 | #include <pinocchio/multibody/model.hpp> | ||
| 41 | |||
| 42 | namespace hpp { | ||
| 43 | namespace constraints { | ||
| 44 | /// Return the closest point to point P, on a segment line \f$ A + t*v, t \in | ||
| 45 | /// [0,1] \f$. \param P PA where P is the point to \param A the origin the | ||
| 46 | /// segment line \param v vector presenting the segment line \param[out] B the | ||
| 47 | /// closest point | ||
| 48 | inline void closestPointToSegment(const vector3_t& P, const vector3_t& A, | ||
| 49 | const vector3_t& v, vector3_t& B) { | ||
| 50 | vector3_t w = A - P; | ||
| 51 | value_type c1, c2; | ||
| 52 | c1 = v.dot(w); | ||
| 53 | c2 = v.dot(v); | ||
| 54 | if (c1 <= 0) | ||
| 55 | B = A; | ||
| 56 | else if (c2 <= c1) | ||
| 57 | B = A + v; | ||
| 58 | else | ||
| 59 | B = A + c1 / c2 * v; | ||
| 60 | } | ||
| 61 | |||
| 62 | /// \param A, u point and vector defining the line \f$ A + t*u \f$ | ||
| 63 | /// \param P, n point and normal vector defining the plane \f$ Q \in plane | ||
| 64 | /// \Rightleftarrow (P - Q) . n = 0 \f$ \return the intesection point. \warning | ||
| 65 | /// \c u and \c n are expected not to be orthogonal. \todo make this function | ||
| 66 | /// robust to orthogonal inputs. | ||
| 67 | 152329 | inline vector3_t linePlaneIntersection(const vector3_t& A, const vector3_t& u, | |
| 68 | const vector3_t& P, const vector3_t& n) { | ||
| 69 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 152334 times.
|
152329 | assert(std::abs(n.dot(u)) > 1e-8); |
| 70 |
6/12✓ Branch 2 taken 152339 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 152328 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 152337 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 152336 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 152339 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 152330 times.
✗ Branch 18 not taken.
|
304664 | return A + u * (n.dot(P - A)) / n.dot(u); |
| 71 | } | ||
| 72 | |||
| 73 | class HPP_CONSTRAINTS_DLLAPI ConvexShape { | ||
| 74 | public: | ||
| 75 | /// Represent a convex shape | ||
| 76 | /// \param pts a sequence of points lying in a plane. The convex shape is | ||
| 77 | /// obtained by connecting consecutive points (in a circular way) | ||
| 78 | /// | ||
| 79 | /// \note There is no convexity check yet. The order is important: | ||
| 80 | /// The normal is parallel to (pts[1] - pts[0]).cross (pts[2] - pts[1]) | ||
| 81 | /// The normal to the segment in the plane are directed outward. | ||
| 82 | /// (pts[i+1] - pts[i]).cross (normalToConvexShape) | ||
| 83 | 26 | ConvexShape(const std::vector<vector3_t>& pts, | |
| 84 | JointPtr_t joint = JointPtr_t()) | ||
| 85 |
4/8✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 26 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 26 times.
✗ Branch 14 not taken.
|
26 | : Pts_(pts), joint_(joint) { |
| 86 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | init(); |
| 87 | 26 | } | |
| 88 | |||
| 89 | ConvexShape(const coal::TriangleP& t, const JointPtr_t& joint = JointPtr_t()) | ||
| 90 | : Pts_(triangleToPoints(t)), joint_(joint) { | ||
| 91 | init(); | ||
| 92 | } | ||
| 93 | |||
| 94 | /// This constructor is required for compatibility with deprecated | ||
| 95 | /// Triangle constructor. | ||
| 96 | 1 | ConvexShape(const vector3_t& p0, const vector3_t& p1, const vector3_t& p2, | |
| 97 | const JointPtr_t& joint = JointPtr_t()) | ||
| 98 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
1 | : Pts_(points(p0, p1, p2)), joint_(joint) { |
| 99 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | init(); |
| 100 | 1 | } | |
| 101 | |||
| 102 | // Copy constructor | ||
| 103 |
5/10✓ Branch 2 taken 38601 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38601 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 38601 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 38600 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 38600 times.
✗ Branch 18 not taken.
|
38594 | ConvexShape(const ConvexShape& t) : Pts_(t.Pts_), joint_(t.joint_) { init(); } |
| 104 | |||
| 105 | 14 | void reverse() { | |
| 106 | 14 | std::reverse(Pts_.begin(), Pts_.end()); | |
| 107 | 14 | init(); | |
| 108 | 14 | } | |
| 109 | |||
| 110 | /// Intersection with a line defined by a point and a vector. | ||
| 111 | /// \param A, u point and vector expressed in the local frame. | ||
| 112 | inline vector3_t intersectionLocal(const vector3_t& A, | ||
| 113 | const vector3_t& u) const { | ||
| 114 | return linePlaneIntersection(A, u, C_, N_); | ||
| 115 | } | ||
| 116 | |||
| 117 | /// As isInside but consider A as expressed in joint frame. | ||
| 118 | 23 | inline bool isInsideLocal(const vector3_t& Ap) const { | |
| 119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | assert(shapeDimension_ > 2); |
| 120 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 16 times.
|
76 | for (std::size_t i = 0; i < shapeDimension_; ++i) { |
| 121 |
3/4✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✓ Branch 7 taken 53 times.
|
60 | if (Ns_[i].dot(Ap - Pts_[i]) > 0) return false; |
| 122 | } | ||
| 123 | 16 | return true; | |
| 124 | } | ||
| 125 | |||
| 126 | /// Return the shortest distance from a point to the shape | ||
| 127 | /// A negative value means the point is inside the shape | ||
| 128 | /// \param a a point already in the plane containing the convex shape, | ||
| 129 | /// and expressed in the local frame. | ||
| 130 | 152370 | inline value_type distanceLocal(const vector3_t& a) const { | |
| 131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 152370 times.
|
152370 | assert(shapeDimension_ > 1); |
| 132 | 152370 | const value_type inf = std::numeric_limits<value_type>::infinity(); | |
| 133 | 152370 | value_type minPosDist = inf, maxNegDist = -inf; | |
| 134 | 152370 | bool outside = false; | |
| 135 |
2/2✓ Branch 0 taken 610420 times.
✓ Branch 1 taken 152381 times.
|
762801 | for (std::size_t i = 0; i < shapeDimension_; ++i) { |
| 136 |
2/4✓ Branch 6 taken 610432 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 610431 times.
✗ Branch 10 not taken.
|
610420 | value_type d = dist(a - Pts_[i], Ls_[i], Us_[i], Ns_[i]); |
| 137 |
2/2✓ Branch 0 taken 97986 times.
✓ Branch 1 taken 512445 times.
|
610431 | if (d > 0) { |
| 138 | 97986 | outside = true; | |
| 139 |
2/2✓ Branch 0 taken 87129 times.
✓ Branch 1 taken 10857 times.
|
97986 | if (d < minPosDist) minPosDist = d; |
| 140 | } | ||
| 141 |
4/4✓ Branch 0 taken 512443 times.
✓ Branch 1 taken 97988 times.
✓ Branch 2 taken 307399 times.
✓ Branch 3 taken 205044 times.
|
610431 | if (d <= 0 && d > maxNegDist) maxNegDist = d; |
| 142 | } | ||
| 143 |
2/2✓ Branch 0 taken 86415 times.
✓ Branch 1 taken 65966 times.
|
152381 | if (outside) return minPosDist; |
| 144 | 65966 | return maxNegDist; | |
| 145 | } | ||
| 146 | |||
| 147 | /// Return the X axis of the plane in the joint frame | ||
| 148 | 2 | inline const vector3_t& planeXaxis() const { | |
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(shapeDimension_ > 2); |
| 150 | 2 | return Ns_[0]; | |
| 151 | } | ||
| 152 | /// Return the Y axis of the plane in the joint frame | ||
| 153 | /// The Y axis is aligned with \f$ Pts_[1] - Pts_[0] \f$ | ||
| 154 | 2 | inline const vector3_t& planeYaxis() const { | |
| 155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | assert(shapeDimension_ > 2); |
| 156 | 2 | return Us_[0]; | |
| 157 | } | ||
| 158 | |||
| 159 | /// Transform of the shape in the joint frame | ||
| 160 | 77112 | inline const Transform3s& positionInJoint() const { return MinJoint_; } | |
| 161 | |||
| 162 | ✗ | bool operator==(ConvexShape const& other) const { | |
| 163 | ✗ | if (Pts_ != other.Pts_) return false; | |
| 164 | ✗ | if (shapeDimension_ != other.shapeDimension_) return false; | |
| 165 | ✗ | if (C_ != other.C_) return false; | |
| 166 | ✗ | if (N_ != other.N_) return false; | |
| 167 | ✗ | if (Ns_ != other.Ns_) return false; | |
| 168 | ✗ | if (Us_ != other.Us_) return false; | |
| 169 | ✗ | if (Ls_ != other.Ls_) return false; | |
| 170 | ✗ | if (MinJoint_ != other.MinJoint_) return false; | |
| 171 | ✗ | if (joint_ != other.joint_) return false; | |
| 172 | ✗ | return true; | |
| 173 | } | ||
| 174 | ✗ | bool operator!=(ConvexShape const& other) const { | |
| 175 | ✗ | return !(this->operator==(other)); | |
| 176 | } | ||
| 177 | |||
| 178 | /// The points in the joint frame. It is constant. | ||
| 179 | std::vector<vector3_t> Pts_; | ||
| 180 | size_t shapeDimension_; | ||
| 181 | /// the center in the joint frame. It is constant. | ||
| 182 | vector3_t C_; | ||
| 183 | /// the normal to the shape in the joint frame. It is constant. | ||
| 184 | vector3_t N_; | ||
| 185 | /// Ns_ and Us_ are unit vector, in the plane containing the shape, | ||
| 186 | /// expressed in the joint frame. | ||
| 187 | /// Ns_[i] is normal to edge i, pointing inside. | ||
| 188 | /// Ns_[i] is a vector director of edge i. | ||
| 189 | std::vector<vector3_t> Ns_, Us_; | ||
| 190 | vector_t Ls_; | ||
| 191 | Transform3s MinJoint_; | ||
| 192 | JointPtr_t joint_; | ||
| 193 | |||
| 194 | private: | ||
| 195 | /// Return the distance between the point A and the segment | ||
| 196 | /// [P, c2*v] oriented by u. | ||
| 197 | /// w = PA. | ||
| 198 | 610427 | inline value_type dist(const vector3_t& w, const value_type& c2, | |
| 199 | const vector3_t& v, const vector3_t& u) const { | ||
| 200 | value_type c1; | ||
| 201 | 610427 | c1 = v.dot(w); | |
| 202 |
4/4✓ Branch 0 taken 98146 times.
✓ Branch 1 taken 512288 times.
✓ Branch 3 taken 11569 times.
✓ Branch 4 taken 86576 times.
|
610434 | if (c1 <= 0) return (u.dot(w) > 0) ? (w.norm()) : (-w.norm()); |
| 203 |
2/2✓ Branch 0 taken 98736 times.
✓ Branch 1 taken 413552 times.
|
512288 | if (c2 <= c1) |
| 204 | // TODO: (w - c2 * v).norm() == sqrt((u.dot(w)**2 + (c1 - c2)**2) | ||
| 205 | // second should be cheaper. | ||
| 206 |
8/14✓ Branch 1 taken 11569 times.
✓ Branch 2 taken 87169 times.
✓ Branch 4 taken 11569 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11569 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11569 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 87168 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 87168 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 87159 times.
✗ Branch 20 not taken.
|
98736 | return (u.dot(w) > 0) ? ((w - c2 * v).norm()) : (-(w - c2 * v).norm()); |
| 207 | 413552 | return u.dot(w); | |
| 208 | } | ||
| 209 | |||
| 210 | static std::vector<vector3_t> triangleToPoints(const coal::TriangleP& t) { | ||
| 211 | // TODO | ||
| 212 | // return points (t.a, t.b, t.c); | ||
| 213 | std::vector<vector3_t> ret(3); | ||
| 214 | ret[0] = t.a; | ||
| 215 | ret[1] = t.b; | ||
| 216 | ret[2] = t.c; | ||
| 217 | return ret; | ||
| 218 | } | ||
| 219 | 1 | static std::vector<vector3_t> points(const vector3_t& p0, const vector3_t& p1, | |
| 220 | const vector3_t& p2) { | ||
| 221 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<vector3_t> ret(3); |
| 222 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ret[0] = p0; |
| 223 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ret[1] = p1; |
| 224 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | ret[2] = p2; |
| 225 | 1 | return ret; | |
| 226 | } | ||
| 227 | |||
| 228 | 38642 | void init() { | |
| 229 | 38642 | shapeDimension_ = Pts_.size(); | |
| 230 | |||
| 231 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38638 times.
|
38642 | switch (shapeDimension_) { |
| 232 | ✗ | case 0: | |
| 233 | ✗ | throw std::logic_error("Cannot represent an empty shape."); | |
| 234 | break; | ||
| 235 | 4 | case 1: | |
| 236 | 4 | C_ = Pts_[0]; | |
| 237 | // The transformation will be (N_, Ns_[0], Us_[0]) | ||
| 238 | // Fill vectors so as to be consistent | ||
| 239 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | N_ = vector3_t(1, 0, 0); |
| 240 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | Ns_.push_back(vector3_t(0, 1, 0)); |
| 241 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | Us_.push_back(vector3_t(0, 0, 1)); |
| 242 | 4 | break; | |
| 243 | ✗ | case 2: | |
| 244 | ✗ | Ls_ = vector_t(1); | |
| 245 | ✗ | C_ = (Pts_[0] + Pts_[1]) / 2; | |
| 246 | // The transformation will be (N_, Ns_[0], Us_[0]) | ||
| 247 | // Fill vectors so as to be consistent | ||
| 248 | ✗ | Us_.push_back(Pts_[1] - Pts_[0]); | |
| 249 | ✗ | Ls_[0] = Us_[0].norm(); | |
| 250 | ✗ | Us_[0].normalize(); | |
| 251 | ✗ | if (Us_[0][0] != 0) | |
| 252 | ✗ | N_ = vector3_t(-Us_[0][1], Us_[0][0], 0); | |
| 253 | else | ||
| 254 | ✗ | N_ = vector3_t(0, -Us_[0][2], Us_[0][1]); | |
| 255 | ✗ | N_.normalize(); | |
| 256 | ✗ | Ns_.push_back(Us_[0].cross(N_)); | |
| 257 | ✗ | Ns_[0].normalize(); // Should be unnecessary | |
| 258 | ✗ | break; | |
| 259 | 38638 | default: | |
| 260 | 38638 | Ls_ = vector_t(shapeDimension_); | |
| 261 | 38638 | C_.setZero(); | |
| 262 |
2/2✓ Branch 2 taken 155312 times.
✓ Branch 3 taken 38638 times.
|
193950 | for (std::size_t i = 0; i < shapeDimension_; ++i) C_ += Pts_[i]; |
| 263 | // TODO This is very ugly. Why Eigen does not have the operator/=(int) | ||
| 264 | // ... | ||
| 265 |
1/2✓ Branch 2 taken 38638 times.
✗ Branch 3 not taken.
|
38638 | C_ /= (value_type)Pts_.size(); |
| 266 |
2/4✓ Branch 6 taken 38638 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 38638 times.
✗ Branch 10 not taken.
|
38638 | N_ = (Pts_[1] - Pts_[0]).cross(Pts_[2] - Pts_[1]); |
| 267 |
2/4✓ Branch 2 taken 38638 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38638 times.
|
38638 | assert(!N_.isZero()); |
| 268 | 38638 | N_.normalize(); | |
| 269 | |||
| 270 | 38638 | Us_.resize(Pts_.size()); | |
| 271 | 38638 | Ns_.resize(Pts_.size()); | |
| 272 |
2/2✓ Branch 0 taken 155312 times.
✓ Branch 1 taken 38638 times.
|
193950 | for (std::size_t i = 0; i < shapeDimension_; ++i) { |
| 273 |
1/2✓ Branch 5 taken 155312 times.
✗ Branch 6 not taken.
|
155312 | Us_[i] = Pts_[(i + 1) % shapeDimension_] - Pts_[i]; |
| 274 | 155312 | Ls_[i] = Us_[i].norm(); | |
| 275 | 155312 | Us_[i].normalize(); | |
| 276 | 155312 | Ns_[i] = Us_[i].cross(N_); | |
| 277 | 155312 | Ns_[i].normalize(); | |
| 278 | } | ||
| 279 |
2/2✓ Branch 0 taken 155312 times.
✓ Branch 1 taken 38638 times.
|
193950 | for (std::size_t i = 0; i < shapeDimension_; ++i) { |
| 280 |
1/2✓ Branch 3 taken 155312 times.
✗ Branch 4 not taken.
|
155312 | assert(Us_[(i + 1) % shapeDimension_].dot(Ns_[i]) < 0 && |
| 281 | "The sequence does not define a convex surface"); | ||
| 282 | } | ||
| 283 | 38638 | break; | |
| 284 | } | ||
| 285 | |||
| 286 | 38642 | MinJoint_.translation() = C_; | |
| 287 |
1/2✓ Branch 3 taken 38642 times.
✗ Branch 4 not taken.
|
38642 | MinJoint_.rotation().col(0) = N_; |
| 288 |
1/2✓ Branch 4 taken 38642 times.
✗ Branch 5 not taken.
|
38642 | MinJoint_.rotation().col(1) = Ns_[0]; |
| 289 |
1/2✓ Branch 4 taken 38642 times.
✗ Branch 5 not taken.
|
38642 | MinJoint_.rotation().col(2) = Us_[0]; |
| 290 | 38642 | } | |
| 291 | }; | ||
| 292 | |||
| 293 | struct HPP_CONSTRAINTS_DLLAPI ConvexShapeData { | ||
| 294 | // normal in the world frame | ||
| 295 | vector3_t normal_; | ||
| 296 | // center in the world frame | ||
| 297 | vector3_t center_; | ||
| 298 | // Current joint position | ||
| 299 | Transform3s oMj_; | ||
| 300 | |||
| 301 | /// Compute center and normal in world frame | ||
| 302 | 6 | inline void updateToCurrentTransform(const ConvexShape& cs) { | |
| 303 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if (cs.joint_ == NULL) { |
| 304 | 6 | oMj_.setIdentity(); | |
| 305 | 6 | _recompute<true>(cs); | |
| 306 | } else { | ||
| 307 | ✗ | oMj_ = cs.joint_->currentTransformation(); | |
| 308 | ✗ | _recompute<false>(cs); | |
| 309 | } | ||
| 310 | 6 | } | |
| 311 | |||
| 312 | /// Compute center and normal in world frame | ||
| 313 | /// Thread safe version. | ||
| 314 | 229432 | inline void updateToCurrentTransform(const ConvexShape& cs, | |
| 315 | const pinocchio::DeviceData& d) { | ||
| 316 |
2/2✓ Branch 1 taken 1879 times.
✓ Branch 2 taken 227553 times.
|
229432 | if (cs.joint_ == NULL) { |
| 317 | 1879 | oMj_.setIdentity(); | |
| 318 | 1885 | _recompute<true>(cs); | |
| 319 | } else { | ||
| 320 | 227553 | oMj_ = cs.joint_->currentTransformation(d); | |
| 321 | 227561 | _recompute<false>(cs); | |
| 322 | } | ||
| 323 | 229439 | } | |
| 324 | |||
| 325 | template <bool WorldFrame> | ||
| 326 | 458884 | inline void _recompute(const ConvexShape& cs) { | |
| 327 | if (WorldFrame) { | ||
| 328 | 3768 | center_ = cs.C_; | |
| 329 | 3788 | normal_ = cs.N_; | |
| 330 | } else { | ||
| 331 | 455116 | center_ = oMj_.act(cs.C_); | |
| 332 |
1/2✓ Branch 3 taken 227556 times.
✗ Branch 4 not taken.
|
455124 | normal_ = oMj_.rotation() * cs.N_; |
| 333 | } | ||
| 334 | 458900 | } | |
| 335 | |||
| 336 | /// Intersection with a line defined by a point and a vector. | ||
| 337 | /// \param A, u point and vector expressed in the world frame. | ||
| 338 | 152327 | inline vector3_t intersection(const vector3_t& A, const vector3_t& u) const { | |
| 339 | 152327 | return linePlaneIntersection(A, u, center_, normal_); | |
| 340 | } | ||
| 341 | |||
| 342 | /// Check whether the intersection of the line defined by A and u | ||
| 343 | /// onto the plane containing the triangle is inside the triangle. | ||
| 344 | /// \param A, u point and vector in world frame defining the line \f$ A + t*u | ||
| 345 | /// \f$ | ||
| 346 | ✗ | inline bool isInside(const ConvexShape& cs, const vector3_t& A, | |
| 347 | const vector3_t& u) const { | ||
| 348 | ✗ | return isInside(cs, intersection(A, u)); | |
| 349 | } | ||
| 350 | /// Check whether the point As in world frame is inside the triangle. | ||
| 351 | 18 | inline bool isInside(const ConvexShape& cs, const vector3_t& Ap) const { | |
| 352 |
2/4✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | if (cs.joint_ == NULL) return cs.isInsideLocal(Ap); |
| 353 | ✗ | vector3_t Ap_loc = oMj_.actInv(Ap); | |
| 354 | ✗ | return cs.isInsideLocal(Ap_loc); | |
| 355 | } | ||
| 356 | |||
| 357 | /// \param yaxis vector in world frame to which we should try to align | ||
| 358 | inline Transform3s alignedPositionInJoint(const ConvexShape& cs, | ||
| 359 | vector3_t yaxis) const { | ||
| 360 | assert(cs.shapeDimension_ > 2); | ||
| 361 | // Project vector onto the plane | ||
| 362 | yaxis = oMj_.actInv(yaxis); | ||
| 363 | vector3_t yproj = yaxis - yaxis.dot(cs.N_) * cs.N_; | ||
| 364 | if (yproj.isZero()) | ||
| 365 | return cs.MinJoint_; | ||
| 366 | else { | ||
| 367 | Transform3s M; | ||
| 368 | M.translation() = cs.C_; | ||
| 369 | M.rotation().col(0) = cs.N_; | ||
| 370 | M.rotation().col(1) = yaxis; | ||
| 371 | M.rotation().col(2) = cs.N_.cross(yaxis); | ||
| 372 | return M; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | /// See ConvexShape::distanceLocal | ||
| 377 | /// \param a a point already in the plane containing the convex shape, | ||
| 378 | /// and expressed in the global frame. | ||
| 379 | 152368 | inline value_type distance(const ConvexShape& cs, vector3_t a) const { | |
| 380 |
2/2✓ Branch 1 taken 150448 times.
✓ Branch 2 taken 1917 times.
|
152368 | if (cs.joint_ != NULL) a = oMj_.actInv(a); |
| 381 | 152365 | return cs.distanceLocal(a); | |
| 382 | } | ||
| 383 | }; | ||
| 384 | } // namespace constraints | ||
| 385 | } // namespace hpp | ||
| 386 | |||
| 387 | #endif // HPP_CONSTRAINTS_CONVEX_SHAPE_HH | ||
| 388 |