DesignerTrajectoryManager.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2015-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 ArmarXGuiPlugins::RobotTrajectoryDesigner::Manager
19 * @author Luca Quaer
20 * @date 2018
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
26
27using namespace armarx;
28
29////////////////////////////////////////////////////////////////////////////////////////////
30/// Struct-functions
31////////////////////////////////////////////////////////////////////////////////////////////
32
33void
34DesignerTrajectoryManager::ManipulationInterval::addFirstUserWaypoint(UserWaypointPtr uw)
35{
36 userWaypointsList.push_back(uw);
37}
38
39void
40DesignerTrajectoryManager::ManipulationInterval::pushFront(UserWaypointPtr uw, TransitionPtr t)
41{
42 userWaypointsList.push_front(uw);
43 transitionsList.push_front(t);
44 lowerIntervalLimit--;
45}
46
47void
48DesignerTrajectoryManager::ManipulationInterval::pushBack(UserWaypointPtr uw, TransitionPtr t)
49{
50 userWaypointsList.push_back(uw);
51 transitionsList.push_back(t);
52 upperIntervalLimit++;
53}
54
55void
56DesignerTrajectoryManager::ManipulationInterval::addBreakpointIndex(int index)
57{
58 breakpointIndicesSet.insert(index);
59}
60
61void
62DesignerTrajectoryManager::ManipulationInterval::finishSearch()
63{
64 // copy userWaypointsList to userWaypoints vector
65 userWaypoints.reserve(userWaypointsList.size());
66 std::copy(
67 userWaypointsList.begin(), userWaypointsList.end(), std::back_inserter(userWaypoints));
68
69 // copy transitionsList to transitions vector
70 transitions.reserve(transitionsList.size());
71 std::copy(transitionsList.begin(), transitionsList.end(), std::back_inserter(transitions));
72
73 // copy breakpointInicesSet to breakpointIndices vector
74 breakpointIndices.reserve(breakpointIndicesSet.size());
75 std::copy(breakpointIndicesSet.begin(),
76 breakpointIndicesSet.end(),
77 std::back_inserter(breakpointIndices));
78}
79
81DesignerTrajectoryManager::ManipulationInterval::getUserWaypointByRealIndex(unsigned int i) const
82{
83 if (i - lowerIntervalLimit < userWaypoints.size())
84 {
85 return userWaypoints[i - lowerIntervalLimit];
86 }
87 else
88 {
89 // modify Exception?
90 throw OutOfRangeException();
91 }
92}
93
95DesignerTrajectoryManager::ManipulationInterval::getUserWaypointByZeroBasedIndex(
96 unsigned int i) const
97{
98 if (i < userWaypoints.size())
99 {
100 return userWaypoints[i];
101 }
102 else
103 {
104 // modify Exception?
105 throw OutOfRangeException();
106 }
107}
108
110DesignerTrajectoryManager::ManipulationInterval::getTransitionByRealIndex(unsigned int i) const
111{
112 if (i - lowerIntervalLimit < transitions.size())
113 {
114 return transitions[i - lowerIntervalLimit];
115 }
116 else
117 {
118 // modify Exception?
119 throw OutOfRangeException();
120 }
121}
122
124DesignerTrajectoryManager::ManipulationInterval::getTransitionByZeroBasedIndex(unsigned int i) const
125{
126 if (i < transitions.size())
127 {
128 return transitions[i];
129 }
130 else
131 {
132 // modify Exception?
133 throw OutOfRangeException();
134 }
135}
136
137std::vector<std::vector<double>>
138DesignerTrajectoryManager::ManipulationInterval::getUserWaypointsIKSolutions(
139 std::vector<std::vector<double>>& ikSolutions,
140 unsigned int intervalStart,
141 unsigned int intervalEnd)
142{
143 std::vector<std::vector<double>> result;
144 for (unsigned int& newIndex : newIndexOfUserWaypoint)
145 {
146 if (newIndex < intervalStart)
147 {
148 continue;
149 }
150 if (newIndex > intervalEnd)
151 {
152 break;
153 }
154
155 result.push_back(ikSolutions[newIndex]);
156 }
157 return result;
158}
159
160void
161DesignerTrajectoryManager::ManipulationInterval::applyJointAnglesOfUserWaypoints(
162 std::vector<std::vector<double>> ikSolution)
163{
164 std::vector<std::vector<double>> jointAngles = getUserWaypointsIKSolutions(
165 ikSolution, newIndexOfUserWaypoint[0], newIndexOfUserWaypoint[userWaypoints.size() - 1]);
166
167 int count = 0;
168 for (UserWaypointPtr w : userWaypoints)
169 {
170 w->setJointAngles(jointAngles[count++]);
171 }
172}
173
174////////////////////////////////////////////////////////////////////////////////////////////////////
175/// Auxiliary functions
176////////////////////////////////////////////////////////////////////////////////////////////////////
177
178void
179DesignerTrajectoryManager::saveState()
180{
181 //cut off the last mementos behind the current memento
182 if (mementos.currentMemento < mementos.mementoList.size() - 1)
183 {
184 mementos.mementoList.resize(mementos.currentMemento + 1);
185 }
186
187 if (designerTrajectory)
188 {
189 mementos.mementoList.push_back(
190 std::shared_ptr<DesignerTrajectory>(new DesignerTrajectory(*designerTrajectory)));
191 }
192 else
193 {
194 mementos.mementoList.push_back(nullptr);
195 }
196
197 //if the size of the list is bigger than the MEMENTO_MAX, it just delete the first
198 //(oldest) memento
199 if (mementos.mementoList.size() > MEMENTO_MAX)
200 {
201 mementos.mementoList.pop_front();
202 }
203 else
204 {
205 mementos.currentMemento++;
206 }
207}
208
209DesignerTrajectoryManager::ManipulationInterval
210DesignerTrajectoryManager::calculateManipulationInterval(unsigned int manipulationIndex)
211{
212 DesignerTrajectoryPtr& dt = designerTrajectory;
213 ManipulationInterval mi;
214
215 // set start upper- and lowerIntervalLimit to manipulationIndex
216 mi.lowerIntervalLimit = manipulationIndex;
217 mi.upperIntervalLimit = manipulationIndex;
218
219 // add UserWaypoint with index = manipulationIndex to ManipulationInterval
220 mi.addFirstUserWaypoint(dt->getUserWaypoint(manipulationIndex));
221
222 // add index of first user waypoint if it is a breakepoint
223 if (dt->getUserWaypoint(manipulationIndex)->getIsTimeOptimalBreakpoint())
224 {
225 mi.addBreakpointIndex(manipulationIndex);
226 }
227
228 // search upwards
229 for (unsigned int i = manipulationIndex + 1; i < dt->getNrOfUserWaypoints(); i++)
230 {
231 UserWaypointPtr tmpUwp = dt->getUserWaypoint(i);
232 TransitionPtr tmpTrans = dt->getTransition(i - 1);
233 mi.pushBack(tmpUwp, tmpTrans);
234
235 if (tmpUwp->getIsTimeOptimalBreakpoint())
236 {
237 mi.addBreakpointIndex(i);
238
239 /*
240 if (dt->getTransition(i - 1)->getInterpolationType()
241 != dt->getTransition(i)->getInterpolationType())
242 {
243 break;
244 }
245 */
246 }
247 }
248
249 // search downwards
250 for (unsigned int i = manipulationIndex - 1; i != static_cast<unsigned>(-1); i--)
251 {
252 UserWaypointPtr tmpUwp = dt->getUserWaypoint(i);
253 TransitionPtr tmpTrans = dt->getTransition(i);
254 mi.pushFront(tmpUwp, tmpTrans);
255
256 if (tmpUwp->getIsTimeOptimalBreakpoint())
257 {
258 mi.addBreakpointIndex(i);
259
260 /*
261 if (dt->getTransition(i - 1)->getInterpolationType()
262 != dt->getTransition(i)->getInterpolationType())
263 {
264 break;
265 }
266 */
267 }
268 }
269
270 // add first and last point to breakpointIndicesSet if they are not included already
271 mi.addBreakpointIndex(mi.lowerIntervalLimit);
272 mi.addBreakpointIndex(mi.upperIntervalLimit);
273 mi.finishSearch();
274
275 return mi;
276}
277
278std::vector<AbstractInterpolationPtr>
279DesignerTrajectoryManager::getInterpolationObjects(ManipulationInterval& mi)
280{
281 std::vector<PoseBasePtr> poses;
282 for (UserWaypointPtr& uwp : mi.userWaypoints)
283 {
284 poses.push_back(uwp->getPose());
285 }
286
287 std::vector<InterpolationType> interpolationTypes;
288 for (TransitionPtr& tp : mi.transitions)
289 {
290 interpolationTypes.push_back(tp->getInterpolationType());
291 }
292
293 return InterpolationSegmentFactory::produceInterpolationSegments(poses, interpolationTypes);
294}
295
296void
297DesignerTrajectoryManager::calculateInterpolatedPoints(
298 std::vector<AbstractInterpolationPtr> interpolationObjects,
299 unsigned int fps,
300 ManipulationInterval& mi)
301{
302 // requirement: time in seconds !!!!
303
304 // treat first point (with time 0.0) seperately
305 ////mi.interpolatedPoses.push_back(interpolationObjects[0]->getPoseAt(0.0));
306 ////mi.newIndexOfUserWaypoint.push_back(0);
307
308 // calculate all timestamps and add the poses accordingly
309 for (unsigned int i = 0; i < mi.transitions.size(); i++)
310 {
311 std::vector<double> timestamps;
312
313 // check if transition is linear interpolated (no need to calculate further points between)
314 // get the transition
315 TransitionPtr tmpTransition = mi.getTransitionByZeroBasedIndex(i);
316
317 // calculate total frame count (how many frames to insert between 2 userwaypoints)
318 //unsigned int totalFrameCount = tmpTransition->getUserDuration() * fps;
319 unsigned int totalFrameCount = tmpTransition->getTimeOptimalDuration() * fps;
320
321 if (totalFrameCount == 0)
322 {
323 totalFrameCount = DEFAULT_FRAME_COUNT;
324 }
325
326 if (totalFrameCount > 1)
327 {
328 // calculate the increment value to get evenly distributed timestamps
329 double increment = 1.0 / (totalFrameCount - 1);
330
331 // starting at k = 1 jumps the 0.0 timestamp in every transition
332 ////for (unsigned int k = 1; k < totalFrameCount; k++)
333 for (unsigned int k = 0; k < totalFrameCount; k++)
334 {
335 timestamps.push_back(k * increment);
336 }
337 }
338 else
339 {
340 timestamps.push_back(0.0);
341 timestamps.push_back(1.0);
342 }
343
344
345 std::vector<PoseBasePtr> tmpInterpolatedPositions;
346 for (double timestamp : timestamps)
347 {
348 ////mi.interpolatedPoses.push_back(interpolationObjects[i]->getPoseAt(timestamp));
349 tmpInterpolatedPositions.push_back(interpolationObjects[i]->getPoseAt(timestamp));
350 }
351
352 mi.interpolatedTransitions.push_back(tmpInterpolatedPositions);
353 tmpInterpolatedPositions.clear();
354
355 // add the index of the last pose, which originated from an userwaypoint, to the
356 // newIndexOfUserWaypoint vector
357 ////mi.newIndexOfUserWaypoint.push_back(mi.interpolatedPoses.size() - 1);
358 }
359}
360
361bool
362DesignerTrajectoryManager::checkTransitionReachability(ManipulationInterval& mi,
363 unsigned int transitionIndex)
364{
365 for (PoseBasePtr pose : mi.interpolatedTransitions[transitionIndex])
366 {
367 continue;
368 //if (!kin->isReachable(rns, pose))
369
370 //provisorisch
371 if (!kinSolver->isReachable(rns, pose, VirtualRobot::IKSolver::Position))
372 {
373 return false;
374 }
375 }
376
377 return true;
378}
379
380std::vector<std::vector<double>>
381DesignerTrajectoryManager::calculateIKSolutions(ManipulationInterval& mi)
382{
383 // IKSolutions
384 std::vector<std::vector<double>> ikSolutions;
385 ikSolutions.push_back(mi.userWaypoints[0]->getJointAngles());
386
387 // the new index of userwaypoint 0 is 0
388 mi.newIndexOfUserWaypoint.push_back(0);
389
390 // motion planning insertion indices
391 std::vector<InsertTransition> mpInserts;
392
393 for (unsigned int transitionIndex = 0; transitionIndex < mi.interpolatedTransitions.size();
394 transitionIndex++)
395 {
396 if (!checkTransitionReachability(mi, transitionIndex))
397 {
398 // this transition is not reachable
399 InsertTransition mpInsert;
400 mpInsert.transitionIndex = transitionIndex;
401 mpInsert.insertionIndex = ikSolutions.size() - 1; //destinations.size() - 1;
402 mpInserts.push_back(mpInsert);
403
404 //calculate IKSolution (jump to end point of this transition)
405 std::vector<double> start = {ikSolutions.back()};
406
407 std::vector<PoseBasePtr> destinations = {
408 mi.interpolatedTransitions[transitionIndex].back()};
409
410 std::vector<VirtualRobot::IKSolver::CartesianSelection> selections = {
411 mi.userWaypoints[transitionIndex + 1]->getIKSelection()};
412
413 std::vector<std::vector<double>> tmpIkSolutions =
414 kinSolver->solveRecursiveIKRelative(rns, start, destinations, selections);
415
416 // insert tmpIkSolutions into ikSolutions
417 ikSolutions.insert(ikSolutions.end(), tmpIkSolutions.begin(), tmpIkSolutions.end());
418
419 // the new index of the userwaypoint transitionIndex+1 is set later
420 // when inserting motion planning results into ikSolutions
421 // reserve place in vector
422 mi.newIndexOfUserWaypoint.push_back(-1);
423
424 continue;
425 }
426
427 // this transition is reachable
428 // calculate IKSolution of this transition
429 // get start
430 std::vector<double> start = {ikSolutions.back()};
431
432 // get destinations: all poses from interpolatedTransition except for the first
433 std::vector<PoseBasePtr> destinations(mi.interpolatedTransitions[transitionIndex].begin() +
434 1,
435 mi.interpolatedTransitions[transitionIndex].end());
436
437 // get selection
438 std::vector<VirtualRobot::IKSolver::CartesianSelection> selections;
439
440 // |destinations| - 1 times do:
441 for (unsigned int i = 1; i < destinations.size(); i++)
442 {
443 selections.push_back(mi.userWaypoints[transitionIndex + 1]->getIKSelection());
444 }
445
446 // for last destination: get real IKSelection of UserWaypoint
447 selections.push_back(mi.userWaypoints[transitionIndex + 1]->getIKSelection());
448
449 // call ikSolver
450 std::vector<std::vector<double>> tmpIkSolutions =
451 kinSolver->solveRecursiveIKRelative(rns, start, destinations, selections);
452 // END: calculate IKSolution of this transition
453
454 // check for tmpIkSolutions for collision
455
456 // this transition is reachable and has no collisions
457 // insert tmpIkSolutions into ikSolutions
458 ikSolutions.insert(ikSolutions.end(), tmpIkSolutions.begin(), tmpIkSolutions.end());
459 // save the new index of the userwaypoint with index transitionIndex + 1
460 mi.newIndexOfUserWaypoint.push_back(ikSolutions.size() - 1);
461 }
462 return ikSolutions;
463}
464
465std::vector<TimedTrajectory>
466DesignerTrajectoryManager::calculateTimeOptimalTrajectories(
467 std::vector<std::vector<double>> ikSolutions,
468 ManipulationInterval& mi)
469{
470 std::vector<TimedTrajectory> result;
471
472 for (unsigned int i = 0; i < mi.breakpointIndices.size() - 1; i++)
473 {
474 /*
475 * mi.breakpointIndices are the indices before the interpolated points were inserted.
476 */
477 int intervalStart = mi.breakpointIndices[i];
478 int intervalEnd = mi.breakpointIndices[i + 1];
479 std::vector<std::vector<double>> ikSolutionsInterval(
480 ikSolutions.begin() + mi.newIndexOfUserWaypoint[intervalStart],
481 ikSolutions.begin() + 1 + mi.newIndexOfUserWaypoint[intervalEnd]);
482
483 /*
484 * Because intervalStart/intervalEnd are the breakpoint indices BEFORE interpolated
485 * points were inserted,
486 * their new index (retrieved with mi.newIndexOfUserWaypoint[...]) is needed as parameter
487 * for the function mi.getUserWaypointsIKSolutions(..., ..., ...)
488 */
489 std::vector<std::vector<double>> userWaypointsIKSolution =
490 mi.getUserWaypointsIKSolutions(ikSolutions,
491 mi.newIndexOfUserWaypoint[intervalStart],
492 mi.newIndexOfUserWaypoint[intervalEnd]);
493
494 result.push_back(DesignerTrajectoryCalculator(environment)
495 .calculateTimeOptimalTrajectory(
496 ikSolutionsInterval, userWaypointsIKSolution, rns, MAX_DEVIATION));
497 }
498
499 return result;
500}
501
502bool
504{
505 if (mementos.currentMemento != 0)
506 {
507 if (*(std::next(mementos.mementoList.begin(), mementos.currentMemento - 1)))
508 {
509 designerTrajectory = DesignerTrajectoryPtr(new DesignerTrajectory(
510 *(*(std::next(mementos.mementoList.begin(), mementos.currentMemento - 1)))));
511 isInitialized = true;
512 }
513 else
514 {
515 isInitialized = false;
516 }
517 mementos.currentMemento--;
518 return true;
519 }
520 else
521 {
522 return false;
523 }
524}
525
526bool
528{
529 if (mementos.currentMemento < mementos.mementoList.size() - 1)
530 {
531 if (*std::next(mementos.mementoList.begin(), mementos.currentMemento + 1))
532 {
533 designerTrajectory = DesignerTrajectoryPtr(new DesignerTrajectory(
534 *(*(std::next(mementos.mementoList.begin(), mementos.currentMemento + 1)))));
535 }
536 else
537 {
538 isInitialized = false;
539 }
540
541 mementos.currentMemento++;
542 return true;
543 }
544 else
545 {
546 return false;
547 }
548}
549
550bool
552{
553 return isInitialized;
554}
555
556void
557DesignerTrajectoryManager::theUniversalMethod(unsigned int index)
558{
559 if (designerTrajectory->getNrOfUserWaypoints() > 1)
560 {
561 //calculate ikSolution of mainpulation intervall//////////////////////////////////////
562 ManipulationInterval mi = calculateManipulationInterval(index);
563
564 // poses
565 std::vector<PoseBasePtr> poses;
566 std::vector<PoseBasePtr> posesBackup;
567
568 // selections
569 std::vector<VirtualRobot::IKSolver::CartesianSelection> selections;
570 std::vector<VirtualRobot::IKSolver::CartesianSelection> selectionsBackup;
571
572 for (UserWaypointPtr uwp : mi.userWaypoints)
573 {
574 poses.push_back(uwp->getPose());
575 posesBackup.push_back(PoseBasePtr(
576 new Pose(Pose(uwp->getPose()->position, uwp->getPose()->orientation).toEigen())));
577 selections.push_back(uwp->getIKSelection());
578 selectionsBackup.push_back(uwp->getIKSelection());
579 }
580
582 {
584 }
585
586 std::vector<InterpolationType> interpolations;
587 for (TransitionPtr trans : mi.transitions)
588 {
589 interpolations.push_back(trans->getInterpolationType());
590 }
591 int count = 0;
592 for (UserWaypointPtr uwp : mi.userWaypoints)
593 {
594 uwp->setPose(poses[count]);
595 uwp->setIKSelection(selections[count]);
596 count++;
597 }
598
599 calculateInterpolatedPoints(
601 DEFAULT_FRAME_COUNT,
602 mi);
603 //calculateInterpolatedPoints(getInterpolationObjects(mi), DEFAULT_FRAME_COUNT, mi);
604
605 //bool motionPlanningCalled = false;
606
607 std::vector<std::vector<double>> ikSolutions = calculateIKSolutions(mi);
608
609 count = 0;
610 for (UserWaypointPtr uwp : mi.userWaypoints)
611 {
612 uwp->setIKSelection(selectionsBackup[count]);
613 uwp->setPose(posesBackup[count]);
614 count++;
615 }
616
617 //Set the JointAngles of the UserWaypoints////////////////////////////////////////////
618 mi.applyJointAnglesOfUserWaypoints(ikSolutions);
619
620 //set interBreakpointsTrajectories////////////////////////////////////////////////////
621 std::vector<TimedTrajectory> timedTrajectories =
622 calculateTimeOptimalTrajectories(ikSolutions, mi);
623 //search how many interBreakPointTrajectories are behind and before the new
624 //interBreakpointTrajectories
625 int countBefore = 0;
626 int countAfter = 0;
627 if (mi.lowerIntervalLimit != 0)
628 {
629 countBefore++;
630 for (unsigned int i = mi.lowerIntervalLimit - 1; i > 0; i--)
631 {
632 if (designerTrajectory->getUserWaypoint(i)->getIsTimeOptimalBreakpoint())
633 {
634 countBefore++;
635 }
636 }
637 }
638
639 if (mi.upperIntervalLimit != designerTrajectory->getNrOfUserWaypoints() - 1)
640 {
641 countAfter++;
642 for (unsigned int i = mi.upperIntervalLimit + 1;
643 i < designerTrajectory->getNrOfUserWaypoints() - 1;
644 i++)
645 {
646 countAfter++;
647 }
648 }
649
650 std::vector<TrajectoryPtr> InterBreakPointTrajectories =
651 designerTrajectory->getInterBreakpointTrajectories();
652 std::vector<TrajectoryPtr> newInterBreakPointTrajectories;
653 newInterBreakPointTrajectories.insert(newInterBreakPointTrajectories.end(),
654 InterBreakPointTrajectories.begin(),
655 InterBreakPointTrajectories.begin() + countBefore);
656
657 // set new inter breakpoint trajectories
658 for (TimedTrajectory& t : timedTrajectories)
659 {
660 TrajectoryPtr traj = t.getTrajectory();
661 newInterBreakPointTrajectories.push_back(traj);
662 }
663
664 newInterBreakPointTrajectories.insert(newInterBreakPointTrajectories.end(),
665 InterBreakPointTrajectories.end() - countAfter,
666 InterBreakPointTrajectories.end());
667 designerTrajectory->setInterBreakpointTrajectories(newInterBreakPointTrajectories);
668
669 //set newTimeOptimalDuration of each Transition///////////////////////////////////////
670 //and timeOptimalTimestamp of each UserWaypoint///////////////////////////////////////
671 //and Trajectories of all changed Transitions ////////////////////////////////////////
672 TrajectoryPtr traj = designerTrajectory->getTimeOptimalTrajectory();
673 std::vector<double> timestamps = traj->getTimestamps();
674 unsigned int trajCount = 0;
675
676 //search for the timestamp of first changed point of traj
677 while (trajCount < timestamps.size() &&
678 designerTrajectory->getUserWaypoint(mi.breakpointIndices[0])
679 ->getTimeOptimalTimestamp() > timestamps[trajCount])
680 {
681 trajCount++;
682 }
683
684 for (unsigned int t = 0; t < timedTrajectories.size(); t++)
685 {
686 //all timestamps of the userWaypoint of the timedTrajectory
687 std::vector<double> timedUserWaypoints = timedTrajectories[t].getUserPoints();
688
689 if (timedUserWaypoints.size() == 0)
690 {
691 throw InvalidArgumentException();
692 }
693
694 unsigned int count = 0;
695
696 //set timeOptimalDuration of all changed transitions
697 //set timeOptimalTimestamp of all changed userWaypoints
698 for (unsigned int i = mi.breakpointIndices[t]; i < mi.breakpointIndices[t + 1]; i++)
699 {
700 TransitionPtr trans = designerTrajectory->getTransition(i);
701 trans->setTimeOptimalDuration(timedUserWaypoints[count + 1] -
702 timedUserWaypoints[count]);
703 count++;
704 }
705
706
707 //set all Trajectories of changed Transitions
708 for (unsigned int i = mi.breakpointIndices[t]; i < mi.breakpointIndices[t + 1]; i++)
709 {
710 TransitionPtr trans = designerTrajectory->getTransition(i);
711 UserWaypointPtr end = trans->getEnd();
712 unsigned int trajCountEnd = trajCount + 1;
713 std::vector<double> newTimestamps = {0.0};
714 std::vector<std::vector<double>> newTrajData;
715 //add first jointAngles of first timestamp
716 for (unsigned int dim = 0; dim < traj->dim(); dim++)
717 {
718 newTrajData.push_back({traj->getState(timestamps[trajCount], dim)});
719 }
720
721 //add all jointAngles for all timestamps at transition
722 while (trajCountEnd < timestamps.size() &&
723 timestamps[trajCountEnd] < end->getTimeOptimalTimestamp())
724 {
725 newTimestamps.push_back(timestamps[trajCountEnd] - timestamps[trajCount]);
726 for (unsigned int dim = 0; dim < traj->dim(); dim++)
727 {
728 //jointAngles of the dimension
729 newTrajData[dim].push_back(traj->getState(timestamps[trajCountEnd], dim));
730 }
731 trajCountEnd++;
732 }
733 trajCount = trajCountEnd;
735 new Trajectory(newTrajData, newTimestamps, traj->getDimensionNames()));
736 trans->setTrajectory(newTraj);
737 }
738 }
739
740 //shift all timeOptimaltimestamps of the userWaypoints behind last BreakpointIndices
741 //it goes through transitions (getNrOfUserWaypoints - 2 = NrOfTransitions - 1)
742 for (unsigned int i = mi.breakpointIndices.back();
743 i <= designerTrajectory->getNrOfUserWaypoints() - 2;
744 i++)
745 {
746 //the setter of transitions updates the timeOptimalTimestamps of end- and start-
747 //Userwaypoint
748 double time = designerTrajectory->getTransition(i)->getTimeOptimalDuration();
749 designerTrajectory->getTransition(i)->setTimeOptimalDuration(time);
750 }
751
752
753 //update UserTimestamps of all UserWaypoints
754 for (unsigned int i = 0; i < designerTrajectory->getNrOfUserWaypoints() - 2; i++)
755 {
756 double time = designerTrajectory->getTransition(i)->getStart()->getUserTimestamp() +
757 designerTrajectory->getTransition(i)->getUserDuration();
758 designerTrajectory->getTransition(i)->getEnd()->setUserTimestamp(time);
759 }
760 }
761 saveState();
762}
763
764std::vector<double>
765DesignerTrajectoryManager::getNewIkSolutionOfFirstPoint(PoseBasePtr oldStart,
766 PoseBasePtr newStart,
767 std::vector<double> jointAnglesOldStart)
768{
769 //Resolve recursive IK from oldStart to NewStart
770 std::vector<AbstractInterpolationPtr> ip =
772 std::vector<PoseBasePtr> poses;
773 std::vector<VirtualRobot::IKSolver::CartesianSelection> selections;
774
775 for (AbstractInterpolationPtr current : ip)
776 {
777 for (double i = 1; i < DEFAULT_FRAME_COUNT - 1; i = i + 1.0)
778 {
779 poses.push_back(current->getPoseAt(i / DEFAULT_FRAME_COUNT));
780 selections.push_back(VirtualRobot::IKSolver::CartesianSelection::Position);
781 }
782 }
783 poses.push_back(newStart);
784 selections.push_back(VirtualRobot::IKSolver::CartesianSelection::All);
785 std::vector<std::vector<double>> ikSolutions =
786 kinSolver->solveRecursiveIKRelative(rns, jointAnglesOldStart, poses, selections);
787
788 return ikSolutions.back();
789}
790
791////////////////////////////////////////////////////////////////////////////////////////////////////
792/// Constructor(s)
793////////////////////////////////////////////////////////////////////////////////////////////////////
794
796 EnvironmentPtr environment) :
797 kinSolver(KinematicSolver::getInstance(environment->getScene(), environment->getRobot())),
798 environment(environment)
799{
800 rns = environment->getRobot()->getRobotNodeSet(rnsName);
801}
802
803////////////////////////////////////////////////////////////////////////////////////////////////////
804/// Public Functions
805////////////////////////////////////////////////////////////////////////////////////////////////////
806
807void
809{
810 PoseBasePtr pb = kinSolver->doForwardKinematic(rns, jointAngles);
811 Pose pose = Pose(pb->position, pb->orientation);
812 pb = PoseBasePtr(new Pose(rns->getKinematicRoot()->toLocalCoordinateSystem(pose.toEigen())));
813
814 // create UserWaypoint with the given jointAngles
815 UserWaypointPtr tmpUwp(new UserWaypoint(pb));
816 tmpUwp->setJointAngles(jointAngles);
817
818 designerTrajectory = DesignerTrajectoryPtr(new DesignerTrajectory(tmpUwp, rns));
819
820 //mementos.currentMemento = 0;
821
822 if (mementos.mementoList.size() != 0)
823 {
824 saveState();
825 }
826 else
827 {
828 mementos.mementoList.push_back(
829 DesignerTrajectoryPtr(new DesignerTrajectory(*designerTrajectory)));
830 }
831
832 isInitialized = true;
833}
834
835void
837{
838 if (isInitialized)
839 {
840 //get a clean copy of the designerTrajectory
841 designerTrajectory = getDesignerTrajectory();
842
843 UserWaypointPtr newPoint = UserWaypointPtr(new UserWaypoint(pb));
844 designerTrajectory->addLastUserWaypoint(newPoint);
845 theUniversalMethod(designerTrajectory->getNrOfUserWaypoints() - 1);
846 }
847 else
848 {
849 throw NotInitializedException("Manager is not intialized", "Manager");
850 }
851}
852
853void
854DesignerTrajectoryManager::insertWaypoint(unsigned int index, const PoseBasePtr pb)
855{
856 if (isInitialized)
857 {
858 //get a clean copy of the designerTrajectory
859 designerTrajectory = getDesignerTrajectory();
860
861 if (index != 0)
862 {
863 UserWaypointPtr newPoint = UserWaypointPtr(new UserWaypoint(pb));
864 designerTrajectory->insertUserWaypoint(newPoint, index);
865 theUniversalMethod(index);
866 }
867 else
868 {
869 PoseBasePtr oldStart = designerTrajectory->getUserWaypoint(0)->getPose();
870 std::vector<double> jointAngles = getNewIkSolutionOfFirstPoint(
871 oldStart, pb, designerTrajectory->getUserWaypoint(0)->getJointAngles());
872 if (jointAngles.size() == 0)
873 {
874 return;
875 }
876 UserWaypointPtr newPoint = UserWaypointPtr(new UserWaypoint(pb));
877 designerTrajectory->insertUserWaypoint(newPoint, index);
878 designerTrajectory->getUserWaypoint(0)->setJointAngles(jointAngles);
879
880 theUniversalMethod(index);
881 }
882 }
883 else
884 {
885 throw NotInitializedException("Manager is not intialized", "Manager");
886 }
887}
888
889void
891{
892 if (isInitialized)
893 {
894 //get a clean copy of the designerTrajectory
895 designerTrajectory = getDesignerTrajectory();
896 if (index != 0)
897 {
898 designerTrajectory->getUserWaypoint(index)->setPose(pb);
899 }
900 else
901 {
902 std::vector<double> newJointAngles;
903 if (designerTrajectory->getNrOfUserWaypoints() > 1)
904 {
905 newJointAngles = getNewIkSolutionOfFirstPoint(
906 designerTrajectory->getUserWaypoint(1)->getPose(),
907 pb,
908 designerTrajectory->getUserWaypoint(1)->getJointAngles());
909 if (newJointAngles.size() == 0)
910 {
911 return;
912 }
913 designerTrajectory->getUserWaypoint(0)->setPose(pb);
914 designerTrajectory->getUserWaypoint(0)->setJointAngles(newJointAngles);
915 }
916 else
917 {
918 //newJointAngles = kinSolver->solveIK(rns, pb, designerTrajectory->getUserWaypoint(0)->getIKSelection(), 50);
919 newJointAngles = getNewIkSolutionOfFirstPoint(
920 designerTrajectory->getUserWaypoint(0)->getPose(),
921 pb,
922 designerTrajectory->getUserWaypoint(0)->getJointAngles());
923 if (newJointAngles.size() == 0)
924 {
925 return;
926 }
927 UserWaypointPtr uwpTmp(new UserWaypoint(pb));
928 uwpTmp->setJointAngles(newJointAngles);
929 uwpTmp->setIKSelection(designerTrajectory->getUserWaypoint(0)->getIKSelection());
930 uwpTmp->setIsTimeOptimalBreakpoint(
931 designerTrajectory->getUserWaypoint(0)->getIsTimeOptimalBreakpoint());
932 DesignerTrajectoryPtr dtTmp(new DesignerTrajectory(uwpTmp, rns));
933 designerTrajectory = dtTmp;
934 }
935 }
936 theUniversalMethod(index);
937 }
938 else
939 {
940 throw NotInitializedException("Manager is not intialized", "Manager");
941 }
942}
943
944void
946 unsigned int index,
947 VirtualRobot::IKSolver::CartesianSelection ikSelection)
948{
949 if (isInitialized)
950 {
951 //get a clean copy of the designerTrajectory
952 designerTrajectory = getDesignerTrajectory();
953
954 designerTrajectory->getUserWaypoint(index)->setIKSelection(ikSelection);
955 theUniversalMethod(index);
956 }
957 else
958 {
959 throw NotInitializedException("Manager is not intialized", "Manager");
960 }
961}
962
963void
965{
966 if (isInitialized)
967 {
968 //get a clean copy of the designerTrajectory
969 designerTrajectory = getDesignerTrajectory();
970
971 if (designerTrajectory->getNrOfUserWaypoints() == 1)
972 {
973 isInitialized = false;
974 designerTrajectory = nullptr;
975 saveState();
976 }
977 else
978 {
979 designerTrajectory->deleteUserWaypoint(index);
980
981 //check if first userwaypoint was delted
982 if (index == 0)
983 {
984 designerTrajectory->getUserWaypoint(0)->setTimeOptimalTimestamp(0);
985 designerTrajectory->getUserWaypoint(0)->setUserTimestamp(0);
986 }
987
988 // check if just one waypoint is left
989 if (designerTrajectory->getNrOfUserWaypoints() == 1)
990 {
991 saveState();
992 return;
993 }
994
995 // check if last userwaypoint was deleted
996 if (index == designerTrajectory->getNrOfUserWaypoints())
997 {
998 theUniversalMethod(index - 1);
999 }
1000 else
1001 {
1002 theUniversalMethod(index);
1003 }
1004 }
1005 }
1006 else
1007 {
1008 throw NotInitializedException("Manager is not intialized", "Manager");
1009 }
1010}
1011
1012void
1014{
1015 if (isInitialized)
1016 {
1017 //get a clean copy of the designerTrajectory
1018 designerTrajectory = getDesignerTrajectory();
1019
1020 designerTrajectory->getTransition(index)->setInterpolationType(it);
1021 theUniversalMethod(index);
1022 }
1023 else
1024 {
1025 throw NotInitializedException("Manager is not intialized", "Manager");
1026 }
1027}
1028
1029void
1031{
1032 if (isInitialized)
1033 {
1034 //get a clean copy of the designerTrajectory
1035 designerTrajectory = getDesignerTrajectory();
1036
1037 designerTrajectory->getUserWaypoint(index)->setIsTimeOptimalBreakpoint(b);
1038 theUniversalMethod(index);
1039 }
1040 else
1041 {
1042 throw NotInitializedException("Manager is not intialized", "Manager");
1043 }
1044}
1045
1046void
1048{
1049 if (isInitialized)
1050 {
1051 //get a clean copy of the designerTrajectory
1052 designerTrajectory = getDesignerTrajectory();
1053
1054 designerTrajectory->getTransition(index)->setUserDuration(duration);
1055 //shift all userTimestamps of the userwaypoints behind
1056 for (unsigned int i = index + 1; i < designerTrajectory->getNrOfUserWaypoints() - 1; i++)
1057 {
1058 TransitionPtr trans = designerTrajectory->getTransition(i);
1059 trans->setUserDuration(trans->getUserDuration());
1060 }
1061 //theUniversalMethod(index);
1062 saveState();
1063 }
1064 else
1065 {
1066 throw NotInitializedException("Manager is not intialized", "Manager");
1067 }
1068}
1069
1072{
1073 if (isInitialized)
1074 {
1075 //return DesignerTrajectoryPtr(new DesignerTrajectory(*designerTrajectory));
1077 *(*std::next(mementos.mementoList.begin(), mementos.currentMemento))));
1078 }
1079 else
1080 {
1081 return nullptr;
1082 }
1083}
1084
1085bool
1087{
1088 if (newDesignerTrajectory->getNrOfUserWaypoints() > 1 &&
1089 newDesignerTrajectory->getRns()->getName() == rns->getName())
1090 {
1091 TrajectoryPtr trajectory = newDesignerTrajectory->getTimeOptimalTrajectory();
1092
1093 //set Trajectories of transitions
1094 for (unsigned int i = 0; i < newDesignerTrajectory->getNrOfUserWaypoints() - 1; i++)
1095 {
1096 TransitionPtr trans = newDesignerTrajectory->getTransition(i);
1097 double transBeginTime = trans->getStart()->getTimeOptimalTimestamp();
1098 double transEndTime = trans->getEnd()->getTimeOptimalTimestamp();
1099 TrajectoryPtr traj = trajectory->getPart(transBeginTime, transEndTime, 2);
1100
1101
1102 //shift timestamps
1103 std::vector<std::vector<double>> nodeData;
1104 for (unsigned int dim = 0; dim < traj->dim(); dim++)
1105 {
1106 nodeData.push_back(traj->getDimensionData(dim));
1107 }
1108 std::vector<double> newTimestamps = {0.0};
1109 std::vector<double> oldTimestamps = traj->getTimestamps();
1110 for (unsigned int j = 1; j < oldTimestamps.size(); j++)
1111 {
1112 if (oldTimestamps[j] - transBeginTime >= 0)
1113 {
1114 newTimestamps.push_back(oldTimestamps[j] - transBeginTime);
1115 }
1116 else
1117 {
1118 newTimestamps.push_back(0);
1119 }
1120 }
1121
1122 TrajectoryPtr shiftedTraj(
1123 new Trajectory(nodeData, newTimestamps, traj->getDimensionNames()));
1124 trans->setTrajectory(shiftedTraj);
1125 }
1126 designerTrajectory = newDesignerTrajectory;
1127
1128 if (mementos.mementoList.size() != 0)
1129 {
1130 saveState();
1131 }
1132 else
1133 {
1134 mementos.mementoList.push_back(
1135 DesignerTrajectoryPtr(new DesignerTrajectory(*designerTrajectory)));
1136 }
1137 isInitialized = true;
1138 return true;
1139 }
1140 return false;
1141}
1142
1143bool
1145{
1146 return mementos.currentMemento > 0;
1147}
1148
1149bool
1151{
1152 if (mementos.mementoList.size() != 0 &&
1153 mementos.currentMemento < mementos.mementoList.size() - 1)
1154 {
1155 return true;
1156 }
1157 else
1158 {
1159 return false;
1160 }
1161}
std::string timestamp()
uint8_t index
constexpr T dt
void deleteWaypoint(unsigned int index)
Deletes a UserWaypoint from this manager's DesignerTrajectory.
void setTransitionInterpolation(unsigned int index, InterpolationType it)
Sets the InterpolationType of a Transition from this manager's DesignerTrajectory.
void setWaypointAsBreakpoint(unsigned int index, bool b)
Sets a UserWaypoint as (not-) breakpoint.
void addWaypoint(const PoseBasePtr pose)
Adds a UserWaypoint to the end of this manager's DesignerTrajectory.
void initializeDesignerTrajectory(std::vector< double > &jointAngles)
Public functions.
void insertWaypoint(unsigned int index, const PoseBasePtr pose)
Inserts a UserWaypoint at the given position to this manager's DesignerTrajectory.
bool import(DesignerTrajectoryPtr newDesignerTrajectory)
Overrides the current DesignerTrajectory with the given DesignerTrajectory.
DesignerTrajectoryManager(std::string rnsName, EnvironmentPtr environment_)
Constructor(s)
bool getIsInitialized()
True if the DesignerTrajectory is initialized.
void editWaypointIKSelection(unsigned int index, VirtualRobot::IKSolver::CartesianSelection ikSelection)
Edits the IKSelection of a UserWaypoint.
bool undoPossible()
setCollisionModels Sets the collision models on the collision detection attribute
DesignerTrajectoryPtr getDesignerTrajectory() const
Returns a deep copy of this manager's DesignerTrajectory.
void editWaypointPoseBase(unsigned int index, const PoseBasePtr pose)
Edits the pose of a UserWaypoint.
void setTransitionUserDuration(unsigned int index, double duration)
Sets the desired duration of a Transition.
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 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 > produceLinearInterpolationSegments(std::vector< PoseBasePtr > controlPoints)
produceInterpolationSegments constructs a vector of LinearInterpolations
Realizes the Singleton-Pattern, Provides Methods to solve Kinematic Problems (forward and inverse)
The Pose class.
Definition Pose.h:243
virtual Eigen::Matrix4f toEigen() const
Definition Pose.cpp:334
The Trajectory class represents n-dimensional sampled trajectories.
Definition Trajectory.h:77
The UserWaypoint class represents a waypoint of the trajectory.
const VariantTypeId Trajectory
Definition Trajectory.h:44
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Trajectory > TrajectoryPtr
Definition Trajectory.h:52
std::shared_ptr< Environment > EnvironmentPtr
Definition Environment.h:29
InterpolationType
The InterpolationType enum lists all available interpolation types eLinearInterpolation: represents l...
std::shared_ptr< Transition > TransitionPtr
Definition Transition.h:143
std::shared_ptr< DesignerTrajectory > DesignerTrajectoryPtr
std::shared_ptr< UserWaypoint > UserWaypointPtr
std::shared_ptr< AbstractInterpolation > AbstractInterpolationPtr