Loading...
Searching...
No Matches
Vertex.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2014, University of Toronto
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the University of Toronto nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Authors: Jonathan Gammell, Marlin Strub */
36
37// My definition:
38#include "ompl/geometric/planners/informedtrees/bitstar/Vertex.h"
39
40// For std::move
41#include <utility>
42
43// For std::once_flag
44#include <mutex>
45
46// For exceptions:
47#include "ompl/util/Exception.h"
48
49// BIT*:
50// A collection of common helper functions
51#include "ompl/geometric/planners/informedtrees/bitstar/HelperFunctions.h"
52// The ID generator class
53#include "ompl/geometric/planners/informedtrees/bitstar/IdGenerator.h"
54// The cost-helper class:
55#include "ompl/geometric/planners/informedtrees/bitstar/CostHelper.h"
56
57// Debug macros.
58#ifdef BITSTAR_DEBUG
59// Debug setting. The id number of a vertex to track. Requires BITSTAR_DEBUG to be defined in BITstar.h
60#define TRACK_VERTEX_ID 0
61
63#define PRINT_VERTEX_CHANGE \
64 if (id_ == TRACK_VERTEX_ID) \
65 { \
66 std::cout << "Vertex " << id_ << ": " << __func__ << "" << std::endl; \
67 }
68
70#define ASSERT_NOT_PRUNED \
71 if (this->isPruned_) \
72 { \
73 std::cout << "Vertex " << id_ << ": " << __func__ << std::endl; \
74 throw ompl::Exception("Attempting to access a pruned vertex."); \
75 }
76#else
77#define PRINT_VERTEX_CHANGE
78#define ASSERT_NOT_PRUNED
79#endif // BITSTAR_DEBUG
80
81// An anonymous namespace to hide the instance:
82namespace
83{
84 // Global variables:
85 // The initialization flag stating that the ID generator has been created:
86 std::once_flag g_IdInited;
87 // A pointer to the actual ID generator
88 boost::scoped_ptr<ompl::geometric::BITstar::IdGenerator> g_IdGenerator;
89
90 // A function to initialize the ID generator pointer:
91 void initIdGenerator()
92 {
93 g_IdGenerator.reset(new ompl::geometric::BITstar::IdGenerator());
94 }
95
96 // A function to get the current ID generator:
98 {
99 std::call_once(g_IdInited, &initIdGenerator);
100 return *g_IdGenerator;
101 }
102} // namespace
103
104namespace ompl
105{
106 namespace geometric
107 {
109 // Public functions:
110 BITstar::Vertex::Vertex(ompl::base::SpaceInformationPtr spaceInformation, const CostHelper *const costHelpPtr,
111 SearchQueue *const queuePtr, const std::shared_ptr<const unsigned int> &approximationId,
112 bool root)
113 : id_(getIdGenerator().getNewId())
114 , si_(std::move(spaceInformation))
115 , costHelpPtr_(std::move(costHelpPtr))
116 , queuePtr_(queuePtr)
117 , state_(si_->allocState())
118 , isRoot_(root)
119 , edgeCost_(costHelpPtr_->infiniteCost())
120 , cost_(costHelpPtr_->infiniteCost())
121 , costAtExpansion_(costHelpPtr_->infiniteCost())
122 , currentSearchId_(queuePtr->getSearchId())
123 , currentApproximationId_(approximationId)
124 {
125 PRINT_VERTEX_CHANGE
126
127 if (this->isRoot())
128 {
129 cost_ = costHelpPtr_->identityCost();
130 }
131 // No else, infinite by default
132 }
133
134 BITstar::Vertex::~Vertex()
135 {
136 PRINT_VERTEX_CHANGE
137
138 // Free the state on destruction
139 si_->freeState(state_);
140 }
141
142 BITstar::VertexId BITstar::Vertex::getId() const
143 {
144 ASSERT_NOT_PRUNED
145
146 return id_;
147 }
148
149 ompl::base::State const *BITstar::Vertex::state() const
150 {
151 ASSERT_NOT_PRUNED
152
153 return state_;
154 }
155
156 ompl::base::State *BITstar::Vertex::state()
157 {
158 PRINT_VERTEX_CHANGE
159 ASSERT_NOT_PRUNED
160
161 return state_;
162 }
163
165 // The vertex's graph properties:
166 bool BITstar::Vertex::isRoot() const
167 {
168 ASSERT_NOT_PRUNED
169
170 return isRoot_;
171 }
172
173 bool BITstar::Vertex::hasParent() const
174 {
175 ASSERT_NOT_PRUNED
176
177 return static_cast<bool>(parentPtr_);
178 }
179
180 bool BITstar::Vertex::isInTree() const
181 {
182 ASSERT_NOT_PRUNED
183
184 return this->isRoot() || this->hasParent();
185 }
186
187 unsigned int BITstar::Vertex::getDepth() const
188 {
189 ASSERT_NOT_PRUNED
190
191#ifdef BITSTAR_DEBUG
192 if (!this->isRoot() && !this->hasParent())
193 {
194 throw ompl::Exception("Attempting to get the depth of a vertex that does not have a parent yet is not "
195 "root.");
196 }
197#endif // BITSTAR_DEBUG
198
199 return depth_;
200 }
201
202 BITstar::VertexConstPtr BITstar::Vertex::getParent() const
203 {
204 ASSERT_NOT_PRUNED
205
206#ifdef BITSTAR_DEBUG
207 if (!this->hasParent())
208 {
209 if (this->isRoot())
210 {
211 throw ompl::Exception("Attempting to access the parent of the root vertex.");
212 }
213 else
214 {
215 throw ompl::Exception("Attempting to access the parent of a vertex that does not have one.");
216 }
217 }
218#endif // BITSTAR_DEBUG
219
220 return parentPtr_;
221 }
222
223 BITstar::VertexPtr BITstar::Vertex::getParent()
224 {
225 ASSERT_NOT_PRUNED
226
227#ifdef BITSTAR_DEBUG
228 if (!this->hasParent())
229 {
230 if (this->isRoot())
231 {
232 throw ompl::Exception("Attempting to access the parent of the root vertex.");
233 }
234 else
235 {
236 throw ompl::Exception("Attempting to access the parent of a vertex that does not have one.");
237 }
238 }
239#endif // BITSTAR_DEBUG
240
241 return parentPtr_;
242 }
243
244 void BITstar::Vertex::addParent(const VertexPtr &newParent, const ompl::base::Cost &edgeInCost)
245 {
246 PRINT_VERTEX_CHANGE
247 ASSERT_NOT_PRUNED
248
249#ifdef BITSTAR_DEBUG
250 // Assert I can take a parent
251 if (this->isRoot())
252 {
253 throw ompl::Exception("Attempting to add a parent to the root vertex, which cannot have a parent.");
254 }
255 if (this->hasParent())
256 {
257 throw ompl::Exception("Attempting to add a parent to a vertex that already has one.");
258 }
259#endif // BITSTAR_DEBUG
260
261 // Store the parent.
262 parentPtr_ = newParent;
263
264 // Store the edge cost.
265 edgeCost_ = edgeInCost;
266
267 // Update my cost and that of my children.
268 this->updateCostAndDepth(true);
269 }
270
271 void BITstar::Vertex::removeParent(bool updateChildCosts)
272 {
273 PRINT_VERTEX_CHANGE
274 ASSERT_NOT_PRUNED
275
276#ifdef BITSTAR_DEBUG
277 // Assert I have a parent
278 if (this->isRoot())
279 {
280 throw ompl::Exception("Attempting to remove the parent of the root vertex, which cannot have a "
281 "parent.");
282 }
283 if (!this->hasParent())
284 {
285 throw ompl::Exception("Attempting to remove the parent of a vertex that does not have a parent.");
286 }
287#endif // BITSTAR_DEBUG
288
289 // Clear my parent
290 parentPtr_.reset();
291
292 // Update my cost and possibly the cost of my descendants:
293 this->updateCostAndDepth(updateChildCosts);
294 }
295
296 bool BITstar::Vertex::hasChildren() const
297 {
298 ASSERT_NOT_PRUNED
299
300 return !children_.empty();
301 }
302
303 void BITstar::Vertex::getChildren(VertexConstPtrVector *children) const
304 {
305 ASSERT_NOT_PRUNED
306
307 children->clear();
308
309 for (const auto &child : children_)
310 {
311#ifdef BITSTAR_DEBUG
312 // Check that the weak pointer hasn't expired
313 if (child.expired())
314 {
315 throw ompl::Exception("A (weak) pointer to a child was found to have expired while collecting the "
316 "children of a vertex.");
317 }
318#endif // BITSTAR_DEBUG
319
320 // Lock and push back
321 children->push_back(child.lock());
322 }
323 }
324
325 void BITstar::Vertex::getChildren(VertexPtrVector *children)
326 {
327 ASSERT_NOT_PRUNED
328
329 children->clear();
330
331 for (const auto &child : children_)
332 {
333#ifdef BITSTAR_DEBUG
334 // Check that the weak pointer hasn't expired
335 if (child.expired())
336 {
337 throw ompl::Exception("A (weak) pointer to a child was found to have expired while collecting the "
338 "children of a vertex.");
339 }
340#endif // BITSTAR_DEBUG
341
342 // Lock and push back
343 children->push_back(child.lock());
344 }
345 }
346
347 void BITstar::Vertex::addChild(const VertexPtr &child)
348 {
349 PRINT_VERTEX_CHANGE
350 ASSERT_NOT_PRUNED
351
352#ifdef BITSTAR_DEBUG
353 // Assert that I am this child's parent
354 if (child->isRoot())
355 {
356 throw ompl::Exception("Attempted to add a root vertex as a child.");
357 }
358 if (!child->hasParent())
359 {
360 throw ompl::Exception("Attempted to add child that does not have a listed parent.");
361 }
362 if (child->getParent()->getId() != id_)
363 {
364 throw ompl::Exception("Attempted to add someone else's child as mine.");
365 }
366#endif // BITSTAR_DEBUG
367
368 // Push back the shared_ptr into the vector of weak_ptrs, this makes a weak_ptr copy
369 children_.push_back(child);
370
371 // Leave the costs of the child out of date.
372 }
373
374 void BITstar::Vertex::removeChild(const VertexPtr &child)
375 {
376 PRINT_VERTEX_CHANGE
377 ASSERT_NOT_PRUNED
378
379#ifdef BITSTAR_DEBUG
380 // Assert that I am this child's parent
381 if (child->isRoot())
382 {
383 throw ompl::Exception("Attempted to remove a root vertex as a child.");
384 }
385 if (!child->hasParent())
386 {
387 throw ompl::Exception("Attempted to remove a child that does not have a listed parent.");
388 }
389 if (child->getParent()->getId() != id_)
390 {
391 throw ompl::Exception("Attempted to remove a child vertex from the wrong parent.");
392 }
393
394 // Variables
395 // Whether the child has been found (and then deleted);
396 bool foundChild;
397
398 // Iterate over the vector of children pointers until the child is found. Iterators make erase easier
399 foundChild = false;
400#endif // BITSTAR_DEBUG
401 for (auto it = children_.begin(); it != children_.end(); ++it)
402 {
403#ifdef BITSTAR_DEBUG
404 // Check that the weak pointer hasn't expired
405 if (it->expired())
406 {
407 throw ompl::Exception("A (weak) pointer to a child was found to have expired while removing a "
408 "child from a vertex.");
409 }
410#endif // BITSTAR_DEBUG
411
412 // Check if this is the child we're looking for
413 if (it->lock()->getId() == child->getId())
414 {
415#ifdef BITSTAR_DEBUG
416 // It is, mark as found
417 foundChild = true;
418#endif // BITSTAR_DEBUG
419
420 // First, clear the entry in the vector
421 it->reset();
422
423 // Then remove that entry from the vector efficiently
424 swapPopBack(it, &children_);
425 break;
426 }
427 // No else.
428 }
429
430 // Leave the costs of the child out of date.
431#ifdef BITSTAR_DEBUG
432 if (!foundChild)
433 {
434 throw ompl::Exception("Attempting to remove a child vertex not present in the vector of children "
435 "stored in the (supposed) parent vertex.");
436 }
437#endif // BITSTAR_DEBUG
438 }
439
440 void BITstar::Vertex::blacklistChild(const VertexConstPtr &vertex)
441 {
442 childIdBlacklist_.emplace(vertex->getId());
443 }
444
445 void BITstar::Vertex::whitelistChild(const VertexConstPtr &vertex)
446 {
447 childIdWhitelist_.emplace(vertex->getId());
448 }
449
450 bool BITstar::Vertex::isBlacklistedAsChild(const VertexConstPtr &vertex) const
451 {
452 return childIdBlacklist_.find(vertex->getId()) != childIdBlacklist_.end();
453 }
454
455 bool BITstar::Vertex::isWhitelistedAsChild(const VertexConstPtr &vertex) const
456 {
457 return childIdWhitelist_.find(vertex->getId()) != childIdWhitelist_.end();
458 }
459
460 void BITstar::Vertex::clearBlacklist()
461 {
462 childIdBlacklist_.clear();
463 }
464
465 void BITstar::Vertex::clearWhitelist()
466 {
467 childIdWhitelist_.clear();
468 }
469
470 ompl::base::Cost BITstar::Vertex::getCost() const
471 {
472 ASSERT_NOT_PRUNED
473
474 return cost_;
475 }
476
477 ompl::base::Cost BITstar::Vertex::getEdgeInCost() const
478 {
479 ASSERT_NOT_PRUNED
480
481#ifdef BITSTAR_DEBUG
482 if (!this->hasParent())
483 {
484 throw ompl::Exception("Attempting to access the incoming-edge cost of a vertex without a parent.");
485 }
486#endif // BITSTAR_DEBUG
487
488 return edgeCost_;
489 }
490
491 bool BITstar::Vertex::isConsistent() const
492 {
493 return cost_.value() == costAtExpansion_.value();
494 }
495
496 bool BITstar::Vertex::isPruned() const
497 {
498 return isPruned_;
499 }
500
501 bool BITstar::Vertex::isExpandedOnCurrentApproximation() const
502 {
503 return expansionApproximationId_ == *currentApproximationId_;
504 }
505
506 bool BITstar::Vertex::isExpandedOnCurrentSearch() const
507 {
508 return expansionSearchId_ == *currentSearchId_;
509 }
510
511 bool BITstar::Vertex::hasEverBeenExpandedAsRewiring() const
512 {
513 return hasEverBeenExpandedAsRewiring_;
514 }
515
516 void BITstar::Vertex::registerExpansion()
517 {
518 // Store the cost-to-come at expansion.
519 costAtExpansion_ = cost_;
520
521 // Remember the search and approximation ids.
522 expansionApproximationId_ = *currentApproximationId_;
523 expansionSearchId_ = *currentSearchId_;
524 }
525
526 void BITstar::Vertex::registerRewiringExpansion()
527 {
528 hasEverBeenExpandedAsRewiring_ = true;
529 }
530
531 void BITstar::Vertex::markPruned()
532 {
533 PRINT_VERTEX_CHANGE
534 ASSERT_NOT_PRUNED
535
536 isPruned_ = true;
537 }
538
539 void BITstar::Vertex::markUnpruned()
540 {
541 PRINT_VERTEX_CHANGE
542
543 isPruned_ = false;
544 }
545
546 void BITstar::Vertex::insertInEdgeQueueInLookup(const SearchQueue::EdgeQueueElemPtr &element)
547 {
548 ASSERT_NOT_PRUNED
549
550 // Conditionally clear any existing lookups.
551 this->clearLookupsIfOutdated();
552
553#ifdef BITSTAR_DEBUG
554 // Assert that this edge is NOT _from_ this vertex.
555 if (element->data.second.first->getId() == id_)
556 {
557 throw ompl::Exception("Attempted to add a cyclic incoming queue edge.");
558 }
559 // Assert that this edge is _to_ this vertex.
560 if (element->data.second.second->getId() != id_)
561 {
562 throw ompl::Exception("Attempted to add an incoming queue edge to the wrong vertex.");
563 }
564 // Assert that an edge from this source does not already exist.
565 for (const auto &inEdge : edgeQueueInLookup_)
566 {
567 if (element->data.second.first->getId() == inEdge->data.second.first->getId())
568 {
569 throw ompl::Exception("Attempted to add a second edge to the queue from a single source vertex.");
570 }
571 }
572#endif // BITSTAR_DEBUG
573
574 // Insert it into the lookup.
575 edgeQueueInLookup_.push_back(element);
576 }
577
578 void BITstar::Vertex::removeFromEdgeQueueInLookup(const SearchQueue::EdgeQueueElemPtr &element)
579 {
580 ASSERT_NOT_PRUNED
581
582#ifdef BITSTAR_DEBUG
583 // Assert that the edge queue entries we have are of the same set as the one we're seeking to delete.
584 // If so, there's no point clearing them, as then we'd be trying to remove an edge that doesn't exist which
585 // would be an error.
586 if (*currentApproximationId_ != lookupApproximationId_)
587 {
588 throw ompl::Exception(
589 "Attempted to remove an incoming queue edge added under a different expansion id.");
590 }
591
592 // Variable
593 // Element found
594 bool found = false;
595#endif // BITSTAR_DEBUG
596
597 // Iterate through the list and find the address of the element to delete
598 for (auto it = edgeQueueInLookup_.begin(); it != edgeQueueInLookup_.end(); ++it)
599 {
600 // Is it the element we're looking for? Source id
601 if ((*it)->data.second.first->getId() == element->data.second.first->getId())
602 {
603 // Remove by iterator
605
606#ifdef BITSTAR_DEBUG
607 // Mark as found
608 found = true;
609#endif // BITSTAR_DEBUG
610 break;
611 }
612 // No else, try the next
613 }
614
615#ifdef BITSTAR_DEBUG
616 if (!found)
617 {
618 throw ompl::Exception("Attempted to remove an edge not in the incoming lookup.");
619 }
620#endif // BITSTAR_DEBUG
621 }
622
623 void
624 BITstar::Vertex::removeFromEdgeQueueInLookup(const SearchQueue::EdgeQueueElemPtrVector::const_iterator &element)
625 {
626 ASSERT_NOT_PRUNED
627
628#ifdef BITSTAR_DEBUG
629 // Assert that the edge queue entries we have are of the same set as the one we're seeking to delete.
630 // If so, there's no point clearing them, as then we'd be trying to remove an edge that doesn't exist which
631 // would be an error.
632 if (*currentApproximationId_ != lookupApproximationId_)
633 {
634 throw ompl::Exception(
635 "Attempted to remove an incoming queue edge added under a different expansion id.");
636 }
637#endif // BITSTAR_DEBUG
638
639 // Remove a non-const version of the given iterator.
640 // (trick from https://stackoverflow.com/a/10669041/1442500)
641 this->removeFromEdgeQueueInLookup(edgeQueueInLookup_.erase(element, element));
642 }
643
644 void BITstar::Vertex::clearEdgeQueueInLookup()
645 {
646 ASSERT_NOT_PRUNED
647
648 edgeQueueInLookup_.clear();
649 }
650
651 BITstar::SearchQueue::EdgeQueueElemPtrVector::const_iterator BITstar::Vertex::edgeQueueInLookupConstBegin()
652 {
653 ASSERT_NOT_PRUNED
654
655 // Conditionally clear any existing lookups
656 this->clearLookupsIfOutdated();
657
658 return edgeQueueInLookup_.cbegin();
659 }
660
661 BITstar::SearchQueue::EdgeQueueElemPtrVector::const_iterator BITstar::Vertex::edgeQueueInLookupConstEnd()
662 {
663 ASSERT_NOT_PRUNED
664
665 // Conditionally clear any existing lookups
666 this->clearLookupsIfOutdated();
667
668 return edgeQueueInLookup_.cend();
669 }
670
671 unsigned int BITstar::Vertex::edgeQueueInLookupSize()
672 {
673 ASSERT_NOT_PRUNED
674
675 // Conditionally clear any existing lookups
676 this->clearLookupsIfOutdated();
677
678 return edgeQueueInLookup_.size();
679 }
680
681 void BITstar::Vertex::insertInEdgeQueueOutLookup(const SearchQueue::EdgeQueueElemPtr &element)
682 {
683 ASSERT_NOT_PRUNED
684
685 // Conditionally clear any existing lookups
686 this->clearLookupsIfOutdated();
687
688#ifdef BITSTAR_DEBUG
689 // Assert that this edge is _from_ this vertex
690 if (element->data.second.first->getId() != id_)
691 {
692 throw ompl::Exception("Attempted to add an outgoing queue edge to the wrong vertex.");
693 }
694 // Assert that this edge is NOT _to_ this vertex
695 if (element->data.second.second->getId() == id_)
696 {
697 throw ompl::Exception("Attempted to add a cyclic outgoing queue edge.");
698 }
699 // Assert that an edge to this target does not already exist
700 for (const auto &outEdge : edgeQueueOutLookup_)
701 {
702 if (element->data.second.second->getId() == outEdge->data.second.second->getId())
703 {
704 throw ompl::Exception("Attempted to add a second edge to the queue to a single target vertex.");
705 }
706 }
707#endif // BITSTAR_DEBUG
708
709 // Push back
710 edgeQueueOutLookup_.push_back(element);
711 }
712
713 void BITstar::Vertex::removeFromEdgeQueueOutLookup(const SearchQueue::EdgeQueueElemPtr &element)
714 {
715 ASSERT_NOT_PRUNED
716
717#ifdef BITSTAR_DEBUG
718 // Assert that the edge queue entries we have are of the same set as the one we're seeking to delete.
719 // If so, there's no point clearing them, as then we'd be trying to remove an edge that doesn't exist which
720 // would be an error.
721 if (*currentApproximationId_ != lookupApproximationId_)
722 {
723 throw ompl::Exception(
724 "Attempted to remove an incoming queue edge added under a different expansion id.");
725 }
726
727 // Variable
728 // Element found
729 bool found = false;
730#endif // BITSTAR_DEBUG
731
732 // Iterate through the list and find the address of the element to delete
733 for (auto it = edgeQueueOutLookup_.begin(); it != edgeQueueOutLookup_.end(); ++it)
734 {
735 // Is it the element we're looking for? Source id
736 if ((*it)->data.second.second->getId() == element->data.second.second->getId())
737 {
738 // Remove by iterator
740
741#ifdef BITSTAR_DEBUG
742 // Mark as found
743 found = true;
744#endif // BITSTAR_DEBUG
745 break;
746 }
747 // No else, try the next
748 }
749
750#ifdef BITSTAR_DEBUG
751 if (!found)
752 {
753 throw ompl::Exception("Attempted to remove an edge not in the outgoing lookup.");
754 }
755#endif // BITSTAR_DEBUG
756 }
757
758 void BITstar::Vertex::removeFromEdgeQueueOutLookup(
759 const SearchQueue::EdgeQueueElemPtrVector::const_iterator &element)
760 {
761 ASSERT_NOT_PRUNED
762
763#ifdef BITSTAR_DEBUG
764 // Assert that the edge queue entries we have are of the same set as the one we're seeking to delete.
765 // If so, there's no point clearing them, as then we'd be trying to remove an edge that doesn't exist which
766 // would be an error.
767 if (*currentApproximationId_ != lookupApproximationId_)
768 {
769 throw ompl::Exception(
770 "Attempted to remove an outgoing queue edge added under a different expansion id.");
771 }
772#endif // BITSTAR_DEBUG
773
774 // Remove a non-const version of the given iterator
775 // (trick from https://stackoverflow.com/a/10669041/1442500)
776 this->removeFromEdgeQueueOutLookup(edgeQueueOutLookup_.erase(element, element));
777 }
778
779 void BITstar::Vertex::clearEdgeQueueOutLookup()
780 {
781 ASSERT_NOT_PRUNED
782
783 edgeQueueOutLookup_.clear();
784 }
785
786 BITstar::SearchQueue::EdgeQueueElemPtrVector::const_iterator BITstar::Vertex::edgeQueueOutLookupConstBegin()
787 {
788 ASSERT_NOT_PRUNED
789
790 // Make sure the lookups aren't out of date.
791 this->clearLookupsIfOutdated();
792
793 return edgeQueueOutLookup_.cbegin();
794 }
795
796 BITstar::SearchQueue::EdgeQueueElemPtrVector::const_iterator BITstar::Vertex::edgeQueueOutLookupConstEnd()
797 {
798 ASSERT_NOT_PRUNED
799
800 // Make sure the lookups aren't out of date.
801 this->clearLookupsIfOutdated();
802
803 return edgeQueueOutLookup_.cend();
804 }
805
806 unsigned int BITstar::Vertex::edgeQueueOutLookupSize()
807 {
808 ASSERT_NOT_PRUNED
809
810 // Make sure the lookups aren't out of date.
811 this->clearLookupsIfOutdated();
812
813 return edgeQueueOutLookup_.size();
814 }
815
816 void BITstar::Vertex::updateCostAndDepth(bool cascadeUpdates /*= true*/)
817 {
818 PRINT_VERTEX_CHANGE
819 ASSERT_NOT_PRUNED
820
821 if (this->isRoot())
822 {
823 // Am I root? -- I don't really know how this would ever be called, but ok.
824 cost_ = costHelpPtr_->identityCost();
825 depth_ = 0u;
826 }
827 else if (!this->hasParent())
828 {
829 // Am I disconnected?
830 cost_ = costHelpPtr_->infiniteCost();
831
832 // Set the depth to 0u, getDepth will throw in this condition
833 depth_ = 0u;
834
835#ifdef BITSTAR_DEBUG
836 // Assert that I have not been asked to cascade this bad data to my children:
837 if (this->hasChildren() && cascadeUpdates)
838 {
839 throw ompl::Exception("Attempting to update descendants' costs and depths of a vertex that does "
840 "not have a parent and is not root. This information would therefore be "
841 "gibberish.");
842 }
843#endif // BITSTAR_DEBUG
844 }
845 else
846 {
847 // I have a parent, so my cost is my parent cost + my edge cost to the parent
848 cost_ = costHelpPtr_->combineCosts(parentPtr_->getCost(), edgeCost_);
849
850 // If I have outgoing edges in the search queue, they need to be updated.
851 for (const auto &edge : edgeQueueOutLookup_)
852 {
853 if (lookupApproximationId_ == *currentApproximationId_)
854 {
855 queuePtr_->update(edge);
856 }
857 }
858
859 // I am one more than my parent's depth:
860 depth_ = (parentPtr_->getDepth() + 1u);
861 }
862
863 // Am I updating my children?
864 if (cascadeUpdates)
865 {
866 // Now, iterate over my vector of children and tell each one to update its own damn cost:
867 for (auto &child : children_)
868 {
869#ifdef BITSTAR_DEBUG
870 // Check that it hasn't expired
871 if (child.expired())
872 {
873 throw ompl::Exception("A (weak) pointer to a child has was found to have expired while "
874 "updating the costs and depths of descendant vertices.");
875 }
876#endif // BITSTAR_DEBUG
877
878 // Get a lock and tell the child to update:
879 child.lock()->updateCostAndDepth(true);
880 }
881 }
882 // No else, do not update the children. Let's hope the caller knows what they're doing.
883 }
884
885 void BITstar::Vertex::removeFromEdgeQueueInLookup(const SearchQueue::EdgeQueueElemPtrVector::iterator &element)
886 {
887#ifdef BITSTAR_DEBUG
888 // Store the parent id of the edge we're removing.
889 VertexId parentId = (*element)->data.second.first->getId();
890
891 // Assert that this edge is not from this vertex.
892 if (parentId == id_)
893 {
894 throw ompl::Exception("Attempted to remove a cyclic incoming queue edge.");
895 }
896
897 // Assert that this edge is to this vertex.
898 if ((*element)->data.second.second->getId() != id_)
899 {
900 throw ompl::Exception("Attempted to remove an incoming queue edge from the wrong vertex.");
901 }
902
903 // Assert that it could exist.
904 if (edgeQueueInLookup_.empty())
905 {
906 throw ompl::Exception("Attempted to remove an incoming queue edge from a vertex with an empty list.");
907 }
908
909 // Assert that this edge actually exists.
910 bool found = false;
911 for (auto it = edgeQueueInLookup_.begin(); it != edgeQueueInLookup_.end() && !found; ++it)
912 {
913 found = ((*it)->data.second.first->getId() == parentId);
914 }
915 if (!found)
916 {
917 throw ompl::Exception("Attempted to remove an edge not in the incoming lookup.");
918 }
919#endif // BITSTAR_DEBUG
920
921 // Clear our entry in the list
922 *element = nullptr;
923
924 // Remove it efficiently
925 swapPopBack(element, &edgeQueueInLookup_);
926
927#ifdef BITSTAR_DEBUG
928 // Assert that it's now gone.
929 for (const auto &edgePtr : edgeQueueInLookup_)
930 {
931 if (edgePtr->data.second.first->getId() == parentId)
932 {
933 throw ompl::Exception("Failed to remove the designated edge in the incoming lookup.");
934 }
935 }
936#endif // BITSTAR_DEBUG
937 }
938
939 void BITstar::Vertex::removeFromEdgeQueueOutLookup(const SearchQueue::EdgeQueueElemPtrVector::iterator &element)
940 {
941#ifdef BITSTAR_DEBUG
942 // Store the child id of the edge we're removing.
943 VertexId childId = (*element)->data.second.second->getId();
944
945 // Assert that this edge is this vertex.
946 if ((*element)->data.second.first->getId() != id_)
947 {
948 throw ompl::Exception("Attempted to remove an outgoing queue edge from the wrong vertex.");
949 }
950 // Assert that this edge is not to this vertex.
951 if (childId == id_)
952 {
953 throw ompl::Exception("Attempted to remove a cyclic outgoing queue edge.");
954 }
955 // Assert that it could exist
956 if (edgeQueueOutLookup_.empty())
957 {
958 throw ompl::Exception("Attempted to remove an outgoing queue edge from a vertex with an empty list.");
959 }
960 // Assert that this edge actually exists
961 bool found = false;
962 for (auto it = edgeQueueOutLookup_.begin(); it != edgeQueueOutLookup_.end() && !found; ++it)
963 {
964 found = ((*it)->data.second.second->getId() == childId);
965 }
966 if (!found)
967 {
968 throw ompl::Exception("Attempted to remove an edge not in the outgoing lookup.");
969 }
970#endif // BITSTAR_DEBUG
971
972 // Clear our entry in the list.
973 *element = nullptr;
974
975 // Remove it efficiently.
976 swapPopBack(element, &edgeQueueOutLookup_);
977
978#ifdef BITSTAR_DEBUG
979 // Assert that it's now gone.
980 for (const auto &edgePtr : edgeQueueOutLookup_)
981 {
982 if (edgePtr->data.second.second->getId() == childId)
983 {
984 throw ompl::Exception("Failed to remove the designated edge in the outgoing lookup.");
985 }
986 }
987#endif // BITSTAR_DEBUG
988 }
989
990 void BITstar::Vertex::clearLookupsIfOutdated()
991 {
992 // Clean up any old lookups.
993 if (lookupApproximationId_ != *currentApproximationId_)
994 {
995 // Clear the existing entries.
996 this->clearEdgeQueueInLookup();
997 this->clearEdgeQueueOutLookup();
998
999 // Update the counter.
1000 lookupApproximationId_ = *currentApproximationId_;
1001 }
1002 // No else, this is the same pass through the vertex queue.
1003 }
1004 } // namespace geometric
1005} // namespace ompl
The exception type for ompl.
Definition Exception.h:47
Definition of a cost value. Can represent the cost of a motion or the cost of a state.
Definition Cost.h:48
double value() const
The value of the cost.
Definition Cost.h:56
Definition of an abstract state.
Definition State.h:50
A helper class to handle the various heuristic functions in one place.
Definition CostHelper.h:69
An ID generator class for vertex IDs.
Definition IdGenerator.h:59
A queue of edges, sorted according to a sort key.
Definition SearchQueue.h:65
EdgeQueue::Element * EdgeQueueElemPtr
An element pointer into the edge queue binary heap.
Definition SearchQueue.h:85
bool hasParent() const
Returns whether this vertex has a parent.
Definition Vertex.cpp:173
void removeFromEdgeQueueOutLookup(const SearchQueue::EdgeQueueElemPtr &outEdge)
Remove an outgoing edge queue entry by value.
Definition Vertex.cpp:713
VertexConstPtr getParent() const
Get a const pointer to the parent of this vertex.
Definition Vertex.cpp:202
bool isRoot() const
Returns whether the vertex is the root of the search tree.
Definition Vertex.cpp:166
BITstar::VertexId getId() const
The (unique) vertex ID.
Definition Vertex.cpp:142
void removeFromEdgeQueueInLookup(const SearchQueue::EdgeQueueElemPtr &inEdge)
Remove an incoming edge queue entry by value to the member vector.
Definition Vertex.cpp:578
std::vector< VertexConstPtr > VertexConstPtrVector
A vector of shared pointers to const vertices.
Definition BITstar.h:128
std::vector< VertexPtr > VertexPtrVector
A vector of shared pointers to vertices.
Definition BITstar.h:125
std::shared_ptr< const Vertex > VertexConstPtr
A shared pointer to a const vertex.
Definition BITstar.h:119
std::shared_ptr< Vertex > VertexPtr
A shared pointer to a vertex.
Definition BITstar.h:116
unsigned int VertexId
The vertex id type.
Definition BITstar.h:131
This namespace contains code that is specific to planning under geometric constraints.
Main namespace. Contains everything in this library.
STL namespace.