hpp-constraints  6.0.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 #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.
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 {
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 
68  const vector3_t& P, const vector3_t& n) {
69  assert(std::abs(n.dot(u)) > 1e-8);
70  return A + u * (n.dot(P - A)) / n.dot(u);
71 }
72 
74  public:
83  ConvexShape(const std::vector<vector3_t>& pts,
84  JointPtr_t joint = JointPtr_t())
85  : Pts_(pts), joint_(joint) {
86  init();
87  }
88 
89  ConvexShape(const coal::TriangleP& t, const JointPtr_t& joint = JointPtr_t())
90  : Pts_(triangleToPoints(t)), joint_(joint) {
91  init();
92  }
93 
96  ConvexShape(const vector3_t& p0, const vector3_t& p1, const vector3_t& p2,
97  const JointPtr_t& joint = JointPtr_t())
98  : Pts_(points(p0, p1, p2)), joint_(joint) {
99  init();
100  }
101 
102  // Copy constructor
103  ConvexShape(const ConvexShape& t) : Pts_(t.Pts_), joint_(t.joint_) { init(); }
104 
105  void reverse() {
106  std::reverse(Pts_.begin(), Pts_.end());
107  init();
108  }
109 
113  const vector3_t& u) const {
114  return linePlaneIntersection(A, u, C_, N_);
115  }
116 
118  inline bool isInsideLocal(const vector3_t& Ap) const {
119  assert(shapeDimension_ > 2);
120  for (std::size_t i = 0; i < shapeDimension_; ++i) {
121  if (Ns_[i].dot(Ap - Pts_[i]) > 0) return false;
122  }
123  return true;
124  }
125 
130  inline value_type distanceLocal(const vector3_t& a) const {
131  assert(shapeDimension_ > 1);
132  const value_type inf = std::numeric_limits<value_type>::infinity();
133  value_type minPosDist = inf, maxNegDist = -inf;
134  bool outside = false;
135  for (std::size_t i = 0; i < shapeDimension_; ++i) {
136  value_type d = dist(a - Pts_[i], Ls_[i], Us_[i], Ns_[i]);
137  if (d > 0) {
138  outside = true;
139  if (d < minPosDist) minPosDist = d;
140  }
141  if (d <= 0 && d > maxNegDist) maxNegDist = d;
142  }
143  if (outside) return minPosDist;
144  return maxNegDist;
145  }
146 
148  inline const vector3_t& planeXaxis() const {
149  assert(shapeDimension_ > 2);
150  return Ns_[0];
151  }
154  inline const vector3_t& planeYaxis() const {
155  assert(shapeDimension_ > 2);
156  return Us_[0];
157  }
158 
160  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 
179  std::vector<vector3_t> Pts_;
189  std::vector<vector3_t> Ns_, Us_;
193 
194  private:
198  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  c1 = v.dot(w);
202  if (c1 <= 0) return (u.dot(w) > 0) ? (w.norm()) : (-w.norm());
203  if (c2 <= c1)
204  // TODO: (w - c2 * v).norm() == sqrt((u.dot(w)**2 + (c1 - c2)**2)
205  // second should be cheaper.
206  return (u.dot(w) > 0) ? ((w - c2 * v).norm()) : (-(w - c2 * v).norm());
207  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  static std::vector<vector3_t> points(const vector3_t& p0, const vector3_t& p1,
220  const vector3_t& p2) {
221  std::vector<vector3_t> ret(3);
222  ret[0] = p0;
223  ret[1] = p1;
224  ret[2] = p2;
225  return ret;
226  }
227 
228  void init() {
229  shapeDimension_ = Pts_.size();
230 
231  switch (shapeDimension_) {
232  case 0:
233  throw std::logic_error("Cannot represent an empty shape.");
234  break;
235  case 1:
236  C_ = Pts_[0];
237  // The transformation will be (N_, Ns_[0], Us_[0])
238  // Fill vectors so as to be consistent
239  N_ = vector3_t(1, 0, 0);
240  Ns_.push_back(vector3_t(0, 1, 0));
241  Us_.push_back(vector3_t(0, 0, 1));
242  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  default:
260  Ls_ = vector_t(shapeDimension_);
261  C_.setZero();
262  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  C_ /= (value_type)Pts_.size();
266  N_ = (Pts_[1] - Pts_[0]).cross(Pts_[2] - Pts_[1]);
267  assert(!N_.isZero());
268  N_.normalize();
269 
270  Us_.resize(Pts_.size());
271  Ns_.resize(Pts_.size());
272  for (std::size_t i = 0; i < shapeDimension_; ++i) {
273  Us_[i] = Pts_[(i + 1) % shapeDimension_] - Pts_[i];
274  Ls_[i] = Us_[i].norm();
275  Us_[i].normalize();
276  Ns_[i] = Us_[i].cross(N_);
277  Ns_[i].normalize();
278  }
279  for (std::size_t i = 0; i < shapeDimension_; ++i) {
280  assert(Us_[(i + 1) % shapeDimension_].dot(Ns_[i]) < 0 &&
281  "The sequence does not define a convex surface");
282  }
283  break;
284  }
285 
286  MinJoint_.translation() = C_;
287  MinJoint_.rotation().col(0) = N_;
288  MinJoint_.rotation().col(1) = Ns_[0];
289  MinJoint_.rotation().col(2) = Us_[0];
290  }
291 };
292 
294  // normal in the world frame
296  // center in the world frame
298  // Current joint position
300 
302  inline void updateToCurrentTransform(const ConvexShape& cs) {
303  if (cs.joint_ == NULL) {
304  oMj_.setIdentity();
305  _recompute<true>(cs);
306  } else {
307  oMj_ = cs.joint_->currentTransformation();
308  _recompute<false>(cs);
309  }
310  }
311 
314  inline void updateToCurrentTransform(const ConvexShape& cs,
315  const pinocchio::DeviceData& d) {
316  if (cs.joint_ == NULL) {
317  oMj_.setIdentity();
318  _recompute<true>(cs);
319  } else {
320  oMj_ = cs.joint_->currentTransformation(d);
321  _recompute<false>(cs);
322  }
323  }
324 
325  template <bool WorldFrame>
326  inline void _recompute(const ConvexShape& cs) {
327  if (WorldFrame) {
328  center_ = cs.C_;
329  normal_ = cs.N_;
330  } else {
331  center_ = oMj_.act(cs.C_);
332  normal_ = oMj_.rotation() * cs.N_;
333  }
334  }
335 
338  inline vector3_t intersection(const vector3_t& A, const vector3_t& u) const {
339  return linePlaneIntersection(A, u, center_, normal_);
340  }
341 
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  }
351  inline bool isInside(const ConvexShape& cs, const vector3_t& Ap) const {
352  if (cs.joint_ == NULL) return cs.isInsideLocal(Ap);
353  vector3_t Ap_loc = oMj_.actInv(Ap);
354  return cs.isInsideLocal(Ap_loc);
355  }
356 
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 
379  inline value_type distance(const ConvexShape& cs, vector3_t a) const {
380  if (cs.joint_ != NULL) a = oMj_.actInv(a);
381  return cs.distanceLocal(a);
382  }
383 };
384 } // namespace constraints
385 } // namespace hpp
386 
387 #endif // HPP_CONSTRAINTS_CONVEX_SHAPE_HH
Definition: convex-shape.hh:73
ConvexShape(const std::vector< vector3_t > &pts, JointPtr_t joint=JointPtr_t())
Definition: convex-shape.hh:83
Transform3s MinJoint_
Definition: convex-shape.hh:191
ConvexShape(const vector3_t &p0, const vector3_t &p1, const vector3_t &p2, const JointPtr_t &joint=JointPtr_t())
Definition: convex-shape.hh:96
const vector3_t & planeYaxis() const
Definition: convex-shape.hh:154
bool operator!=(ConvexShape const &other) const
Definition: convex-shape.hh:174
vector3_t C_
the center in the joint frame. It is constant.
Definition: convex-shape.hh:182
std::vector< vector3_t > Us_
Definition: convex-shape.hh:189
std::vector< vector3_t > Pts_
The points in the joint frame. It is constant.
Definition: convex-shape.hh:179
bool operator==(ConvexShape const &other) const
Definition: convex-shape.hh:162
ConvexShape(const ConvexShape &t)
Definition: convex-shape.hh:103
bool isInsideLocal(const vector3_t &Ap) const
As isInside but consider A as expressed in joint frame.
Definition: convex-shape.hh:118
const Transform3s & positionInJoint() const
Transform of the shape in the joint frame.
Definition: convex-shape.hh:160
void reverse()
Definition: convex-shape.hh:105
vector3_t N_
the normal to the shape in the joint frame. It is constant.
Definition: convex-shape.hh:184
const vector3_t & planeXaxis() const
Return the X axis of the plane in the joint frame.
Definition: convex-shape.hh:148
value_type distanceLocal(const vector3_t &a) const
Definition: convex-shape.hh:130
vector_t Ls_
Definition: convex-shape.hh:190
std::vector< vector3_t > Ns_
Definition: convex-shape.hh:189
ConvexShape(const coal::TriangleP &t, const JointPtr_t &joint=JointPtr_t())
Definition: convex-shape.hh:89
vector3_t intersectionLocal(const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:112
JointPtr_t joint_
Definition: convex-shape.hh:192
size_t shapeDimension_
Definition: convex-shape.hh:180
#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:48
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:67
pinocchio::JointPtr_t JointPtr_t
Definition: fwd.hh:49
Definition: active-set-differentiable-function.hh:36
Definition: convex-shape.hh:293
Transform3s alignedPositionInJoint(const ConvexShape &cs, vector3_t yaxis) const
Definition: convex-shape.hh:358
vector3_t normal_
Definition: convex-shape.hh:295
void updateToCurrentTransform(const ConvexShape &cs, const pinocchio::DeviceData &d)
Definition: convex-shape.hh:314
Transform3s oMj_
Definition: convex-shape.hh:299
void _recompute(const ConvexShape &cs)
Definition: convex-shape.hh:326
bool isInside(const ConvexShape &cs, const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:346
vector3_t intersection(const vector3_t &A, const vector3_t &u) const
Definition: convex-shape.hh:338
void updateToCurrentTransform(const ConvexShape &cs)
Compute center and normal in world frame.
Definition: convex-shape.hh:302
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:351
value_type distance(const ConvexShape &cs, vector3_t a) const
Definition: convex-shape.hh:379
vector3_t center_
Definition: convex-shape.hh:297