hpp-constraints  6.1.0
Definition of basic geometric constraints for motion planning
convex-shape.hh
Go to the documentation of this file.
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 // clang-format off
33 #include <pinocchio/multibody/model.hpp>
34 // clang-format on
35 
36 #include <coal/shape/geometric_shapes.h>
37 
38 #include <vector>
39 
40 // Only for specialization of vector3_t. This is a bad design of Pinocchio.
42 #include <hpp/constraints/fwd.hh>
43 #include <hpp/pinocchio/joint.hh>
44 
45 namespace hpp {
46 namespace constraints {
51 inline void closestPointToSegment(const vector3_t& P, const vector3_t& A,
52  const vector3_t& v, vector3_t& B) {
53  vector3_t w = A - P;
54  value_type c1, c2;
55  c1 = v.dot(w);
56  c2 = v.dot(v);
57  if (c1 <= 0)
58  B = A;
59  else if (c2 <= c1)
60  B = A + v;
61  else
62  B = A + c1 / c2 * v;
63 }
64 
71  const vector3_t& P, const vector3_t& n) {
72  assert(std::abs(n.dot(u)) > 1e-8);
73  return A + u * (n.dot(P - A)) / n.dot(u);
74 }
75 
77  public:
86  ConvexShape(const std::vector<vector3_t>& pts,
87  JointPtr_t joint = JointPtr_t())
88  : Pts_(pts), joint_(joint) {
89  init();
90  }
91 
92  ConvexShape(const coal::TriangleP& t, const JointPtr_t& joint = JointPtr_t())
93  : Pts_(triangleToPoints(t)), joint_(joint) {
94  init();
95  }
96 
99  ConvexShape(const vector3_t& p0, const vector3_t& p1, const vector3_t& p2,
100  const JointPtr_t& joint = JointPtr_t())
101  : Pts_(points(p0, p1, p2)), joint_(joint) {
102  init();
103  }
104 
105  // Copy constructor
106  ConvexShape(const ConvexShape& t) : Pts_(t.Pts_), joint_(t.joint_) { init(); }
107 
108  void reverse() {
109  std::reverse(Pts_.begin(), Pts_.end());
110  init();
111  }
112 
116  const vector3_t& u) const {
117  return linePlaneIntersection(A, u, C_, N_);
118  }
119 
121  inline bool isInsideLocal(const vector3_t& Ap) const {
122  assert(shapeDimension_ > 2);
123  for (std::size_t i = 0; i < shapeDimension_; ++i) {
124  if (Ns_[i].dot(Ap - Pts_[i]) > 0) return false;
125  }
126  return true;
127  }
128 
133  inline value_type distanceLocal(const vector3_t& a) const {
134  assert(shapeDimension_ > 1);
135  const value_type inf = std::numeric_limits<value_type>::infinity();
136  value_type minPosDist = inf, maxNegDist = -inf;
137  bool outside = false;
138  for (std::size_t i = 0; i < shapeDimension_; ++i) {
139  value_type d = dist(a - Pts_[i], Ls_[i], Us_[i], Ns_[i]);
140  if (d > 0) {
141  outside = true;
142  if (d < minPosDist) minPosDist = d;
143  }
144  if (d <= 0 && d > maxNegDist) maxNegDist = d;
145  }
146  if (outside) return minPosDist;
147  return maxNegDist;
148  }
149 
151  inline const vector3_t& planeXaxis() const {
152  assert(shapeDimension_ > 2);
153  return Ns_[0];
154  }
157  inline const vector3_t& planeYaxis() const {
158  assert(shapeDimension_ > 2);
159  return Us_[0];
160  }
161 
163  inline const Transform3s& positionInJoint() const { return MinJoint_; }
164 
165  bool operator==(ConvexShape const& other) const {
166  if (Pts_ != other.Pts_) return false;
167  if (shapeDimension_ != other.shapeDimension_) return false;
168  if (C_ != other.C_) return false;
169  if (N_ != other.N_) return false;
170  if (Ns_ != other.Ns_) return false;
171  if (Us_ != other.Us_) return false;
172  if (Ls_ != other.Ls_) return false;
173  if (MinJoint_ != other.MinJoint_) return false;
174  if (joint_ != other.joint_) return false;
175  return true;
176  }
177  bool operator!=(ConvexShape const& other) const {
178  return !(this->operator==(other));
179  }
180 
182  std::vector<vector3_t> Pts_;
192  std::vector<vector3_t> Ns_, Us_;
196 
197  private:
201  inline value_type dist(const vector3_t& w, const value_type& c2,
202  const vector3_t& v, const vector3_t& u) const {
203  value_type c1;
204  c1 = v.dot(w);
205  if (c1 <= 0) return (u.dot(w) > 0) ? (w.norm()) : (-w.norm());
206  if (c2 <= c1)
207  // TODO: (w - c2 * v).norm() == sqrt((u.dot(w)**2 + (c1 - c2)**2)
208  // second should be cheaper.
209  return (u.dot(w) > 0) ? ((w - c2 * v).norm()) : (-(w - c2 * v).norm());
210  return u.dot(w);
211  }
212 
213  static std::vector<vector3_t> triangleToPoints(const coal::TriangleP& t) {
214  // TODO
215  // return points (t.a, t.b, t.c);
216  std::vector<vector3_t> ret(3);
217  ret[0] = t.a;
218  ret[1] = t.b;
219  ret[2] = t.c;
220  return ret;
221  }
222  static std::vector<vector3_t> points(const vector3_t& p0, const vector3_t& p1,
223  const vector3_t& p2) {
224  std::vector<vector3_t> ret(3);
225  ret[0] = p0;
226  ret[1] = p1;
227  ret[2] = p2;
228  return ret;
229  }
230 
231  void init() {
232  shapeDimension_ = Pts_.size();
233 
234  switch (shapeDimension_) {
235  case 0:
236  throw std::logic_error("Cannot represent an empty shape.");
237  break;
238  case 1:
239  C_ = Pts_[0];
240  // The transformation will be (N_, Ns_[0], Us_[0])
241  // Fill vectors so as to be consistent
242  N_ = vector3_t(1, 0, 0);
243  Ns_.push_back(vector3_t(0, 1, 0));
244  Us_.push_back(vector3_t(0, 0, 1));
245  break;
246  case 2:
247  Ls_ = vector_t(1);
248  C_ = (Pts_[0] + Pts_[1]) / 2;
249  // The transformation will be (N_, Ns_[0], Us_[0])
250  // Fill vectors so as to be consistent
251  Us_.push_back(Pts_[1] - Pts_[0]);
252  Ls_[0] = Us_[0].norm();
253  Us_[0].normalize();
254  if (Us_[0][0] != 0)
255  N_ = vector3_t(-Us_[0][1], Us_[0][0], 0);
256  else
257  N_ = vector3_t(0, -Us_[0][2], Us_[0][1]);
258  N_.normalize();
259  Ns_.push_back(Us_[0].cross(N_));
260  Ns_[0].normalize(); // Should be unnecessary
261  break;
262  default:
263  Ls_ = vector_t(shapeDimension_);
264  C_.setZero();
265  for (std::size_t i = 0; i < shapeDimension_; ++i) C_ += Pts_[i];
266  // TODO This is very ugly. Why Eigen does not have the operator/=(int)
267  // ...
268  C_ /= (value_type)Pts_.size();
269  N_ = (Pts_[1] - Pts_[0]).cross(Pts_[2] - Pts_[1]);
270  assert(!N_.isZero());
271  N_.normalize();
272 
273  Us_.resize(Pts_.size());
274  Ns_.resize(Pts_.size());
275  for (std::size_t i = 0; i < shapeDimension_; ++i) {
276  Us_[i] = Pts_[(i + 1) % shapeDimension_] - Pts_[i];
277  Ls_[i] = Us_[i].norm();
278  Us_[i].normalize();
279  Ns_[i] = Us_[i].cross(N_);
280  Ns_[i].normalize();
281  }
282  for (std::size_t i = 0; i < shapeDimension_; ++i) {
283  assert(Us_[(i + 1) % shapeDimension_].dot(Ns_[i]) < 0 &&
284  "The sequence does not define a convex surface");
285  }
286  break;
287  }
288 
289  MinJoint_.translation() = C_;
290  MinJoint_.rotation().col(0) = N_;
291  MinJoint_.rotation().col(1) = Ns_[0];
292  MinJoint_.rotation().col(2) = Us_[0];
293  }
294 };
295 
297  // normal in the world frame
299  // center in the world frame
301  // Current joint position
303 
305  inline void updateToCurrentTransform(const ConvexShape& cs) {
306  if (cs.joint_ == NULL) {
307  oMj_.setIdentity();
308  _recompute<true>(cs);
309  } else {
310  oMj_ = cs.joint_->currentTransformation();
311  _recompute<false>(cs);
312  }
313  }
314 
317  inline void updateToCurrentTransform(const ConvexShape& cs,
318  const pinocchio::DeviceData& d) {
319  if (cs.joint_ == NULL) {
320  oMj_.setIdentity();
321  _recompute<true>(cs);
322  } else {
323  oMj_ = cs.joint_->currentTransformation(d);
324  _recompute<false>(cs);
325  }
326  }
327 
328  template <bool WorldFrame>
329  inline void _recompute(const ConvexShape& cs) {
330  if (WorldFrame) {
331  center_ = cs.C_;
332  normal_ = cs.N_;
333  } else {
334  center_ = oMj_.act(cs.C_);
335  normal_ = oMj_.rotation() * cs.N_;
336  }
337  }
338 
341  inline vector3_t intersection(const vector3_t& A, const vector3_t& u) const {
342  return linePlaneIntersection(A, u, center_, normal_);
343  }
344 
349  inline bool isInside(const ConvexShape& cs, const vector3_t& A,
350  const vector3_t& u) const {
351  return isInside(cs, intersection(A, u));
352  }
354  inline bool isInside(const ConvexShape& cs, const vector3_t& Ap) const {
355  if (cs.joint_ == NULL) return cs.isInsideLocal(Ap);
356  vector3_t Ap_loc = oMj_.actInv(Ap);
357  return cs.isInsideLocal(Ap_loc);
358  }
359 
362  vector3_t yaxis) const {
363  assert(cs.shapeDimension_ > 2);
364  // Project vector onto the plane
365  yaxis = oMj_.actInv(yaxis);
366  vector3_t yproj = yaxis - yaxis.dot(cs.N_) * cs.N_;
367  if (yproj.isZero())
368  return cs.MinJoint_;
369  else {
370  Transform3s M;
371  M.translation() = cs.C_;
372  M.rotation().col(0) = cs.N_;
373  M.rotation().col(1) = yaxis;
374  M.rotation().col(2) = cs.N_.cross(yaxis);
375  return M;
376  }
377  }
378 
382  inline value_type distance(const ConvexShape& cs, vector3_t a) const {
383  if (cs.joint_ != NULL) a = oMj_.actInv(a);
384  return cs.distanceLocal(a);
385  }
386 };
387 } // namespace constraints
388 } // namespace hpp
389 
390 #endif // HPP_CONSTRAINTS_CONVEX_SHAPE_HH
Definition: convex-shape.hh:76
ConvexShape(const std::vector< vector3_t > &pts, JointPtr_t joint=JointPtr_t())
Definition: convex-shape.hh:86
Transform3s MinJoint_
Definition: convex-shape.hh:194
ConvexShape(const vector3_t &p0, const vector3_t &p1, const vector3_t &p2, const JointPtr_t &joint=JointPtr_t())
Definition: convex-shape.hh:99
const vector3_t & planeYaxis() const
Definition: convex-shape.hh:157
bool operator!=(ConvexShape const &other) const
Definition: convex-shape.hh:177
vector3_t C_
the center in the joint frame. It is constant.
Definition: convex-shape.hh:185
std::vector< vector3_t > Us_
Definition: convex-shape.hh:192
std::vector< vector3_t > Pts_
The points in the joint frame. It is constant.
Definition: convex-shape.hh:182
bool operator==(ConvexShape const &other) const
Definition: convex-shape.hh:165
ConvexShape(const ConvexShape &t)
Definition: convex-shape.hh:106
bool isInsideLocal(const vector3_t &Ap) const
As isInside but consider A as expressed in joint frame.
Definition: convex-shape.hh:121
const Transform3s & positionInJoint() const
Transform of the shape in the joint frame.
Definition: convex-shape.hh:163
void reverse()
Definition: convex-shape.hh:108
vector3_t N_
the normal to the shape in the joint frame. It is constant.
Definition: convex-shape.hh:187
const vector3_t & planeXaxis() const
Return the X axis of the plane in the joint frame.
Definition: convex-shape.hh:151
value_type distanceLocal(const vector3_t &a) const
Definition: convex-shape.hh:133
vector_t Ls_
Definition: convex-shape.hh:193
std::vector< vector3_t > Ns_
Definition: convex-shape.hh:192
ConvexShape(const coal::TriangleP &t, const JointPtr_t &joint=JointPtr_t())
Definition: convex-shape.hh:92
vector3_t intersectionLocal(const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:115
JointPtr_t joint_
Definition: convex-shape.hh:195
size_t shapeDimension_
Definition: convex-shape.hh:183
#define HPP_CONSTRAINTS_DLLAPI
Definition: config.hh:88
assert(d.lhs()._blocks()==d.rhs()._blocks())
const Derived & d
Definition: matrix-view-operation.hh:138
pinocchio::vector3_t vector3_t
Definition: fwd.hh:52
void closestPointToSegment(const vector3_t &P, const vector3_t &A, const vector3_t &v, vector3_t &B)
Definition: convex-shape.hh:51
pinocchio::Transform3s Transform3s
Definition: fwd.hh:64
pinocchio::value_type value_type
Definition: fwd.hh:48
bool operator==(const ComparisonTypes_t &v, const internal::ReplicateCompType &r)
Definition: comparison-types.hh:117
pinocchio::vector_t vector_t
Definition: fwd.hh:59
vector3_t linePlaneIntersection(const vector3_t &A, const vector3_t &u, const vector3_t &P, const vector3_t &n)
Definition: convex-shape.hh:70
pinocchio::JointPtr_t JointPtr_t
Definition: fwd.hh:49
Eigen::Matrix< value_type, 3, 1 > vector3_t
Definition: convex-shape.hh:296
Transform3s alignedPositionInJoint(const ConvexShape &cs, vector3_t yaxis) const
Definition: convex-shape.hh:361
vector3_t normal_
Definition: convex-shape.hh:298
void updateToCurrentTransform(const ConvexShape &cs, const pinocchio::DeviceData &d)
Definition: convex-shape.hh:317
Transform3s oMj_
Definition: convex-shape.hh:302
void _recompute(const ConvexShape &cs)
Definition: convex-shape.hh:329
bool isInside(const ConvexShape &cs, const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:349
vector3_t intersection(const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:341
void updateToCurrentTransform(const ConvexShape &cs)
Compute center and normal in world frame.
Definition: convex-shape.hh:305
bool isInside(const ConvexShape &cs, const vector3_t &Ap) const
Check whether the point As in world frame is inside the triangle.
Definition: convex-shape.hh:354
value_type distance(const ConvexShape &cs, vector3_t a) const
Definition: convex-shape.hh:382
vector3_t center_
Definition: convex-shape.hh:300