InterpolationSegmentFactory.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarXGuiPlugins::RobotTrajectoryDesigner::Interpolation
17 * @author Timo Birr
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
23
25
27
28#include "LinearInterpolation.h"
29#include "SplineInterpolation.h"
30
31///EXCEPTIONS
35
36using namespace armarx;
37using namespace VirtualRobot;
38
39std::vector<AbstractInterpolationPtr>
41 std::vector<PoseBasePtr> controlPoints,
42 std::vector<InterpolationType> interpolations)
43{
44 if (controlPoints.size() != interpolations.size() + 1)
45 {
47 controlPoints.size(), interpolations.size());
48 }
49
50 std::vector<AbstractInterpolationPtr> producedInterpolations =
51 std::vector<AbstractInterpolationPtr>();
52
53 std::vector<int> interPolationChangePoints = std::vector<int>();
54 interPolationChangePoints.push_back(0);
55
56 if (interpolations.size() == 1 && interpolations.at(0) == eSplineInterpolation)
57 {
58 interpolations.assign(0, eLinearInterpolation);
59 }
60
61 //mark parts of the Interpolaion where it changes
62 int splineCounter = 0;
63 InterpolationType current = interpolations.at(0);
64 if (eSplineInterpolation == interpolations.at(0))
65 {
66 splineCounter++;
67 }
68 for (unsigned int i = 1; i < interpolations.size(); i++)
69 {
70 if (eSplineInterpolation == interpolations.at(i))
71 {
72 splineCounter++;
73 }
74 if (current != interpolations.at(i))
75 {
76 if (current == eSplineInterpolation && interpolations.at(i) != eSplineInterpolation)
77 {
78 if (splineCounter < 2)
79 {
80 interpolations[i - 1] = eLinearInterpolation;
81 }
82 else
83 {
84 interPolationChangePoints.push_back(i);
85 }
86 splineCounter = 0;
87 }
88 else
89 {
90 interPolationChangePoints.push_back(i);
91 }
92 current = interpolations[i];
93 }
94 }
95 if (interpolations.size() >= 2 &&
96 interpolations.at(interpolations.size() - 1) == eSplineInterpolation &&
97 interpolations.at(interpolations.size() - 2) != eSplineInterpolation)
98 {
99 interpolations.pop_back();
100 interpolations.push_back(eLinearInterpolation);
101 }
102 //mark parts of the Interpolaion where it changes
103 /*InterpolationType current = interpolations.at(0);
104 for (unsigned int i = 1; i < interpolations.size(); i++)
105 {
106 if (current != interpolations.at(i))
107 {
108 int prev = interPolationChangePoints.back();
109 //A splineInterpolation needs 3 Points or more to be a valid spline Interpolation
110 if (i - prev < 2 && interpolations.at(prev + 1) == InterpolationType::eSplineInterpolation && interpolations.at(i) == InterpolationType::eSplineInterpolation)
111 {
112 throw new exceptions::local::NoInterpolationPossibleException(3, 2);
113 }
114 interPolationChangePoints.push_back(i);
115 current = interpolations[i];
116 }
117 }*/
118 //Produce the InterpolationSegments and add them to producedInterpolationsVector
119 for (unsigned int j = 1; j < interPolationChangePoints.size(); j++)
120 {
121 std::vector<PoseBasePtr> currentCP = std::vector<PoseBasePtr>();
122 for (int i = interPolationChangePoints.at(j - 1); i <= interPolationChangePoints.at(j); i++)
123 {
124 currentCP.push_back(controlPoints.at(i));
125 }
126 std::vector<AbstractInterpolationPtr> temp;
127 switch (interpolations.at(interPolationChangePoints.at(j - 1)))
128 {
130 temp = produceLinearInterpolationSegments(currentCP);
131 break;
133 temp = produceSplineInterpolationSegments(currentCP);
134 break;
135 }
136 producedInterpolations.insert(producedInterpolations.end(), temp.begin(), temp.end());
137 }
138
139 std::vector<PoseBasePtr> currentCP = std::vector<PoseBasePtr>();
140 for (unsigned int i = interPolationChangePoints.at(interPolationChangePoints.size() - 1);
141 i < controlPoints.size();
142 i++)
143 {
144 currentCP.push_back(controlPoints.at(i));
145 }
146 std::vector<AbstractInterpolationPtr> temp;
147 switch (interpolations.at(interpolations.size() - 1))
148 {
150 temp = produceLinearInterpolationSegments(currentCP);
151 break;
153 temp = produceSplineInterpolationSegments(currentCP);
154 break;
155 }
156 producedInterpolations.insert(producedInterpolations.end(), temp.begin(), temp.end());
157 return producedInterpolations;
158}
159
160std::vector<AbstractInterpolationPtr>
162 std::vector<PoseBasePtr> controlPoints)
163{
164 std::vector<AbstractInterpolationPtr> producedInterpolations =
165 std::vector<AbstractInterpolationPtr>();
166 for (unsigned int i = 0; i < controlPoints.size() - 1; i++)
167 {
168 std::vector<PoseBasePtr> currentCP = std::vector<PoseBasePtr>();
169 currentCP.push_back(controlPoints.at(i));
170 currentCP.push_back(controlPoints.at(i + 1));
171 AbstractInterpolationPtr interpolation =
172 std::shared_ptr<AbstractInterpolation>(new LinearInterpolation(currentCP));
173 producedInterpolations.push_back(interpolation);
174 }
175 return producedInterpolations;
176}
177
178std::vector<AbstractInterpolationPtr>
180 std::vector<PoseBasePtr> controlPoints)
181{
182 std::vector<AbstractInterpolationPtr> producedInterpolations =
183 std::vector<AbstractInterpolationPtr>();
184 SplineInterpolationPtr parent = *new std::shared_ptr<SplineInterpolation>(
185 new SplineInterpolation(controlPoints)); //das hier muss genauso aussehen
186
187 for (unsigned int i = 0; i < controlPoints.size() - 1; i++)
188 {
189 AbstractInterpolationPtr interpolation =
190 std::shared_ptr<AbstractInterpolation>(parent->getInterPolationSegment(i));
191 producedInterpolations.push_back(interpolation);
192 }
193 return producedInterpolations;
194}
195
198 std::vector<PoseBasePtr> controlPoints,
199 PoseBasePtr segmentStart)
200{
201 SplineInterpolationPtr parent = *new std::shared_ptr<SplineInterpolation>(
202 new SplineInterpolation(controlPoints)); //das hier muss genauso aussehen
203
204 AbstractInterpolationPtr interpolation =
205 std::shared_ptr<AbstractInterpolation>(parent->getInterPolationSegment(segmentStart));
206
207 return interpolation;
208}
209
210//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
211/// \brief InterpolationSegmentFactory::optimizeControlPoints
212/// \param controlPoints
213/// \param selections
214/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
215void
217 std::vector<PoseBasePtr>& controlPoints,
218 std::vector<IKSolver::CartesianSelection>& selections)
219{
220 /*for(PoseBasePtr pose: controlPoints) {
221 ARMARX_WARNING << Pose(pose->position, pose->orientation).toEigen();
222 }
223 for(IKSolver::CartesianSelection sel: selections) {
224 ARMARX_WARNING << std::to_string(sel);
225 }*/
226
227 for (unsigned int i = 0; i < selections.size() - 1; i++)
228 {
229 //ARMARX_INFO << "OPTIMIZE";
230 if (InterpolationSegmentFactory::isDominantOver(selections[i + 1], selections[i]))
231 {
232 std::vector<IKSolver::CartesianSelection> followingDominations =
233 std::vector<IKSolver::CartesianSelection>();
234 followingDominations.push_back(selections[i + 1]);
235 int followingDominationsStart = i;
236 bool isBreaking;
237 do
238 {
239 //look left until an equal or fully dominating cartesian selection appears
240 for (int j = i; j >= 0; j--)
241 {
243 selections[i + 1]) &&
245 selections[j])) ||
246 selections[i + 1] == selections[j])
247 {
248
249 //ARMARX_INFO << std::to_string(selections[j]) + " is dominant over " + std::to_string(selections[i + 1]);
250 followingDominationsStart = j + 1;
251
252 int dominanceIntervalSize = i + 1 - j;
253 PoseBasePtr dominanceIntervalStart = controlPoints[j];
254 PoseBasePtr dominanceIntervalEnd = controlPoints[i + 1];
255 std::vector<AbstractInterpolationPtr> li =
257 {dominanceIntervalStart, dominanceIntervalEnd});
258 int counter = 1;
259 for (unsigned int k = j + 1; k < i + 1; k++)
260 {
261 controlPoints[k] = optimizePose(
262 controlPoints[k],
263 li[0]->getPoseAt(double(1.0 / dominanceIntervalSize) * counter),
264 selections[k],
265 selections[i + 1]);
266 counter++;
267 //ARMARX_INFO << std::to_string(double(1.0 / dominanceIntervalSize) * k) + " SET POINT AT------" + std::to_string(k) + " with " + std::to_string(selections[i + 1]);
268 }
269 break;
270 }
271 followingDominations.push_back(selections[j]);
272 }
273
274 if (i + 2 < selections.size() &&
275 isDominantOver(selections[i + 2], selections[i + 1]))
276 {
277 isBreaking = false;
278 i++;
279 followingDominations.push_back(selections[i + 1]);
280 }
281 else
282 {
283 isBreaking = true;
284 }
285
286 } while (!isBreaking);
287 /*ARMARX_WARNING << "FOLLOWING DOMINATIONS START ";
288 for(IKSolver::CartesianSelection sel: followingDominations) {
289 ARMARX_WARNING << std::to_string(sel);
290 }
291 ARMARX_WARNING << "FOLLOWING DOMINATIONS END ";*/
292 IKSolver::CartesianSelection dominatingSelection =
293 getSmallestDominating(followingDominations);
294 for (unsigned int m = followingDominationsStart; m <= i + 1; m++)
295 {
296 //ARMARX_WARNING << "SET SELECTION " + std::to_string(m) + " with " + std::to_string(dominatingSelection);
297 selections[m] = dominatingSelection;
298 //selections[m] = IKSolver::CartesianSelection::All;
299 }
300 }
301 //ARMARX_INFO << "Optimizing done";
302 }
303 ARMARX_INFO << "Optimizing done";
304
305 /*ARMARX_WARNING << "RESULT XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
306 for(PoseBasePtr pose: controlPoints) {
307 ARMARX_WARNING << Pose(pose->position, pose->orientation).toEigen();
308 }
309 for(IKSolver::CartesianSelection sel: selections) {
310 ARMARX_WARNING << std::to_string(sel);
311 }*/
312}
313
314bool
315InterpolationSegmentFactory::needsOptimizing(std::vector<IKSolver::CartesianSelection>& selections)
316{
317 for (unsigned int i = 0; i < selections.size() - 1; i++)
318 {
319 //ARMARX_INFO << "NEEDS OPTIMIZING";
320 if (InterpolationSegmentFactory::isDominantOver(selections[i + 1], selections[i]))
321 {
322 return true;
323 }
324 }
325 return false;
326}
327
328bool
329InterpolationSegmentFactory::isDominantOver(VirtualRobot::IKSolver::CartesianSelection current,
330 VirtualRobot::IKSolver::CartesianSelection other)
331{
332 if (other == IKSolver::CartesianSelection::X || other == IKSolver::CartesianSelection::Y ||
333 other == IKSolver::CartesianSelection::Z ||
334 other == IKSolver::CartesianSelection::Orientation)
335 {
336 return current != other;
337 }
338 else if (other == IKSolver::CartesianSelection::Position)
339 {
340 return (current == IKSolver::CartesianSelection::Orientation ||
341 current == IKSolver::CartesianSelection::All);
342 }
343 return false;
344}
345
346IKSolver::CartesianSelection
348 std::vector<VirtualRobot::IKSolver::CartesianSelection> selections)
349{
350 bool isInhomogenous = false;
351 ARMARX_INFO << "Vector start";
352 int max = 0;
353 for (IKSolver::CartesianSelection current : selections)
354 {
355 if (current > max)
356 {
357 ARMARX_INFO << "In Vector" + std::to_string(current);
358 max = current;
359 }
360 if (max != 0 && current != max)
361 {
362 isInhomogenous = true;
363 }
364 }
365 if (max <= 4 && isInhomogenous)
366 {
367 ARMARX_INFO << "SMALLEST DOMINATING" +
368 std::to_string(IKSolver::CartesianSelection::Position);
369 return IKSolver::CartesianSelection::Position;
370 }
371 else if (max == IKSolver::CartesianSelection::Orientation)
372 {
373 for (IKSolver::CartesianSelection currentSelection : selections)
374 {
375 if (currentSelection != IKSolver::CartesianSelection::Orientation)
376 {
377 ARMARX_INFO << "SMALLEST DOMINATING" +
378 std::to_string(IKSolver::CartesianSelection::All);
379 return IKSolver::CartesianSelection::All;
380 }
381 }
382 ARMARX_INFO << "SMALLEST DOMINATING" +
383 std::to_string(IKSolver::CartesianSelection::Orientation);
384 return IKSolver::CartesianSelection::Orientation;
385 }
386 else
387 {
388 ARMARX_INFO << "SMALLEST DOMINATING" + std::to_string(max);
389 return static_cast<IKSolver::CartesianSelection>(max);
390 }
391}
392
393PoseBasePtr
395 PoseBasePtr corrected,
396 IKSolver::CartesianSelection selectionOriginal,
397 IKSolver::CartesianSelection selectionCorrecting)
398{
399 //ARMARX_WARNING << Pose(original->position, original->orientation).toEigen();
400 //ARMARX_WARNING << Pose(corrected->position, corrected->orientation).toEigen();
401 PoseBasePtr firstStep;
402 switch (selectionCorrecting)
403 {
404 case (IKSolver::CartesianSelection::X):
405 firstStep = PoseBasePtr(
406 new Pose(Vector3BasePtr(new Vector3(
407 corrected->position->x, original->position->y, original->position->z)),
408 original->orientation));
409 case (IKSolver::CartesianSelection::Y):
410 firstStep = PoseBasePtr(
411 new Pose(Vector3BasePtr(new Vector3(
412 original->position->x, corrected->position->y, original->position->z)),
413 original->orientation));
414 case (IKSolver::CartesianSelection::Z):
415 firstStep = PoseBasePtr(
416 new Pose(Vector3BasePtr(new Vector3(
417 original->position->x, original->position->y, corrected->position->z)),
418 original->orientation));
419 case (IKSolver::CartesianSelection::Position):
420 firstStep = PoseBasePtr(new Pose(corrected->position, original->orientation));
421 case (IKSolver::CartesianSelection::Orientation):
422 firstStep = PoseBasePtr(new Pose(original->position, corrected->orientation));
423 case (IKSolver::CartesianSelection::All):
424 //ARMARX_WARNING << "CORRECTED ALL";
425 firstStep = corrected;
426 }
427 switch (selectionOriginal)
428 {
429 case (IKSolver::CartesianSelection::X):
430 return PoseBasePtr(new Pose(Vector3BasePtr(new Vector3(original->position->x,
431 firstStep->position->y,
432 firstStep->position->z)),
433 firstStep->orientation));
434 case (IKSolver::CartesianSelection::Y):
435 return PoseBasePtr(new Pose(Vector3BasePtr(new Vector3(firstStep->position->x,
436 original->position->y,
437 firstStep->position->z)),
438 firstStep->orientation));
439 case (IKSolver::CartesianSelection::Z):
440 return PoseBasePtr(new Pose(Vector3BasePtr(new Vector3(firstStep->position->x,
441 firstStep->position->y,
442 original->position->z)),
443 firstStep->orientation));
444 case (IKSolver::CartesianSelection::Position):
445 return PoseBasePtr(new Pose(original->position, firstStep->orientation));
446 case (IKSolver::CartesianSelection::Orientation):
447 return PoseBasePtr(new Pose(firstStep->position, original->orientation));
448 case (IKSolver::CartesianSelection::All):
449 return original;
450 default:
451 return corrected;
452 }
453}
static std::vector< AbstractInterpolationPtr > produceInterpolationSegments(std::vector< PoseBasePtr > controlPoints, std::vector< InterpolationType > interpolations)
produceInterpolationSegments constructs a vector of AbstractInterpolation the concrete Interpolationt...
static bool needsOptimizing(std::vector< VirtualRobot::IKSolver::CartesianSelection > &selections)
needsOptimizing returns true if there is a CartesianSelection at i that dominates a CartesianSelectio...
static bool isDominantOver(VirtualRobot::IKSolver::CartesianSelection current, VirtualRobot::IKSolver::CartesianSelection other)
isDominantOver returns true when current selection dominates other selection Definition: A CartesianS...
static AbstractInterpolationPtr produceSplineInterpolationSegment(std::vector< PoseBasePtr > controlPoints, PoseBasePtr segmentStart)
produceSplineInterpolationSegment constructs the splineInterpolationSegment of a splineInterpolation ...
static PoseBasePtr optimizePose(armarx::PoseBasePtr original, armarx::PoseBasePtr corrected, VirtualRobot::IKSolver::CartesianSelection selectionOriginal, VirtualRobot::IKSolver::CartesianSelection selectionCorrected)
optimizePose changes the original pose so that the interpolation is smove when it changes from select...
static void optimizeControlPoints(std::vector< PoseBasePtr > &controlPoints, std::vector< VirtualRobot::IKSolver::CartesianSelection > &selections)
optimizeControlPoints changes the cartian selections and control points so that the IKSolving produce...
static std::vector< AbstractInterpolationPtr > produceSplineInterpolationSegments(std::vector< PoseBasePtr > controlPoints)
produceInterpolationSegments constructs a vector of SplineInterpolations
static VirtualRobot::IKSolver::CartesianSelection getSmallestDominating(std::vector< VirtualRobot::IKSolver::CartesianSelection > selections)
getSmallestDominating returns the cartesian selection that dominates all other cartesian selections i...
static std::vector< AbstractInterpolationPtr > produceLinearInterpolationSegments(std::vector< PoseBasePtr > controlPoints)
produceInterpolationSegments constructs a vector of LinearInterpolations
The LinearInterpolation class represents a linear Interpolation between a series of control points Li...
The Pose class.
Definition Pose.h:243
The SplineInterpolation class represents a linear Interpolation between a series of control points Sp...
The Vector3 class.
Definition Pose.h:113
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
This file offers overloads of toIce() and fromIce() functions for STL container types.
InterpolationType
The InterpolationType enum lists all available interpolation types eLinearInterpolation: represents l...
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)
std::shared_ptr< SplineInterpolation > SplineInterpolationPtr
std::shared_ptr< AbstractInterpolation > AbstractInterpolationPtr