Tree.h
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 RobotComponents
19 * @author Raphael Grimm ( raphael dot grimm at kit dot edu )
20 * @date 2015
21 * @copyright http://www.gnu.org/licenses/gpl.txt
22 * GNU General Public License
23 */
24#pragma once
25
26#include <deque>
27#include <mutex>
28#include <unordered_map>
29
31
32#include <RobotComponents/interface/components/MotionPlanning/Tasks/AdaptiveDynamicDomainInformedRRTStar/DataStructures.h>
33#include <RobotComponents/interface/components/MotionPlanning/Tasks/AdaptiveDynamicDomainInformedRRTStar/Task.h>
34
35#include "util.h"
36
37namespace armarx::addirrtstar
38{
39 /**
40 * @brief A structure holding and managing all data connected to the tree used in the ADDIRRT* algorithm.
41 *
42 * Function overview:
43 * [public ] applyXYZUpdate(XYZUpdate u): applies an existing update u to the tree
44 * [protected] createNewXYZUpdate(...) : creates a new update and adds it to the tree's current update
45 * [public ] addNode/{in,de}creaseRadius/setNodeParent/addGoalReached: modifies the tree (through do functions)
46 * and adds the corresponding update to the local tree
47 * [protected] doXYZ: performs the actual modification of the tree
48 */
49 class Tree
50 {
51 //types
52 public:
53 /**
54 * @brief The type of configurations.
55 */
56 using ConfigType = VectorXf;
57
58 /**
59 * @brief Represents a node of thr rrt.
60 */
61 struct NodeType
62 {
63 /**
64 * @brief The node's configuration.
65 */
67 /**
68 * @brief The node's parent.
69 */
70 NodeId parent;
71 /**
72 * @brief The node's radius. (adaptive dynamic domain)
73 */
74 float radius;
75 /**
76 * @brief Cost of the edge (parent node, this node)
77 */
79 /**
80 * @brief Cost of the path (sttart node, this node)
81 */
83 /**
84 * @brief Link to all children nodes
85 */
86 std::set<NodeId> children;
87 };
88
89 /**
90 * @brief Lookuptable for pending updates.
91 */
93 std::unordered_map<std::pair<std::size_t, std::size_t>, std::size_t>;
94 /**
95 * @brief Iterator for the PendingUpdateLookuptable.
96 */
97 using PendingUpdateLookuptableIterator = typename PendingUpdateLookuptableType::iterator;
98 /**
99 * @brief Const iterator for the PendingUpdateLookuptable.
100 */
102 typename PendingUpdateLookuptableType::const_iterator;
103
104 /**
105 * @brief Default ctor.
106 */
107 Tree() = default;
108
109 /**
110 * @brief Creates a tree that can be used to analyze and apply updates.
111 * Other operations are undefined.
112 * @param startCfg The start config.
113 */
114 Tree(const VectorXf& startCfg);
115
116 //init
117 /**
118 * @brief Initailizes the tree from the given tree.
119 * @param iceTree The tree to use as initial state.
120 * @param newaddParams The new adaptive dynamic domain parameters.
121 * @param newWorkerId The owner's worker id.
122 */
123 void init(const FullIceTree& iceTree,
124 AdaptiveDynamicDomainParameters newaddParams,
125 std::size_t newWorkerId);
126
127 /**
128 * @brief Increases the storage of all data structures to be appropriate for count workers.
129 * @param count The number of workers.
130 */
131 void increaseWorkerCountTo(std::size_t count);
132
133 //updating
134 public:
135 /**
136 * @param u The update.
137 * @return Whether the given update can be applied.
138 */
139 bool canApplyUpdate(const Update& u);
140 /**
141 * @brief Adds a new update to the list of pending updates.
142 * @param u The update.
143 */
144 void addPendingUpdate(const Update& u);
145 /**
146 * @brief Applies the given update.
147 * @param u The update.
148 */
149 void applyUpdate(const Update& u);
150 /**
151 * @brief Sends the current update to the given proxy. A new update is prepared afterwards.
152 * @param prx The proxy to send the update to.
153 */
154 void sendCurrentUpdate(TreeUpdateInterfacePrx& prx);
155
156 /**
157 * @return Returns all updates send by this tree.
158 */
159 const std::deque<Update>&
161 {
162 return localUpdates;
163 }
164
165 /**
166 * @param workerId The update's worker id.
167 * @param updateId The update's sub id.
168 * @return Whether the given update was applied.
169 */
170 bool
171 hasAppliedUpdate(std::size_t workerId, Ice::Long updateId)
172 {
174 return updateId <= appliedUpdateIds.at(workerId);
175 }
176
177 /**
178 * @param workerId The update's worker id.
179 * @param updateId The update's sub id.
180 * @return Whether the given update is in the list of pending updates.
181 */
182 bool
183 hasPendingUpdate(std::size_t workerId, std::size_t updateId) const
184 {
185 return findPendingUpdate(workerId, updateId) != pendingUpdatesLookupTable.end();
186 }
187
188 /**
189 * @param workerId The update's worker id.
190 * @param updateId The update's sub id.
191 * @return Returns the requested update from the list of pending updates.
192 */
193 const Update&
194 getPendingUpdate(std::size_t workerId, std::size_t updateId) const
195 {
197 return pendingUpdates.at(findPendingUpdate(workerId, updateId)->second);
198 }
199
200 /**
201 * @brief Applies all pending updates. Updates are not consumes.
202 * If a required update is missing this methode will fail. (no update getter is providet).
203 * This function is not thread save! Use it only in a serial/protected environment.
204 */
205 void
207 {
208 std::mutex m;
209 std::unique_lock<std::mutex> lock{m};
211 lock,
212 [](std::size_t w, Ice::Long u)
213 {
215 << "no remote update getter set but missing an update (w/s): " << w << "/"
216 << u;
217 throw std::logic_error{"no remote update getter set but missing an update!"};
218 return Update();
219 });
220 }
221
222 /**
223 * @brief The same as applyPendingUpdates(LockType, RemoteUpdateGetter, UpdateConsumer) but uses an noop as updateConsumer
224 * This overload is needed since the defaultparameter does not work.
225 * @param getRemoteUpdate Function used to request a missing update.
226 * @see Tree::applyPendingUpdates
227 */
228 template <class LockType, class RemoteUpdateGetter>
229 void
230 applyPendingUpdates(LockType&& treeLock, RemoteUpdateGetter getRemoteUpdate)
231 {
232 applyPendingUpdates(treeLock, getRemoteUpdate, [](Update&&) {});
233 }
234
235 /**
236 * @brief Applies all pending updates.
237 * @param treeLock The lock used to protect the update structures.
238 * It will be unlocked when getting a remote update.
239 * @param getRemoteUpdate Function used to request a missing update.
240 * @param updateConsumer Function used to consume updates after they were added. (will be moved to the consumer)
241 */
242 template <class LockType, class RemoteUpdateGetter, class UpdateConsumer>
243 void
245 LockType&& treeLock,
246 RemoteUpdateGetter getRemoteUpdate,
247 UpdateConsumer updateConsumer = [](Update&&) {} //no op
248 )
249 {
250 ARMARX_CHECK_EXPRESSION(treeLock);
252
253 //we want i for an assert after the loop
254 std::size_t i = 0;
255
256 for (; i < pendingUpdates.size(); ++i)
257 {
258 //apply this pending update
259 applyPendingUpdate(i, treeLock, getRemoteUpdate, updateConsumer);
260 ARMARX_CHECK_EXPRESSION(treeLock);
261 }
262
263 ARMARX_CHECK_EXPRESSION(treeLock);
265 //clear updates
266 pendingUpdates.clear();
268 }
269
270 /**
271 * @return The update sub id of the current update. (The one currently constructed, not the last send)
272 */
273 Ice::Long
275 {
276 const auto id = static_cast<Ice::Long>(getLocalUpdates().size()) - 1;
278 return id;
279 }
280
281 /**
282 * @return The update sub id of the last send update.
283 */
284 Ice::Long
286 {
287 return appliedUpdateIds.at(workerId);
288 }
289
290 /**
291 * @return The currently constructed update.
292 */
293 const Update&
295 {
296 return localUpdates.back();
297 }
298
299 protected:
300 /**
301 * @return The currently constructed update. (non const version for internal use)
302 */
303 Update&
305 {
306 return localUpdates.back();
307 }
308
309 /**
310 * @brief Applies a radius update to the tree.
311 * @param u The update.
312 */
313 void applyRadiusUpdate(const RadiusUpdate& u);
314
315 /**
316 * @brief Applies a node creation update to the tree.
317 * @param u The update.
318 * @param workerId The updates source worker.
319 */
320 void
321 applyNodeCreationUpdate(const NodeCreationUpdate& u, std::size_t workerId)
322 {
323 doAddNode(u.config, u.parent, u.fromParentCost, workerId);
324 }
325
326 /**
327 * @brief Applies a rewire update to the tree.
328 * @param rewireUpdate The update.
329 */
330 void applyRewireUpdate(const RewireUpdate& rewireUpdate);
331
332 /**
333 * @brief Applies multiple goal reached updates to the tree.
334 * @param newGoalNodes The new nodes that can reach the goal configuration.
335 */
336 void
337 applyGoalReachedUpdates(const GoalInfoList newGoalNodes)
338 {
339 std::copy(newGoalNodes.begin(), newGoalNodes.end(), std::back_inserter(goalNodes));
340 }
341
342 /**
343 * @brief Prepares the next update. (the update to be send)
344 */
345 void prepareNextUpdate();
346
347 /**
348 * @brief Adds a new radius update to the current update.
349 * @param id The node's id.
350 * @param increaseRadius Whether the node's radius increases.
351 */
352 void
353 createNewRadiusUpdate(const NodeId& id, bool increaseRadius)
354 {
355 getCurrentUpdateNonConst().radii.emplace_back(RadiusUpdate{id, increaseRadius});
356 }
357
358 /**
359 * @brief Adds a new node creation update to the current update.
360 * @param cfg The new node's configuration.
361 * @param parent The new node's parent node.
362 * @param fromParentCost The cost of the edge (node, parent)
363 */
364 void
366 const NodeId& parent,
367 float fromParentCost)
368 {
369 getCurrentUpdateNonConst().nodes.emplace_back(
370 NodeCreationUpdate{cfg, parent, fromParentCost});
371 }
372
373 /**
374 * @brief Adds a new node creation update to the current update.
375 * @param child The rewired child node.
376 * @param newParent The new parent node.
377 * @param fromParentCost The cost of the edge (child, new parent)
378 */
379 void
380 createNewRewireUpdate(const NodeId& child, const NodeId& newParent, float fromParentCost)
381 {
382 getCurrentUpdateNonConst().rewires.emplace_back(
383 RewireUpdate{child, newParent, fromParentCost});
384 }
385
386 /**
387 * @brief Adds a new goal reached update to the current update.
388 * @param goal The node that can reach the goal configuration.
389 * @param costToGoToGoal The cost to reach the goal configuration from the given node)
390 */
391 void
392 createNewGoalReachedUpdate(const NodeId& goal, float costToGoToGoal)
393 {
394 getCurrentUpdateNonConst().newGoalNodes.emplace_back(GoalInfo{goal, costToGoToGoal});
395 }
396
397 /**
398 * @brief Applies one pending update from the list of pending updates.
399 * @param updateIndex The pending update's index.
400 * @param treeLock The lock used to protect the update structures.
401 * It will be unlocked when getting a remote update.
402 * @param getRemoteUpdate Function used to request a missing update.
403 * @param updateConsumer Function used to consume updates after they were added. (will be moved to the consumer)
404 */
405 template <class LockType, class RemoteUpdateGetter, class UpdateConsumer>
406 void
407 applyPendingUpdate(std::size_t updateIndex,
408 LockType&& treeLock,
409 RemoteUpdateGetter getRemoteUpdate,
410 UpdateConsumer updateConsumer)
411 {
412 ARMARX_CHECK_EXPRESSION(treeLock);
413 ARMARX_CHECK_EXPRESSION(updateIndex < pendingUpdates.size());
414
415 auto& u = pendingUpdates.at(updateIndex);
416 increaseWorkerCountTo(u.dependetOnUpdateIds.size());
417
418 const auto& dependetOnUpdateIds = u.dependetOnUpdateIds;
419
420 ARMARX_CHECK_EXPRESSION(u.workerId >= 0);
421 const auto updateWorkerId = static_cast<std::size_t>(u.workerId);
422
423 if (dependetOnUpdateIds.empty())
424 {
425 //this update was moved from! => it was applied because it was queued out of order)
426 return;
427 }
428
429 ARMARX_CHECK_EXPRESSION(updateWorkerId < dependetOnUpdateIds.size());
430 const auto updateId = dependetOnUpdateIds.at(updateWorkerId) + 1;
431
432 //is it an update from this node or was it already applied?
433 if (updateWorkerId == workerId || //self update
434 hasAppliedUpdate(updateWorkerId, updateId) //update was already applied
435 )
436 {
437 return;
438 }
439
440 //this update is new => check if it requires prev updates (if we have then, apply them directly, else get them from remote)
441 prepareUpdate(dependetOnUpdateIds, treeLock, getRemoteUpdate, updateConsumer);
442 ARMARX_CHECK_EXPRESSION(treeLock);
443
444 //now we have all required updates
445 applyUpdate(u);
446 //we dont need the update anymore. move it to the consumer
447 updateConsumer(std::move(u));
448 }
449
450 public:
451 /**
452 * @brief Prepares an update by applying all dependet on updates.
453 * @param dependetOnUpdateIds The ids of dependet on updates.
454 * @param treeLock The lock used to protect the update structures.
455 * It will be unlocked when getting a remote update.
456 * @param getRemoteUpdate Function used to request a missing update.
457 * @param updateConsumer Function used to consume updates after they were added. (will be moved to the consumer)
458 */
459 template <class LockType, class RemoteUpdateGetter, class UpdateConsumer>
460 void
461 prepareUpdate(Ice::LongSeq dependetOnUpdateIds,
462 LockType&& treeLock,
463 RemoteUpdateGetter getRemoteUpdate,
464 UpdateConsumer updateConsumer)
465 {
466 ARMARX_CHECK_EXPRESSION(treeLock);
467
468 for (std::size_t workerNodeId = 0; workerNodeId < dependetOnUpdateIds.size();
469 ++workerNodeId)
470 {
471 const auto updateSubId = dependetOnUpdateIds.at(workerNodeId);
472
473 if (hasAppliedUpdate(workerNodeId, updateSubId))
474 {
475 //we have this update!
476 continue;
477 }
478
479 //the update was not applied
480 //is this update local?
481 auto it = findPendingUpdate(workerNodeId, updateSubId);
482
483 if (it != pendingUpdatesLookupTable.end())
484 {
485 auto missingIndex = (*it).second;
486 //recurse
487 applyPendingUpdate(missingIndex, treeLock, getRemoteUpdate, updateConsumer);
488 }
489 else
490 {
491 ARMARX_CHECK_EXPRESSION(treeLock);
492 //get the update from remote. this may take a while => unlock
493 treeLock.unlock();
494 Update update = getRemoteUpdate(workerNodeId, updateSubId);
495 treeLock.lock();
496 //prepare this update and apply it
498 update.dependetOnUpdateIds, treeLock, getRemoteUpdate, updateConsumer);
499 ARMARX_CHECK_EXPRESSION(treeLock);
500 applyUpdate(update);
501 //we dont need the update anymore. move it to the consumer
502 updateConsumer(std::move(update));
503 }
504 }
505 }
506
507 protected:
508 /**
509 * @param workerId The update's worker.
510 * @param updateId The update's sub id.
511 * @return An iterator tho the pending update. (If it does not exist to end.)
512 */
514 findPendingUpdate(std::size_t workerId, std::size_t updateId)
515 {
516 return pendingUpdatesLookupTable.find(std::make_pair(workerId, updateId));
517 }
518
519 /**
520 * @param workerId The update's worker.
521 * @param updateId The update's sub id.
522 * @return An iterator tho the pending update. (If it does not exist to end.) (const version)
523 */
525 findPendingUpdate(std::size_t workerId, std::size_t updateId) const
526 {
527 return pendingUpdatesLookupTable.find(std::make_pair(workerId, updateId));
528 }
529
530 //changing the tree from the rrt algorithm
531 public:
532 /**
533 * @brief Adds a node to the tree. (creates an appropriate update)
534 * @param cfg The node's configuration.
535 * @param parent The node's parent.
536 * @param fromParentCost The cost of the edge (node, parent)
537 * @return The new node's id.
538 */
539 NodeId addNode(ConfigType cfg, const NodeId& parent, float fromParentCost);
540
541 /**
542 * @brief Sets the parent node of child to parent. (costs are updated) (creates an appropriate update)
543 * @param child The cild node.
544 * @param newParent The new parent node.
545 * @param fromParentCost The cost of the edge (child, new parent)
546 */
547 void
548 setNodeParent(const NodeId& child, const NodeId& newParent, float fromParentCost)
549 {
550 doSetNodeParent(child, newParent, fromParentCost);
551 createNewRewireUpdate(child, newParent, fromParentCost);
552 }
553
554 /**
555 * @brief Decreases a node's radius.(creates an appropriate update)
556 * @param id The node.
557 */
558 void
559 decreaseRadius(const NodeId& id)
560 {
561 createNewRadiusUpdate(id, false);
563 }
564
565 /**
566 * @brief Increases a node's radius.(creates an appropriate update)
567 * @param id The node.
568 */
569 void
570 increaseRadius(const NodeId& id)
571 {
572 createNewRadiusUpdate(id, true);
574 }
575
576 /**
577 * @brief Adds a node to the list of nodes that can reach the goal configuration. (creates an appropriate update)
578 * @param goal The node to add.
579 * @param costToGoToGoal The cost to reach the gol configuration from the given node.
580 */
581 void
582 addGoalReached(const NodeId& goal, float costToGoToGoal)
583 {
584 doAddGoalReached(goal, costToGoToGoal);
585 createNewGoalReachedUpdate(goal, costToGoToGoal);
586 }
587
588 protected:
589 //change the tree
590 /**
591 * @brief Updates fromStartCosts for all children from root.
592 * @param root The root node for the cost update.
593 */
594 void pushCosts(const NodeId& root);
595
596 /**
597 * @brief Adds a node to the tree.
598 * @param cfg The node's configuration.
599 * @param parent The node's parent.
600 * @param fromParentCost The cost of the edge (node, parent)
601 * @param workerId The worker creating this node.
602 * @return The new node's id.
603 */
604 NodeId
605 doAddNode(ConfigType cfg, const NodeId& parent, float fromParentCost, std::size_t workerId);
606 /**
607 * @brief Sets the parent node of child to parent. (costs are updated)
608 * @param child The cild node.
609 * @param newParent The new parent node.
610 * @param fromParentCost The cost of the edge (child, new parent)
611 * @param updateFromStartCost Whether to update the costs of the subtree beneath cild.
612 */
613 void doSetNodeParent(const NodeId& child,
614 const NodeId& newParent,
615 float fromParentCost,
616 bool updateFromStartCost = true);
617 /**
618 * @brief Decreases a node's radius.
619 * @param id The node.
620 */
621 void doDecreaseRadius(const NodeId& id);
622
623 /**
624 * @brief Increases a node's radius.
625 * @param id The node.
626 */
627 void
628 doIncreaseRadius(const NodeId& id)
629 {
630 getNode(id).radius *= (1.f + addParams.alpha); //inf will stay inf
631 }
632
633 /**
634 * @brief Adds a node to the list of nodes that can reach the goal configuration.
635 * @param goal The node to add.
636 * @param costToGoToGoal The cost to reach the gol configuration from the given node.
637 */
638 void
639 doAddGoalReached(const NodeId& goal, float costToGoToGoal)
640 {
641 goalNodes.emplace_back(GoalInfo{goal, costToGoToGoal});
642 }
643
644 //querry the tree
645 public:
646 /**
647 * @param cfg The configuration.
648 * @param k The number of neighbours.
649 * @return The k nearest neighbours of and their distance to the given configuration.
650 */
651 std::vector<std::pair<NodeId, float>>
652 getKNearestNeighboursAndDistances(const ConfigType& cfg, std::size_t k);
653
654 /**
655 * @param cfg The configuration.
656 * @return The nearest neighbour of and its distance to the given configuration.
657 */
658 std::pair<NodeId, float>
660 {
661 return getKNearestNeighboursAndDistances(cfg, 1).front();
662 }
663
664 /**
665 * @param id The node's id.
666 * @return The requested node.
667 */
668 NodeType& getNode(const NodeId& id);
669 /**
670 * @param id The node's id.
671 * @return The requested node. (const)
672 */
673 const NodeType& getNode(const NodeId& id) const;
674
675 /**
676 * @return All nodes.
677 */
678 const std::deque<std::deque<NodeType>>&
679 getNodes() const
680 {
681 return nodes;
682 }
683
684 /**
685 * @param index The index.
686 * @return The id corresponding to the given node index.
687 */
688 NodeId getIdOfIndex(std::size_t index) const;
689
690 /**
691 * @return The number of nodes in the tree.
692 */
693 std::size_t
694 size() const
695 {
696 return nodeCount;
697 }
698
699 /**
700 * @param id The node's id.
701 * @return The requested node.
702 */
703 NodeType&
704 at(const NodeId& id)
705 {
706 return getNode(id);
707 }
708
709 /**
710 * @param id The node's id.
711 * @return The requested node. (const)
712 */
713 const NodeType&
714 at(const NodeId& id) const
715 {
716 return getNode(id);
717 }
718
719 /**
720 * @param index The node's index.
721 * @return The requested node.
722 */
723 NodeType&
724 at(std::size_t index)
725 {
726 return at(getIdOfIndex(index));
727 }
728
729 /**
730 * @param index The node's index.
731 * @return The requested node. (const)
732 */
733 const NodeType&
734 at(std::size_t index) const
735 {
736 return at(getIdOfIndex(index));
737 }
738
739 /**
740 * @return The current RRT with all updates applied. (used to transmitt it through ice.)
741 */
742 FullIceTree getIceTree() const;
743
744 protected:
745 /**
746 * @return An iterator to the node that can reach the goal configuration and results in the lowest path cost. (end if no path was found)
747 */
748 typename std::deque<GoalInfo>::const_iterator
750 {
751 return std::min_element(
752 goalNodes.begin(),
753 goalNodes.end(),
754 [this](const GoalInfo& fst, const GoalInfo& snd)
755 {
756 return (getNode(fst.node).fromStartCost + fst.costToGoToGoal) <
757 (getNode(snd.node).fromStartCost + snd.costToGoToGoal);
758 });
759 }
760
761 //querry for paths
762 public:
763 /**
764 * @return The cost of the shortest solution.
765 */
766 float getBestCost() const;
767
768 /**
769 * @return The path with the lowest cost.
770 */
771 PathWithCost getBestPath() const;
772
773 /**
774 * @param nodeId The node to check.
775 * @return Whether the given node is a node in the list of nodes able to reach the goal configuration.
776 */
777 bool
778 hasGoalNode(const NodeId& nodeId) const
779 {
780 return std::any_of(goalNodes.begin(),
781 goalNodes.end(),
782 [&nodeId](const GoalInfo& info) { return info.node == nodeId; });
783 }
784
785 /**
786 * @return The number of paths found.
787 */
788 std::size_t
790 {
791 return goalNodes.size();
792 }
793
794 /**
795 * @param n The paths index.
796 * @return The cost of the given path.
797 */
798 float
799 getNthPathCost(std::size_t n) const
800 {
802 return getNode(goalNodes.at(n).node).fromStartCost + goalNodes.at(n).costToGoToGoal;
803 }
804
805 /**
806 * @param n N
807 * @return The nth path.
808 */
809 PathWithCost getNthPathWithCost(std::size_t n) const;
810 /**
811 * @param n The path's index.
812 * @return The node ids of nodes contained by the given path.
813 */
814 NodeIdList getNthPathIds(std::size_t n) const;
815
816 protected:
817 /**
818 * @param id The node's id.
819 * @return Returns a path to the requested node.
820 */
821 VectorXfSeq getPathTo(NodeId id) const;
822 //utility
823 public:
824 /**
825 * @param workerId The worker's id.
826 * @return The next node id for the given worker.
827 */
828 NodeId
830 {
832 return {static_cast<Ice::Long>(workerId),
833 static_cast<Ice::Long>(nodes.at(workerId).size())};
834 }
835
836 /**
837 * @brief The root node's id
838 */
839 static const NodeId ROOT_ID;
840
841 /**
842 * @return List of ids of applied updates.
843 */
844 const Ice::LongSeq&
846 {
847 return appliedUpdateIds;
848 }
849
850 protected:
851 /**
852 * @brief List of ids of applied updates.
853 */
854 Ice::LongSeq appliedUpdateIds;
855 //deques are used because they don't need to copy all already stored data
856 //when the capacity runs out
857
858 /**
859 * @brief Updates created by this tree.
860 */
861 std::deque<Update> localUpdates;
862
863 /**
864 * @brief Holds all nodes.
865 * The node nodes[i][j] is the jth node created by worker i.
866 */
867 std::deque<std::deque<NodeType>> nodes;
868 /**
869 * @brief List of nodes able to reach the goal configuration.
870 */
871 std::deque<GoalInfo> goalNodes;
872
873 /**
874 * @brief The parameters of adaptive dynamic domain)
875 */
876 AdaptiveDynamicDomainParameters addParams;
877
878 /**
879 * @brief The worker id of this trees owner. (only used for sending updates and skipping updates send by this tree)
880 */
881 std::size_t workerId;
882 /**
883 * @brief The number of nodes in the rrt.
884 */
885 std::size_t nodeCount;
886
887 /**
888 * @brief Updates to apply to the tree.
889 */
890 std::deque<Update> pendingUpdates; //only default init required
891
892 /**
893 * @brief Speeds up lookup for available updates. (O(log(n)) instead of O(n))
894 *
895 * maps from UpdateId to the corresponding index in the pendingUpdates vector
896 */
898 };
899} // namespace armarx::addirrtstar
uint8_t index
NodeId addNode(ConfigType cfg, const NodeId &parent, float fromParentCost)
Adds a node to the tree.
Definition Tree.cpp:235
std::deque< GoalInfo > goalNodes
List of nodes able to reach the goal configuration.
Definition Tree.h:871
PathWithCost getNthPathWithCost(std::size_t n) const
Definition Tree.cpp:426
std::unordered_map< std::pair< std::size_t, std::size_t >, std::size_t > PendingUpdateLookuptableType
Lookuptable for pending updates.
Definition Tree.h:92
FullIceTree getIceTree() const
Definition Tree.cpp:475
std::pair< NodeId, float > getNearestNeighbourAndDistance(const ConfigType &cfg)
Definition Tree.h:659
void init(const FullIceTree &iceTree, AdaptiveDynamicDomainParameters newaddParams, std::size_t newWorkerId)
Initailizes the tree from the given tree.
Definition Tree.cpp:54
NodeId doAddNode(ConfigType cfg, const NodeId &parent, float fromParentCost, std::size_t workerId)
Adds a node to the tree.
Definition Tree.cpp:258
void applyNodeCreationUpdate(const NodeCreationUpdate &u, std::size_t workerId)
Applies a node creation update to the tree.
Definition Tree.h:321
Ice::Long getCurrentUpdateId() const
Definition Tree.h:274
void sendCurrentUpdate(TreeUpdateInterfacePrx &prx)
Sends the current update to the given proxy.
Definition Tree.cpp:178
PendingUpdateLookuptableConstIterator findPendingUpdate(std::size_t workerId, std::size_t updateId) const
Definition Tree.h:525
void applyPendingUpdates()
Applies all pending updates.
Definition Tree.h:206
NodeId getNextNodeIdFor(std::size_t workerId)
Definition Tree.h:829
AdaptiveDynamicDomainParameters addParams
The parameters of adaptive dynamic domain)
Definition Tree.h:876
NodeType & at(std::size_t index)
Definition Tree.h:724
void decreaseRadius(const NodeId &id)
Decreases a node's radius.
Definition Tree.h:559
std::deque< GoalInfo >::const_iterator getBestCostIt() const
Definition Tree.h:749
std::size_t workerId
The worker id of this trees owner.
Definition Tree.h:881
void createNewGoalReachedUpdate(const NodeId &goal, float costToGoToGoal)
Adds a new goal reached update to the current update.
Definition Tree.h:392
Update & getCurrentUpdateNonConst()
Definition Tree.h:304
void applyGoalReachedUpdates(const GoalInfoList newGoalNodes)
Applies multiple goal reached updates to the tree.
Definition Tree.h:337
const Update & getPendingUpdate(std::size_t workerId, std::size_t updateId) const
Definition Tree.h:194
NodeType & getNode(const NodeId &id)
Definition Tree.cpp:358
PendingUpdateLookuptableIterator findPendingUpdate(std::size_t workerId, std::size_t updateId)
Definition Tree.h:514
void applyUpdate(const Update &u)
Applies the given update.
Definition Tree.cpp:139
std::deque< Update > pendingUpdates
Updates to apply to the tree.
Definition Tree.h:890
void doSetNodeParent(const NodeId &child, const NodeId &newParent, float fromParentCost, bool updateFromStartCost=true)
Sets the parent node of child to parent.
Definition Tree.cpp:281
void doDecreaseRadius(const NodeId &id)
Decreases a node's radius.
Definition Tree.cpp:302
std::size_t nodeCount
The number of nodes in the rrt.
Definition Tree.h:885
PathWithCost getBestPath() const
Definition Tree.cpp:416
std::deque< Update > localUpdates
Updates created by this tree.
Definition Tree.h:861
VectorXf ConfigType
The type of configurations.
Definition Tree.h:56
float getBestCost() const
Definition Tree.cpp:406
std::deque< std::deque< NodeType > > nodes
Holds all nodes.
Definition Tree.h:867
Tree()=default
Default ctor.
const Ice::LongSeq & getAppliedUpdateIds() const
Definition Tree.h:845
void applyRadiusUpdate(const RadiusUpdate &u)
Applies a radius update to the tree.
Definition Tree.cpp:191
void doAddGoalReached(const NodeId &goal, float costToGoToGoal)
Adds a node to the list of nodes that can reach the goal configuration.
Definition Tree.h:639
void doIncreaseRadius(const NodeId &id)
Increases a node's radius.
Definition Tree.h:628
void createNewNodeCreationUpdate(const ConfigType &cfg, const NodeId &parent, float fromParentCost)
Adds a new node creation update to the current update.
Definition Tree.h:365
Ice::LongSeq appliedUpdateIds
List of ids of applied updates.
Definition Tree.h:854
void addGoalReached(const NodeId &goal, float costToGoToGoal)
Adds a node to the list of nodes that can reach the goal configuration.
Definition Tree.h:582
const Update & getCurrentUpdate() const
Definition Tree.h:294
NodeType & at(const NodeId &id)
Definition Tree.h:704
typename PendingUpdateLookuptableType::iterator PendingUpdateLookuptableIterator
Iterator for the PendingUpdateLookuptable.
Definition Tree.h:97
PendingUpdateLookuptableType pendingUpdatesLookupTable
Speeds up lookup for available updates.
Definition Tree.h:897
const NodeType & at(const NodeId &id) const
Definition Tree.h:714
NodeIdList getNthPathIds(std::size_t n) const
Definition Tree.cpp:435
const std::deque< std::deque< NodeType > > & getNodes() const
Definition Tree.h:679
bool hasGoalNode(const NodeId &nodeId) const
Definition Tree.h:778
void applyPendingUpdate(std::size_t updateIndex, LockType &&treeLock, RemoteUpdateGetter getRemoteUpdate, UpdateConsumer updateConsumer)
Applies one pending update from the list of pending updates.
Definition Tree.h:407
bool hasAppliedUpdate(std::size_t workerId, Ice::Long updateId)
Definition Tree.h:171
void increaseWorkerCountTo(std::size_t count)
Increases the storage of all data structures to be appropriate for count workers.
Definition Tree.cpp:108
bool hasPendingUpdate(std::size_t workerId, std::size_t updateId) const
Definition Tree.h:183
const std::deque< Update > & getLocalUpdates() const
Definition Tree.h:160
NodeId getIdOfIndex(std::size_t index) const
Definition Tree.cpp:378
void prepareUpdate(Ice::LongSeq dependetOnUpdateIds, LockType &&treeLock, RemoteUpdateGetter getRemoteUpdate, UpdateConsumer updateConsumer)
Prepares an update by applying all dependet on updates.
Definition Tree.h:461
void pushCosts(const NodeId &root)
Updates fromStartCosts for all children from root.
Definition Tree.cpp:247
void createNewRadiusUpdate(const NodeId &id, bool increaseRadius)
Adds a new radius update to the current update.
Definition Tree.h:353
void increaseRadius(const NodeId &id)
Increases a node's radius.
Definition Tree.h:570
const NodeType & at(std::size_t index) const
Definition Tree.h:734
void addPendingUpdate(const Update &u)
Adds a new update to the list of pending updates.
Definition Tree.cpp:502
void createNewRewireUpdate(const NodeId &child, const NodeId &newParent, float fromParentCost)
Adds a new node creation update to the current update.
Definition Tree.h:380
bool canApplyUpdate(const Update &u)
Definition Tree.cpp:123
void applyPendingUpdates(LockType &&treeLock, RemoteUpdateGetter getRemoteUpdate)
The same as applyPendingUpdates(LockType, RemoteUpdateGetter, UpdateConsumer) but uses an noop as upd...
Definition Tree.h:230
void setNodeParent(const NodeId &child, const NodeId &newParent, float fromParentCost)
Sets the parent node of child to parent.
Definition Tree.h:548
void applyPendingUpdates(LockType &&treeLock, RemoteUpdateGetter getRemoteUpdate, UpdateConsumer updateConsumer=[](Update &&) {})
Applies all pending updates.
Definition Tree.h:244
typename PendingUpdateLookuptableType::const_iterator PendingUpdateLookuptableConstIterator
Const iterator for the PendingUpdateLookuptable.
Definition Tree.h:101
std::size_t size() const
Definition Tree.h:694
Ice::Long getPreviousUpdateId() const
Definition Tree.h:285
float getNthPathCost(std::size_t n) const
Definition Tree.h:799
std::size_t getPathCount() const
Definition Tree.h:789
VectorXfSeq getPathTo(NodeId id) const
Definition Tree.cpp:456
static const NodeId ROOT_ID
The root node's id.
Definition Tree.h:839
void prepareNextUpdate()
Prepares the next update.
Definition Tree.cpp:226
void applyRewireUpdate(const RewireUpdate &rewireUpdate)
Applies a rewire update to the tree.
Definition Tree.cpp:204
std::vector< std::pair< NodeId, float > > getKNearestNeighboursAndDistances(const ConfigType &cfg, std::size_t k)
Definition Tree.cpp:317
#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_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
Represents a node of thr rrt.
Definition Tree.h:62
float radius
The node's radius.
Definition Tree.h:74
float fromStartCost
Cost of the path (sttart node, this node)
Definition Tree.h:82
NodeId parent
The node's parent.
Definition Tree.h:70
ConfigType config
The node's configuration.
Definition Tree.h:66
std::set< NodeId > children
Link to all children nodes.
Definition Tree.h:86
float fromParentCost
Cost of the edge (parent node, this node)
Definition Tree.h:78