PrimitiveFusion.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package VisionX
19  * @author Markus Grotz ( markus dot grotz at kit dot edu )
20  * @date 2015
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #include "PrimitiveFusion.h"
26 
27 
29 
30 
31 using namespace armarx;
32 
34 {
35 
36 }
37 
39 {
40 
41 }
42 
43 
44 // todo rename
45 bool PrimitiveFusion::testBoxIntersection(Eigen::Matrix4f leftPose, Eigen::Matrix4f rightPose, Eigen::Vector3f leftExtent, Eigen::Vector3f rightExtent)
46 {
47  Eigen::Matrix3Xf axes(3, 15);
48 
49  axes.block<3, 3>(0, 0) = leftPose.block<3, 3>(0, 0);
50  axes.block<3, 3>(0, 3) = rightPose.block<3, 3>(0, 0);
51 
52 
53  for (int i = 0; i < 3; i++)
54  {
55  for (int j = 0; j < 3; j++)
56  {
57  Eigen::Vector3f a = leftPose.col(i).head<3>();
58  Eigen::Vector3f b = rightPose.col(j).head<3>();
59  int idx = 6 + (i * 3 + j);
60  Eigen::Vector3f c = a.cross(b);
61  if (a.norm() == 0)
62  {
63  axes.col(idx) = Eigen::Vector3f::Zero();
64  }
65  else
66  {
67  axes.col(idx) = c / c.norm();
68  }
69  }
70  }
71 
72  for (int i = 0; i < 15; i++)
73  {
74  float ra = 0.0;
75  float rb = 0.0;
76 
77  Eigen::Vector3f axis = axes.col(i);
78 
79  if (axis.norm() == 0)
80  {
81  continue;
82  }
83 
84  for (int j = 0; j < 3; j++)
85  {
86  Eigen::Vector3f a = leftPose.col(j).head<3>();
87  Eigen::Vector3f b = rightPose.col(j).head<3>();
88 
89  ra += fabs(axis.dot(a) * leftExtent(j));
90  rb += fabs(axis.dot(b) * rightExtent(j));
91  }
92 
93  Eigen::Vector3f t = projectVector(axis, leftPose.col(3).head<3>());
94  t = t - projectVector(axis, rightPose.col(3).head<3>());
95 
96  if (t.norm() > (ra + rb))
97  {
98  return false;
99  }
100  }
101 
102  return true;
103 }
104 
105 Eigen::Vector3f PrimitiveFusion::projectVector(Eigen::Vector3f axis, Eigen::Vector3f u)
106 {
107  float v = u.dot(axis) / axis.squaredNorm();
108  return axis * v;
109 }
110 
111 
112 
113 void PrimitiveFusion::getIntersectingPrimitives(memoryx::EnvironmentalPrimitiveBaseList& primitives, memoryx::EnvironmentalPrimitiveBasePtr primitive, memoryx::EnvironmentalPrimitiveBaseList& intersectingPrimitives, float eps)
114 {
115  Eigen::Matrix4f leftPose = FramedPosePtr::dynamicCast(primitive->getPose())->toEigen();
116  Eigen::Vector3f leftExtent = Vector3Ptr::dynamicCast(primitive->getOBBDimensions())->toEigen() / 2.0 + eps * Eigen::Vector3f::Ones();
117 
118  for (memoryx::EnvironmentalPrimitiveBasePtr& p : primitives)
119  {
120  Eigen::Matrix4f rightPose = FramedPosePtr::dynamicCast(p->getPose())->toEigen();
121  Eigen::Vector3f rightExtent = Vector3Ptr::dynamicCast(p->getOBBDimensions())->toEigen() / 2.0 + eps * Eigen::Vector3f::Ones();
122 
123  if (primitive->ice_staticId() != p->ice_staticId())
124  {
125  continue;
126  }
127  if (primitive->getId() == p->getId())
128  {
129  continue;
130  }
131  if (testBoxIntersection(leftPose, rightPose, leftExtent, rightExtent))
132  {
133  intersectingPrimitives.push_back(p);
134  }
135  }
136 }
137 
138 
139 void PrimitiveFusion::getIntersectingSimilarPrimitives(memoryx::EnvironmentalPrimitiveBaseList& primitives, memoryx::EnvironmentalPrimitiveBasePtr primitive, memoryx::EnvironmentalPrimitiveBaseList& intersectingPrimitives, float eps)
140 {
141  memoryx::EnvironmentalPrimitiveBaseList candidates;
142 
143  getIntersectingPrimitives(primitives, primitive, candidates, eps);
144 
145  for (memoryx::EnvironmentalPrimitiveBasePtr p : candidates)
146  {
147  if (testPlane(p, primitive))
148  {
149  intersectingPrimitives.push_back(p);
150  }
151 
152  else if (testCylinder(p, primitive))
153  {
154  intersectingPrimitives.push_back(p);
155  }
156 
157 
158  }
159 
160 }
161 
162 
163 bool PrimitiveFusion::testCylinder(memoryx::EnvironmentalPrimitiveBasePtr leftPrimitive, memoryx::EnvironmentalPrimitiveBasePtr rightPrimitive)
164 {
165  memoryx::CylinderPrimitivePtr leftCylinder = memoryx::CylinderPrimitivePtr::dynamicCast(leftPrimitive);
166  memoryx::CylinderPrimitivePtr rightCylinder = memoryx::CylinderPrimitivePtr::dynamicCast(rightPrimitive);
167 
168  if (!leftCylinder || !rightCylinder)
169  {
170  return false;
171  }
172 
173  Eigen::Vector3f leftAxisDirection = Vector3Ptr::dynamicCast(leftCylinder->getCylinderAxisDirection())->toEigen();
174  Eigen::Vector3f rightAxisDirection = Vector3Ptr::dynamicCast(rightCylinder->getCylinderAxisDirection())->toEigen();
175 
176  float r = leftAxisDirection.dot(rightAxisDirection);
177 
178  if (std::acos(r) > pcl::deg2rad(15.0))
179  {
180  return false;
181  }
182 
183 
184  /*
185  // radius should be almost the same
186  if (std::fabs(leftCylinder->getCylinderRadius(), rightCylinder->getCylinderRadius()) < 50.0)
187  {
188  return false;
189  }
190  */
191 
192  Eigen::Matrix4f leftPose = FramedPosePtr::dynamicCast(leftCylinder->getPose())->toEigen();
193  Eigen::Vector3f leftExtent = Eigen::Vector3f(leftCylinder->getLength() / 2.0, leftCylinder->getCylinderRadius(), leftCylinder->getCylinderRadius());
194 
195 
196  Eigen::Matrix4f rightPose = FramedPosePtr::dynamicCast(rightCylinder->getPose())->toEigen();
197  Eigen::Vector3f rightExtent = Eigen::Vector3f(rightCylinder->getLength() / 2.0, rightCylinder->getCylinderRadius(), rightCylinder->getCylinderRadius());
198 
199 
200  if (!testBoxIntersection(leftPose, rightPose, leftExtent, rightExtent))
201  {
202  return false;
203  }
204 
205  return true;
206 }
207 
208 bool PrimitiveFusion::testPlane(memoryx::EnvironmentalPrimitiveBasePtr leftPrimitive, memoryx::EnvironmentalPrimitiveBasePtr rightPrimitive)
209 {
210  memoryx::PlanePrimitivePtr leftPlane = memoryx::PlanePrimitivePtr::dynamicCast(leftPrimitive);
211  memoryx::PlanePrimitivePtr rightPlane = memoryx::PlanePrimitivePtr::dynamicCast(rightPrimitive);
212 
213  if (!leftPlane || !rightPlane)
214  {
215  return false;
216  }
217 
218  Eigen::Vector3f leftPlaneNormal = Vector3Ptr::dynamicCast(leftPlane->getPlaneNormal())->toEigen();
219  Eigen::Vector3f rightPlaneNormal = Vector3Ptr::dynamicCast(rightPlane->getPlaneNormal())->toEigen();
220 
221  if ((leftPlaneNormal - rightPlaneNormal).norm() < 0.001)
222  {
223  return true;
224  }
225 
226  float alpha = std::acos(leftPlaneNormal.dot(rightPlaneNormal));
227 
228  if (alpha > pcl::deg2rad(10.0))
229  {
230  return false;
231  }
232 
233  return true;
234 }
235 
236 
237 
238 bool PrimitiveFusion::isSimilar(memoryx::EnvironmentalPrimitiveBasePtr leftPrimitive, memoryx::EnvironmentalPrimitiveBasePtr rightPrimitive)
239 {
240  if (leftPrimitive->ice_staticId() != rightPrimitive->ice_staticId())
241  {
242  return false;
243  }
244 
245  Eigen::Vector3f leftOBB = Vector3Ptr::dynamicCast(leftPrimitive->getOBBDimensions())->toEigen();
246  Eigen::Vector3f rightOBB = Vector3Ptr::dynamicCast(rightPrimitive->getOBBDimensions())->toEigen();
247 
248  if ((leftOBB - rightOBB).norm() > 10.0)
249  {
250  return false;
251  }
252 
253  Eigen::Vector3f leftPosition = Vector3Ptr::dynamicCast(leftPrimitive->getPose()->position)->toEigen();
254  Eigen::Vector3f rightPosition = Vector3Ptr::dynamicCast(rightPrimitive->getPose()->position)->toEigen();
255 
256  if ((leftPosition - rightPosition).norm() > 5.0)
257  {
258  return false;
259  }
260 
261  Eigen::Matrix3f leftRotation = QuaternionPtr::dynamicCast(leftPrimitive->getPose()->orientation)->toEigen();
262  Eigen::Matrix3f rightRotation = QuaternionPtr::dynamicCast(rightPrimitive->getPose()->orientation)->toEigen();
263 
264  Eigen::Vector3f ea = (leftRotation.transpose() * rightRotation).eulerAngles(0, 1, 2);
265 
266 
267  float delta = pcl::deg2rad(15.0);
268  for (int i = 0; i < 3; i++)
269  {
270  ea[i] = std::fabs(ea[i]);
271  ea[i] = std::fmod(ea[i], M_PI);
272  if (ea[i] > delta && ea[i] < (M_PI - delta))
273  {
274  return false;
275  }
276  }
277 
278  return true;
279 }
280 
281 
282 
283 void PrimitiveFusion::findBoxPrimitives(memoryx::EnvironmentalPrimitiveBaseList& primitives, std::vector<memoryx::EntityBasePtr>& boxes, memoryx::EnvironmentalPrimitiveSegmentBasePrx environmentalPrimitiveSegment)
284 {
285  for (memoryx::EnvironmentalPrimitiveBasePtr& currentPrimitive : primitives)
286  {
287  memoryx::PlanePrimitivePtr plane = memoryx::PlanePrimitivePtr::dynamicCast(currentPrimitive);
288  if (!plane)
289  {
290  continue;
291  }
292 
293  Eigen::Vector3f planeNormal = Vector3Ptr::dynamicCast(plane->getPlaneNormal())->toEigen();
294  float alpha = std::acos(planeNormal.dot(Eigen::Vector3f::UnitZ()));
295  if (alpha < pcl::deg2rad(15.0))
296  {
297  std::vector<memoryx::PlanePrimitivePtr> boxSides;
298  boxSides.push_back(plane);
299 
300  std::vector<memoryx::EnvironmentalPrimitiveBasePtr> intersectingPrimitives;
301  getIntersectingPrimitives(primitives, currentPrimitive, intersectingPrimitives, 50.0);
302 
303  for (memoryx::EnvironmentalPrimitiveBasePtr& i : intersectingPrimitives)
304  {
305  memoryx::PlanePrimitivePtr sideCandidate = memoryx::PlanePrimitivePtr::dynamicCast(i);
306  if (!sideCandidate)
307  {
308  continue;
309  }
310  else if (plane->getPose()->position->z < sideCandidate->getPose()->position->z)
311  {
312  continue;
313  }
314 
315  bool isPerpendicular = true;
316  for (memoryx::PlanePrimitivePtr& side : boxSides)
317  {
318  Eigen::Vector3f sideNormal = Vector3Ptr::dynamicCast(sideCandidate->getPlaneNormal())->toEigen();
319  Eigen::Vector3f otherNormal = Vector3Ptr::dynamicCast(side->getPlaneNormal())->toEigen();
320 
321  float beta = std::acos(sideNormal.dot(otherNormal));
322 
323  if (std::abs(beta) < 0.01)
324  {
325  ARMARX_LOG_S << "found a parallel side. doing nothing at the moment";
326  // todo check if this is a possible opposite side;
327  isPerpendicular = false;
328  break;
329  }
330  else if (std::fabs(beta - M_PI_2) > pcl::deg2rad(5.0))
331  {
332  isPerpendicular = false;
333  break;
334  }
335  }
336  if (isPerpendicular)
337  {
338  boxSides.push_back(sideCandidate);
339  }
340  }
341 
342  if (boxSides.size() == 3)
343  {
344  memoryx::EntityRefList entityRefList;
345  memoryx::PointList graspPoints;
346  std::vector<Eigen::Vector3f> normals;
347  std::vector<Eigen::Vector3f> positions;
348  for (size_t i = 0; i < 3; i++)
349  {
350  memoryx::PlanePrimitivePtr side = boxSides[i];
351  normals.push_back(Vector3Ptr::dynamicCast(side->getPlaneNormal())->toEigen());
352  positions.push_back(Vector3Ptr::dynamicCast(side->getPose()->position)->toEigen());
353 
354  memoryx::EntityRefBasePtr entityRef = environmentalPrimitiveSegment->getEntityRefById(side->getId());
355  entityRefList.push_back(entityRef);
356 
357  for (armarx::Vector3BasePtr& g : side->getGraspPoints())
358  {
359  graspPoints.push_back(g);
360  }
361  }
362 
363 
364  Eigen::Matrix3f rot = Eigen::Matrix3f::Zero();
365  rot.col(0) = normals[0];
366  rot.col(1) = normals[1];
367  rot.col(2) = normals[0].cross(normals[1]);
368 
369  Eigen::Vector3f position = positions[0];
370  position(2) = positions[1](2);
371 
372  FramedPosePtr pose = new FramedPose(rot, position, armarx::GlobalFrame, "");
373 
374  Eigen::Vector3f dimE;
375  dimE(0) = normals[0].dot(positions[0] - position);
376  dimE(1) = normals[1].dot(positions[1] - position);
377  dimE(2) = normals[2].dot(positions[2] - position);
378  dimE = 2.0 * dimE.cwiseAbs();
379 
380  memoryx::BoxPrimitivePtr boxPrimitive = new memoryx::BoxPrimitive();
381  boxPrimitive->setBoxSides(entityRefList);
382  boxPrimitive->setGraspPoints(graspPoints);
383  boxPrimitive->setLabel(0);
384  boxPrimitive->setOBBDimensions(new Vector3(dimE));
385  boxPrimitive->setPose(pose);
386 
387  boxPrimitive->setProbability(1.0);
388  // for (memoryx::PlanePrimitivePtr& side : boxSides)
389  // {
390  //boxPrimitive->setProbability(boxPrimitive->getProbability(), side->getProbability());
391  // }
392 
393  boxPrimitive->setTime(boxSides[0]->getTime());
394  boxPrimitive->setName("box");
395 
396  boxes.push_back(boxPrimitive);
397 
398  bool mirrorSides = true;
399  if (mirrorSides)
400  {
401  for (size_t i = 1; i < 3; i++)
402  {
403  memoryx::PlanePrimitivePtr side = boxSides[i];
404  Eigen::Matrix4f p = FramedPosePtr::dynamicCast(side->getPose())->toEigen();
405  Eigen::Vector3f m = p.block<3, 3>(0, 0).transpose() * normals[i];
406 
407  Eigen::Vector3f mPosition = position - normals[i] * dimE(2);
408  FramedPosePtr mPose = new FramedPose(p.block<3, 3>(0, 0), mPosition, armarx::GlobalFrame, "");
409 
410  memoryx::PointList graspPoints;
411  for (armarx::Vector3BasePtr& g : side->getGraspPoints())
412  {
413  Eigen::Vector4f point = Eigen::Vector4f::Identity();
414  point.head<3>() = Vector3Ptr::dynamicCast(g)->toEigen();
415 
416  point = p.inverse() * point;
417  point.head<3>() = point.head<3>() - m * dimE(i);
418  point = p * point;
419 
420  Eigen::Vector3f temp = point.head<3>();
421  graspPoints.push_back(new Vector3(temp));
422  }
423 
424 
426  mSide->setOBBDimensions(side->getOBBDimensions());
427  mSide->setGraspPoints(graspPoints);
428  mSide->setPose(mPose);
429  // todo rotate normal
430  mSide->setPlaneNormal(side->getPlaneNormal());
431  mSide->setLabel(0);
432  mSide->setTime(side->getTime());
433  mSide->setProbability(0.0);
434 
435  boxes.push_back(mSide);
436  }
437  }
438  }
439  }
440  }
441 }
armarx::PrimitiveFusion::~PrimitiveFusion
~PrimitiveFusion()
PrimitiveFusion Destructor.
Definition: PrimitiveFusion.cpp:38
armarx::PrimitiveFusion::testBoxIntersection
bool testBoxIntersection(Eigen::Matrix4f leftPose, Eigen::Matrix4f rightPose, Eigen::Vector3f leftExtent, Eigen::Vector3f rightExtent)
Definition: PrimitiveFusion.cpp:45
memoryx::VariantType::PlanePrimitive
const armarx::VariantTypeId PlanePrimitive
Definition: EnvironmentalPrimitive.h:38
armarx::PrimitiveFusion::PrimitiveFusion
PrimitiveFusion()
PrimitiveFusion Constructor.
Definition: PrimitiveFusion.cpp:33
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:37
armarx::PrimitiveFusion::getIntersectingPrimitives
void getIntersectingPrimitives(memoryx::EnvironmentalPrimitiveBaseList &primitives, memoryx::EnvironmentalPrimitiveBasePtr primitive, memoryx::EnvironmentalPrimitiveBaseList &intersectingPrimitives, float eps=0.0f)
Definition: PrimitiveFusion.cpp:113
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:62
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::PrimitiveFusion::getIntersectingSimilarPrimitives
void getIntersectingSimilarPrimitives(memoryx::EnvironmentalPrimitiveBaseList &primitives, memoryx::EnvironmentalPrimitiveBasePtr primitive, memoryx::EnvironmentalPrimitiveBaseList &intersectingPrimitives, float eps=0.0f)
Definition: PrimitiveFusion.cpp:139
armarx::PrimitiveFusion::findBoxPrimitives
void findBoxPrimitives(memoryx::EnvironmentalPrimitiveBaseList &primitives, std::vector< memoryx::EntityBasePtr > &boxes, memoryx::EnvironmentalPrimitiveSegmentBasePrx environmentalPrimitiveSegment)
Definition: PrimitiveFusion.cpp:283
PrimitiveFusion.h
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
armarx::PrimitiveFusion::isSimilar
bool isSimilar(memoryx::EnvironmentalPrimitiveBasePtr leftPrimitive, memoryx::EnvironmentalPrimitiveBasePtr rightPrimitive)
Definition: PrimitiveFusion.cpp:238
armarx::abs
std::vector< T > abs(const std::vector< T > &v)
Definition: VectorHelpers.h:253
M_PI
#define M_PI
Definition: MathTools.h:17
FramedPose.h
memoryx::VariantType::BoxPrimitive
const armarx::VariantTypeId BoxPrimitive
Definition: EnvironmentalPrimitive.h:42
ARMARX_LOG_S
#define ARMARX_LOG_S
Definition: Logging.h:145
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
memoryx::KBM::Vector3
Eigen::Vector3d Vector3
Definition: kbm.h:41
armarx::transpose
std::vector< std::vector< T > > transpose(const std::vector< std::vector< T >> &src, Thrower thrower)
Definition: SimoxCSpace.cpp:706
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
norm
double norm(const Point &a)
Definition: point.hpp:94