15#include <boost/multi_array.hpp>
35 this->spreadAngles = newSpreadAngles;
36 this->center = center;
43 Matrix& resultingControlNet)
const
45 Matrix SLE = Matrix::Constant(nControlPoints, nControlPoints, 1.0);
46 using CacheType = boost::multi_array<Real, 3>;
47 CacheType cache(boost::extents[this->nDoF][3][3]);
49 for (
int iDoF = 0; iDoF < this->nDoF; iDoF++)
51 for (
int idx = 0; idx < 3; idx++)
52 for (
int idx2 = 0; idx2 < 3; idx2++)
55 if (
static_cast<unsigned int>(iDoF) != subdividedDoF)
59 cache[iDoF][idx][idx2] = 0.0f;
63 cache[iDoF][idx][idx2] = 1.0f;
73 a1 = (newCenter - this->center(iDoF)) - newSpreadAngle;
74 a2 = (newCenter - this->center(iDoF)) - newSpreadAngle;
78 a1 = (newCenter - this->center(iDoF)) - newSpreadAngle;
79 a2 = (newCenter - this->center(iDoF)) + newSpreadAngle;
83 a1 = (newCenter - this->center(iDoF)) + newSpreadAngle;
84 a2 = (newCenter - this->center(iDoF)) + newSpreadAngle;
89 std::tan(a1 / 2.0) / tan(this->spreadAngles[iDoF] / 2.0) / 2.0 + 0.5;
91 std::tan(a2 / 2.0) / tan(this->spreadAngles[iDoF] / 2.0) / 2.0 + 0.5;
97 cache[iDoF][idx][idx2] = (1 - t1) * (1 - t2);
101 cache[iDoF][idx][idx2] = ((1 - t1) * t2 + (1 - t2) * t1) *
102 std::cos(this->spreadAngles[iDoF]);
106 cache[iDoF][idx][idx2] = t1 * t2;
115 for (
int iSamples = 0; iSamples < nControlPoints; iSamples++)
119 for (
int iControlPoints = 0; iControlPoints < nControlPoints; iControlPoints++)
123 for (
int iDoF = 0; iDoF < this->nDoF; iDoF++)
125 int idx = this->index(iControlPoints, iDoF);
126 int idx2 = this->index(iSamples, iDoF);
128 SLE(iControlPoints, iSamples) *= cache[iDoF][idx][idx2];
132 weight += SLE(iControlPoints, iSamples);
135 for (
int iControlPoints = 0; iControlPoints < nControlPoints; iControlPoints++)
137 SLE(iControlPoints, iSamples) /= weight;
142 resultingControlNet = this->controlNet * SLE;
149 Matrix& resultingControlNet)
const
152 Matrix SLE = Matrix::Constant(nControlPoints, nControlPoints, 1.0);
154 using CacheType = boost::multi_array<Real, 3>;
155 CacheType cache(boost::extents[this->nDoF][3][3]);
157 for (
int iDoF = 0; iDoF < this->nDoF; iDoF++)
159 for (
int idx = 0; idx < 3; idx++)
160 for (
int idx2 = 0; idx2 < 3; idx2++)
167 a1 = (newCenter(iDoF) - this->center(iDoF)) - newSpreadAngles[iDoF];
168 a2 = (newCenter(iDoF) - this->center(iDoF)) - newSpreadAngles[iDoF];
172 a1 = (newCenter(iDoF) - this->center(iDoF)) - newSpreadAngles[iDoF];
173 a2 = (newCenter(iDoF) - this->center(iDoF)) + newSpreadAngles[iDoF];
177 a1 = (newCenter(iDoF) - this->center(iDoF)) + newSpreadAngles[iDoF];
178 a2 = (newCenter(iDoF) - this->center(iDoF)) + newSpreadAngles[iDoF];
182 Real t1 = std::tan(a1 / 2.0) / tan(this->spreadAngles[iDoF] / 2.0) / 2.0 + 0.5;
183 Real t2 = std::tan(a2 / 2.0) / tan(this->spreadAngles[iDoF] / 2.0) / 2.0 + 0.5;
189 cache[iDoF][idx][idx2] = (1 - t1) * (1 - t2);
193 cache[iDoF][idx][idx2] = ((1 - t1) * t2 + (1 - t2) * t1) *
194 std::cos(this->spreadAngles[iDoF]);
198 cache[iDoF][idx][idx2] = t1 * t2;
205 for (
int iSamples = 0; iSamples < nControlPoints; iSamples++)
209 for (
int iControlPoints = 0; iControlPoints < nControlPoints; iControlPoints++)
213 for (
int iDoF = 0; iDoF < this->nDoF; iDoF++)
215 int idx = this->index(iControlPoints, iDoF);
216 int idx2 = this->index(iSamples, iDoF);
217 SLE(iControlPoints, iSamples) *= cache[iDoF][idx][idx2];
221 weight += SLE(iControlPoints, iSamples);
224 for (
int iControlPoints = 0; iControlPoints < nControlPoints; iControlPoints++)
226 SLE(iControlPoints, iSamples) /= weight;
231 resultingControlNet = this->controlNet * SLE;
258 bool included =
true;
260 for (
int i = 0; i < lower.size(); i++)
262 if ((BBlower(i) > (upper(i)) + tolerance) || BBupper(i) <= (lower(i) - tolerance))
267 if ((BBlower(i) < lower(i)) || (BBupper(i) > upper(i)))
272 if ((BBlower(i) > lower(i)) || (BBupper(i) < upper(i)))
300 lower = controlNet.rowwise().minCoeff();
301 upper = controlNet.rowwise().maxCoeff();
307 getBBox(lower, upper, this->controlNet);
315 Vector size = upper - lower;
323 return volume / targetVolume;
330 this->
getBBox(BBlower, BBupper);
333 for (
int i = 0; i < lower.size(); i++)
335 volume *= std::min(upper(i), BBupper(i)) - std::max(lower(i), BBlower(i));
378 kbm->getSubdivisedNet(center, spreadAngles, controlNet);
386 Solution solution(center, spreadAngles, BBupper, BBlower, check);
392 solutionSet.push_back(solution);
393 ARMARX_DEBUG_S <<
"Disjoint: " << std::string(recursion * 2,
'-') << recursion <<
":"
394 << side << std::endl;
404 solutionSet.push_back(solution);
406 <<
"Covered: " << std::string(recursion * 2,
'-') << recursion <<
":" << side
415 if (spreadAngles.maxCoeff() <= resolution)
420 ARMARX_DEBUG_S <<
"Max Res: " << std::string(recursion * 2,
'-') << recursion
421 <<
":" << side << std::endl
422 <<
"center: " << center.transpose()
423 <<
", max. angle: " << spreadAngles.maxCoeff()
424 <<
", lower: " << lower.transpose()
425 <<
", upper: " << upper.transpose()
426 <<
", BB-lower: " << BBlower.transpose()
427 <<
", BB-upper: " << BBupper.transpose() << std::endl;
431 solutionSet.push_back(solution);
435 <<
"Max Res: " << std::string(recursion * 2,
'-') << recursion <<
":" << side
446 ARMARX_DEBUG_S <<
"Subdivide: " << std::string(recursion * 2,
'-') << recursion <<
":"
447 << side << std::endl;
451 unsigned int dof = recursion % kbm->getNDoF();
452 center1(dof) = center(dof) + spreadAngles[dof] / 2.0f;
453 center2(dof) = center(dof) - spreadAngles[dof] / 2.0f;
454 spreadAngles[dof] /= 2.0f;
487 kbm->getSpreadAngles(),
503 kbm->getSpreadAngles(),
528 unsigned int dof = recursion % kbm->getNDoF();
529 kbm->getSubdivisedNet(dof, center[dof], spreadAngles[dof], controlNet);
532 kbm->getSubdivisedNet(center, spreadAngles, controlNet2);
533 ARMARX_DEBUG_S <<
"Similarity of Dof " << dof <<
": " << controlNet.isApprox(controlNet2)
539 kbm->getNDoF(), kbm->getNDim(), center, spreadAngles, controlNet);
544 unsigned int recursion,
549 unsigned int dof = recursion % kbm->getNDoF();
550 center = kbm->getCenter();
551 spreadAngles = kbm->getSpreadAngles();
555 center(dof) = center(dof) - spreadAngles[dof] / 2.0f;
559 center(dof) = center(dof) + spreadAngles[dof] / 2.0f;
562 spreadAngles[dof] /= 2.0f;
571 kbm->getBBox(BBupper, BBlower);
572 Solution solution(kbm->getCenter(), kbm->getSpreadAngles(), BBupper, BBlower, check);
588 if (kbm->getSpreadAngles().maxCoeff() <=
resolution)
612 Real overlap = kbm->getOverlappingVolumeRatio(
622 ARMARX_DEBUG_S <<
"breadth " << std::string(level * 2,
'-') << level << std::endl;
626 ARMARX_DEBUG_S <<
"depth " << std::string(level * 2,
'-') << level <<
": "
627 << kbm->getSpreadAngles().maxCoeff() /
M_PI * 180.0f << std::endl;
639 assert(overlap == 0.0f);
647 Real overlap = kbm->getOverlappingVolumeRatio(
654 if (kbm->getSpreadAngles().maxCoeff() <=
resolution)
656 ARMARX_DEBUG_S <<
"Max recursion, target overlap " << overlap * 100.f <<
", "
657 << kbm->getOverlappingVolumeRatio(
674 Real ratio = kbm->getOverlappingVolumeRatio(
676 GraphNode initial(kbm, ratio, level, kbm->getVolume());
685 Real ratio1 = sub1->getOverlappingVolumeRatio(
687 Real ratio2 = sub2->getOverlappingVolumeRatio(
692 << 100.f * sub1->getVolume() / kbm->getVolume() <<
"%, "
693 << sub2->getVolume() / kbm->getVolume() * 100.f <<
"%" << std::endl;
694 ARMARX_DEBUG_S <<
"Target overlapping: " << ratio1 * 100.f <<
"%, "
695 << ratio2 * 100.f <<
"%, " << this->
targetVolume << std::endl;
706 n = this->
recurse(level + 1, sub1);
710 n = this->
recurse(level + 1, sub2);
713 if (breadth || n == 0)
719 n += this->
recurse(level + 1, sub2);
723 n += this->
recurse(level + 1, sub1);
742 if (left.ratio != right.ratio)
744 return left.ratio < right.ratio;
750 GlobalIKBase::SolutionSet
754 std::priority_queue<GraphNode> priority_queue;
756 priority_queue.push(initial);
759 while (!priority_queue.empty())
761 GraphNode topNode = priority_queue.top();
763 priority_queue.pop();
765 if (topNode.
ratio == 1.0)
776 Real volume = child->getVolume();
777 Real ratio = child->getOverlappingVolumeRatio(
783 priority_queue.push(
GraphNode(child, ratio, topNode.
level + 1, volume));
784 std::cout << side + 1 <<
". Ratio: " << ratio <<
" ("
785 << ratio / topNode.
ratio * 100.0f
786 <<
"%), Vol.: " << volume / topNode.
volume * 100.f <<
"%, ";
795 std::cout <<
"Resolution: " << topNode.
model->getSpreadAngles().maxCoeff();
798 std::cout <<
", " << topNode.
model->getSpreadAngles().maxCoeff() /
M_PI * 180.0f <<
"("
800 <<
", Level: " << topNode.
level << std::endl;
virtual unsigned int recurse(unsigned int level, Models::KBM_ptr kbm)=0
void subdivideAngles(Side side, unsigned int recursion, Models::KBM_ptr kbm, Vector ¢er, Vector &spreadAngles)
Subdivides the joint angles only. Can be used to select in which direction to subdivise first.
Models::KBM_ptr subdivideKBM(GlobalIKBase::Side side, unsigned int recursion, Models::KBM_ptr kbm)
Subdivides the kbm and creates new KBM. Calls GlobalIKBase::subdivideAngles().
void solve(Models::KBM_ptr kbm, const Vector lower, const Vector upper, Real resolution=2.0f *M_PI/180.0f)
std::vector< Solution > SolutionSet
unsigned int recurse(unsigned int level, Models::KBM_ptr kbm) override
Real semiBreadthRecursion
unsigned int recurse(unsigned int level, Models::KBM_ptr kbm) override
GlobalIKSemiBreadth(Real _semiBreadthRecursion, int _solutionSelect=Models::KBM::COVERED)
GlobalIKBase::SolutionSet runDijkstra(KBM::Inverse::GraphNode initial)
Real getOverlappingVolumeRatio(const Vector &lower, const Vector &upper, Real targetVolume)
static BBCheckType checkBBoxes(const Vector &lower, const Vector &upper, const Matrix &controlNet, Real tolerance=0.0f)
Check whether an interval overlaps the the bounding box of a given control net.
void getSubdivisedNet(const Vector newCenter, Vector newSpreadAngles, Matrix &resultingControlNet) const
Work in progress This method computes the control net of a subdivised KBM instance.
static KBM_ptr createKBM(int nDoF, int dim, const Vector ¢er, const Vector &spreadAngles, const Matrix &controlNet)
Factory methods.
BBCheckType
Cases for the check of bounding boxes (i.e., an interval ) and an interval ( )both in Cartesian coor...
@ DISJOINT
The bounding box and interval are disjoint .
@ OVERLAPPING
The interval and bounding box are partially overlapping (if none of the above applies).
@ INCLUDED
The interval is included in the bounding box .
@ COVERED
The bounding box is covered by the interval (most interesting case for inverse kinematics).
static void getBBox(Vector &lower, Vector &upper, const Matrix &controlNet)
Helper function that extracts the bounding box of a control net.
Real getOverlappingVolume(const Vector &lower, const Vector &upper)
void subdivide(const Vector ¢er, const Vector &newSpreadAngles)
Work in progress This method subdivides the KBM representation.
BBCheckType checkBBox(const Vector &lower, const Vector &upper, Real tolerance=0.0f) const
Check whether an interval overlaps the the bounding box of the control points.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Namespace for algorithms related to solving the inverse kinematics.
bool operator<(const GraphNode &left, const GraphNode &right)
std::vector< Solution > SolutionSet
Return type of the global inverse kinematics solvers.
void solveGlobalIK(unsigned int recursion, int side, SolutionSet &solutionSet, Models::KBM_ptr kbm, const Vector &lower, const Vector &upper, Real resolution, Vector spreadAngles, Vector center)
Where the model representation for a Body Schema (especially the Kinematic B“ezier Maps) reside.
std::shared_ptr< KBM > KBM_ptr
double Real
Type definition of the underlying Realing point type.
Point sub(const Point &x, const Point &y)