Loading...
Searching...
No Matches
Vertex.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2025, University of New Hampshire
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 names of the copyright holders 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: Yi Wang, Eyal Weiss, Bingxian Mu, Oren Salzman
36#include "ompl/geometric/planners/lazyinformedtrees/blitstar/Vertex.h"
37
38#include <algorithm>
39#include <atomic>
40#include <cmath>
41#include <string>
42
43#include "ompl/base/goals/GoalState.h"
44#include "ompl/base/goals/GoalStates.h"
45using namespace std;
46using namespace std::string_literals;
47
48namespace ompl
49{
50 namespace geometric
51 {
52 namespace blitstar
53 {
54 namespace
55 {
56 std::size_t generateId()
57 {
58 static std::atomic<std::size_t> id{0u};
59 return id++;
60 }
61 } // namespace
62
63 Vertex::Vertex(const ompl::base::SpaceInformationPtr &spaceInformation,
64 const ompl::base::ProblemDefinitionPtr &problemDefinition, const std::size_t &batchId)
65 : spaceInformation_(spaceInformation)
66 , problemDefinition_(problemDefinition)
67 , objective_(problemDefinition->getOptimizationObjective())
68 , forwardChildren_()
69 , reverseChildren_()
70 , forwardParent_()
71 , reverseParent_()
72 , state_(spaceInformation->allocState()) // The memory allocated here is freed in the destructor.
73 , costToComeFromStart_(objective_->infiniteCost())
74 , costToComeFromGoal_(objective_->infiniteCost())
75 , edgeCostFromForwardParent_(objective_->infiniteCost())
76 , expandedCostToComeFromGoal_(objective_->infiniteCost())
77 , costToGoToGoal_(objective_->infiniteCost())
78 , costToGoToStart_(objective_->infiniteCost())
79 , vertexId_(generateId())
80 , batchId_(batchId)
81 {
82 }
83
84 Vertex::Vertex(const std::shared_ptr<Vertex> &other)
85 : spaceInformation_(other->spaceInformation_)
86 , problemDefinition_(other->problemDefinition_)
87 , objective_(other->objective_)
88 , forwardChildren_(other->forwardChildren_)
89 , reverseChildren_(other->reverseChildren_)
90 , forwardParent_(other->forwardParent_)
91 , reverseParent_(other->reverseParent_)
92 , state_(spaceInformation_->allocState()) // The memory allocated here is freed in the destructor.
93 , costToComeFromStart_(other->costToComeFromStart_)
94 , costToComeFromGoal_(other->costToComeFromGoal_)
95 , edgeCostFromForwardParent_(other->edgeCostFromForwardParent_)
96 , expandedCostToComeFromGoal_(other->expandedCostToComeFromGoal_)
97 , costToGoToGoal_(other->costToGoToGoal_)
98 , costToGoToStart_(other->costToGoToStart_)
99 , vertexId_(other->vertexId_)
100 , batchId_(other->batchId_)
101 {
102 spaceInformation_->copyState(state_, other->getState());
103 }
104
105 Vertex::~Vertex()
106 {
107 // The state has associated memory that needs to be freed manually.
108 spaceInformation_->freeState(state_);
109 };
110
111 std::size_t Vertex::getId() const
112 {
113 return vertexId_;
114 }
115
116 ompl::base::State *Vertex::getState()
117 {
118 return state_;
119 }
120
121 ompl::base::State const *Vertex::getState() const
122 {
123 return state_;
124 }
125
126 ompl::base::ScopedState<> Vertex::getScopedState() const
127 {
128 return ompl::base::ScopedState<>(spaceInformation_->getStateSpace(), state_);
129 }
130
131 ompl::base::Cost Vertex::getCostToComeFromStart() const
132 {
133 return costToComeFromStart_;
134 }
135
136 bool Vertex::isGoal()
137 {
138 return goalVertex_;
139 }
140
141 bool Vertex::isStart()
142 {
143 return startVertex_;
144 }
145 void Vertex::setGoalVertex()
146 {
147 goalVertex_ = true;
148 }
149 void Vertex::setStartVertex()
150 {
151 startVertex_ = true;
152 }
153
154 void Vertex::setForwardId(const std::size_t counter)
155 {
156 ForwardVersion_ = counter;
157 }
158 std::size_t Vertex::getForwardId()
159 {
160 return ForwardVersion_;
161 }
162 void Vertex::resetForwardId()
163 {
164 ForwardVersion_ = 0u;
165 }
166
167 void Vertex::setReverseId(const std::size_t counter)
168 {
169 ReverseVersion_ = counter;
170 }
171 std::size_t Vertex::getReverseId()
172 {
173 return ReverseVersion_;
174 }
175 void Vertex::resetReverseId()
176 {
177 ReverseVersion_ = 0u;
178 }
179
180 ompl::base::Cost Vertex::getCostToComeFromGoal() const
181 {
182 return costToComeFromGoal_;
183 }
184
185 ompl::base::Cost Vertex::getCostToGoToGoal() const
186 {
187 return getCostToComeFromGoal();
188 }
189
190 ompl::base::Cost Vertex::getEdgeCostFromForwardParent() const
191 {
192 return edgeCostFromForwardParent_;
193 }
194
195 ompl::base::Cost Vertex::getValidForwardEdgeCost() const
196 {
197 return edgeCostFromValidForwardParent_;
198 }
199
200 ompl::base::Cost Vertex::getValidReverseEdgeCost() const
201 {
202 return edgeCostFromValidReverseParent_;
203 }
204
205 ompl::base::Cost Vertex::getEdgeCostFromReverseParent() const
206 {
207 return edgeCostFromBackwardParent_;
208 }
209
210 bool Vertex::hasForwardParent() const
211 {
212 return static_cast<bool>(forwardParent_.lock());
213 }
214
215 bool Vertex::hasForwardEdgeParent() const
216 {
217 return static_cast<bool>(forwardEdgeParent_.lock());
218 }
219
220 std::shared_ptr<Vertex> Vertex::getForwardParent() const
221 {
222 return forwardParent_.lock();
223 }
224
225 std::shared_ptr<Vertex> Vertex::getForwardEdgeParent() const
226 {
227 return forwardEdgeParent_.lock();
228 }
229
230 bool Vertex::hasReverseParent() const
231 {
232 return static_cast<bool>(reverseParent_.lock());
233 }
234
235 bool Vertex::hasReverseEdgeParent() const
236 {
237 return static_cast<bool>(reverseEdgeParent_.lock());
238 }
239
240 std::shared_ptr<Vertex> Vertex::getReverseParent() const
241 {
242 return reverseParent_.lock();
243 }
244
245 std::shared_ptr<Vertex> Vertex::getReverseEdgeParent() const
246 {
247 return reverseEdgeParent_.lock();
248 }
249
250 void Vertex::setForwardEdgeCost(const ompl::base::Cost &cost)
251 {
252 edgeCostFromForwardParent_ = cost;
253 }
254
255 void Vertex::setCostToComeFromStart(const ompl::base::Cost &cost)
256 {
257 costToComeFromStart_ = cost;
258 }
259
260 void Vertex::resetMeet()
261 {
262 meetVertex_ = false;
263 }
264 void Vertex::setMeet()
265 {
266 meetVertex_ = true;
267 }
268 bool Vertex::meetVertex()
269 {
270 return meetVertex_;
271 }
272
273 void Vertex::setCostToComeFromGoal(const ompl::base::Cost &cost)
274 {
275 costToComeFromGoal_ = cost;
276 }
277
278 void Vertex::resetCostToComeFromGoal()
279 {
280 costToComeFromGoal_ = objective_->infiniteCost();
281 }
282
283 void Vertex::resetCostToComeFromStart()
284 {
285 costToComeFromStart_ = objective_->infiniteCost();
286 }
287
288 void Vertex::setForwardInvalid()
289 {
290 forwardInvalidChildState_ = true;
291 }
292
293 bool Vertex::forwardInvalid()
294 {
295 return forwardInvalidChildState_;
296 }
297
298 void Vertex::resetForwardInvalid()
299 {
300 forwardInvalidChildState_ = false;
301 }
302
303 void Vertex::setReverseInvalid()
304 {
305 reverseInvalidChildState_ = true;
306 }
307
308 bool Vertex::reverseInvalid()
309 {
310 return reverseInvalidChildState_;
311 }
312
313 void Vertex::resetReverseInvalid()
314 {
315 reverseInvalidChildState_ = false;
316 }
317
318 void Vertex::setCostToGoToGoal(const ompl::base::Cost &cost)
319 {
320 costToGoToGoal_ = cost;
321 }
322
323 void Vertex::setCostToGoToStart(const ompl::base::Cost &cost)
324 {
325 costToGoToStart_ = cost;
326 }
327
328 void Vertex::setNearObstacle()
329 {
330 nearObstacle_ = true;
331 }
332
333 bool Vertex::nearObstacle()
334 {
335 return nearObstacle_;
336 }
337
338 void Vertex::resetNearObstacle()
339 {
340 nearObstacle_ = false;
341 }
342 bool Vertex::isForwardExpanded()
343 {
344 return IsForwardExpanded_;
345 }
346
347 void Vertex::setForwardExpanded()
348 {
349 IsForwardExpanded_ = true;
350 }
351
352 void Vertex::resetForwardExpanded()
353 {
354 IsForwardExpanded_ = false;
355 }
356
357 bool Vertex::isReverseExpanded()
358 {
359 return IsReverseExpanded_;
360 }
361
362 void Vertex::setReverseExpanded()
363 {
364 IsReverseExpanded_ = true;
365 }
366
367 void Vertex::resetReverseExpanded()
368 {
369 IsReverseExpanded_ = false;
370 }
371
372 void Vertex::setLowerCostBoundToStart(const ompl::base::Cost &ToStart)
373 {
374 lowerCostBoundToGoToStart_ = ToStart;
375 }
376
377 void Vertex::setLowerCostBoundToGoal(const ompl::base::Cost &ToGoal)
378 {
379 lowerCostBoundToGoToGoal_ = ToGoal;
380 }
381
382 ompl::base::Cost Vertex::getLowerCostBoundToStart()
383 {
384 return lowerCostBoundToGoToStart_;
385 }
386
387 ompl::base::Cost Vertex::getLowerCostBoundToGoal()
388 {
389 return lowerCostBoundToGoToGoal_;
390 }
391
392 void Vertex::setForwardValidParent(const std::shared_ptr<Vertex> &vertex, const ompl::base::Cost &edgeCost)
393 {
394 // Remember the edge cost.
395 edgeCostFromValidForwardParent_ = edgeCost;
396 // Remember the corresponding parent.
397 forwardEdgeParent_ = std::weak_ptr<Vertex>(vertex);
398 }
399
400 void Vertex::setReverseValidParent(const std::shared_ptr<Vertex> &vertex, const ompl::base::Cost &edgeCost)
401 {
402 // Remember the edge cost.
403 edgeCostFromValidReverseParent_ = edgeCost;
404 // Remember the corresponding parent.
405 reverseEdgeParent_ = std::weak_ptr<Vertex>(vertex);
406 }
407
408 void Vertex::resetForwardParent()
409 {
410 forwardParent_.reset();
411 }
412
413 void Vertex::resetForwardEdgeParent()
414 {
415 forwardEdgeParent_.reset();
416 }
417
418 void Vertex::setForwardVertexParent(const std::shared_ptr<Vertex> &vertex, const ompl::base::Cost &edgeCost)
419 {
420 // If this is a rewiring, remove from my parent's children.
421 if (static_cast<bool>(forwardParent_.lock())) //&&(!static_cast<bool>(forwardEdgeParent_.lock()) ||
422 // forwardParent_.lock()->getId() !=
423 // forwardEdgeParent_.lock()->getId())
424 {
425 forwardParent_.lock()->removeFromForwardChildren(vertexId_);
426 }
427 // Remember the parent.
428 edgeCostFromForwardParent_ = edgeCost;
429 forwardParent_ = std::weak_ptr<Vertex>(vertex);
430 }
431
432 void Vertex::setReverseVertexParent(const std::shared_ptr<Vertex> &vertex, const ompl::base::Cost &edgeCost)
433 {
434 // If this is a rewiring, remove from my parent's children.
435 if (static_cast<bool>(reverseParent_.lock())) //(!static_cast<bool>(reverseEdgeParent_.lock()) ||
436 // reverseParent_.lock()->getId() !=
437 // reverseEdgeParent_.lock()->getId())
438 {
439 reverseParent_.lock()->removeFromReverseChildren(vertexId_);
440 }
441 // Remember the parent.
442 edgeCostFromBackwardParent_ = edgeCost;
443 reverseParent_ = std::weak_ptr<Vertex>(vertex);
444 }
445
446 void Vertex::resetReverseParent()
447 {
448 reverseParent_.reset();
449 }
450
451 void Vertex::resetReverseEdgeParent()
452 {
453 reverseEdgeParent_.reset();
454 }
455
456 void Vertex::addToForwardChildren(const std::shared_ptr<Vertex> &vertex)
457 {
458 forwardChildren_.emplace_back(vertex);
459 }
460
461 void Vertex::removeFromForwardChildren(std::size_t vertexId)
462 {
463 // Find the child.
464 auto it = std::find_if(forwardChildren_.begin(), forwardChildren_.end(),
465 [vertexId](const std::weak_ptr<Vertex> &child)
466 { return vertexId == child.lock()->getId(); });
467
468 // Throw if it is not found.
469 if (it == forwardChildren_.end())
470 {
471 auto msg = "Asked to remove vertex from forward children that is currently not a child."s;
472 throw ompl::Exception(msg);
473 }
474 // Swap and pop.
475
476 std::iter_swap(it, forwardChildren_.rbegin());
477 forwardChildren_.pop_back();
478 }
479
480 void Vertex::addToReverseChildren(const std::shared_ptr<Vertex> &vertex)
481 {
482 reverseChildren_.push_back(vertex);
483 }
484
485 void Vertex::removeFromReverseChildren(std::size_t vertexId)
486 {
487 // Find the child.
488 auto it = std::find_if(reverseChildren_.begin(), reverseChildren_.end(),
489 [vertexId](const std::weak_ptr<Vertex> &child)
490 { return vertexId == child.lock()->getId(); });
491
492 // Throw if it is not found.
493 if (it == reverseChildren_.end())
494 {
495 auto msg = "Asked to remove vertex from reverse children that is currently not a child."s;
496 throw ompl::Exception(msg);
497 }
498
499 // Swap and pop.
500 std::iter_swap(it, reverseChildren_.rbegin());
501 reverseChildren_.pop_back();
502 }
503
504 void Vertex::whitelistAsChild(const std::shared_ptr<Vertex> &vertex) const
505 {
506 whitelistedChildren_.emplace_back(vertex);
507 }
508
509 bool Vertex::isWhitelistedAsChild(const std::shared_ptr<Vertex> &vertex) const
510 {
511 // Check if the vertex is whitelisted by iterating over all whitelisted children.
512 // It this detects an invalid vertex, e.g., a vertex that was once whitelisted but
513 // has been pruned since, remove the vertex from the list of whitelisted children.
514 auto it = whitelistedChildren_.begin();
515 while (it != whitelistedChildren_.end())
516 {
517 // Check if the child is a valid vertex.
518 if (const auto child = it->lock())
519 {
520 // Check if the vertex is whitelisted.
521 if (child->getId() == vertex->getId())
522 {
523 return true;
524 }
525 ++it;
526 }
527 else
528 {
529 it = whitelistedChildren_.erase(it);
530 }
531 }
532 return false;
533 }
534
535 void Vertex::setIncomingCollisionCheckResolution(const std::size_t vertexId, std::size_t numChecks) const
536 {
537 incomingCollisionCheckResolution_[vertexId] = numChecks;
538 }
539
540 std::size_t Vertex::getIncomingCollisionCheckResolution(const std::size_t vertexId) const
541 {
542 if (incomingCollisionCheckResolution_.find(vertexId) == incomingCollisionCheckResolution_.end())
543 {
544 return 0u;
545 }
546 else
547 {
548 return incomingCollisionCheckResolution_[vertexId];
549 }
550 }
551
552 void Vertex::blacklistAsChild(const std::shared_ptr<Vertex> &vertex) const
553 {
554 blacklistedChildren_.emplace_back(vertex);
555 }
556
557 bool Vertex::isBlacklistedAsChild(const std::shared_ptr<Vertex> &vertex) const
558 {
559 auto it = blacklistedChildren_.begin();
560 while (it != blacklistedChildren_.end())
561 {
562 // Check if the child is a valid vertex.
563 if (const auto child = it->lock())
564 {
565 // Check if the vertex is whitelisted.
566 if (child->getId() == vertex->getId())
567 {
568 return true;
569 }
570 ++it;
571 }
572 else
573 {
574 it = blacklistedChildren_.erase(it);
575 }
576 }
577 return false;
578 }
579
580 bool Vertex::hasCachedNeighbors() const
581 {
582 return neighborBatchId_ == batchId_;
583 }
584
585 void Vertex::cacheNeighbors(const std::vector<std::shared_ptr<Vertex>> &neighbors) const
586 {
587 neighbors_.clear();
588 neighbors_.insert(neighbors_.begin(), neighbors.begin(), neighbors.end());
589 neighborBatchId_ = batchId_;
590 }
591
592 const std::vector<std::shared_ptr<Vertex>> Vertex::getNeighbors() const
593 {
594 if (neighborBatchId_ != batchId_)
595 {
596 throw ompl::Exception("Requested neighbors from vertex of outdated approximation.");
597 }
598
599 std::vector<std::shared_ptr<Vertex>> neighbors;
600 for (const auto &neighbor : neighbors_)
601 {
602 assert(neighbor.lock());
603 neighbors.emplace_back(neighbor.lock());
604 }
605
606 return neighbors;
607 }
608
609 std::vector<std::shared_ptr<Vertex>> Vertex::getForwardChildren() const
610 {
611 std::vector<std::shared_ptr<Vertex>> children;
612 for (const auto &child : forwardChildren_)
613 {
614 assert(!child.expired());
615 children.emplace_back(child.lock());
616 }
617 return children;
618 }
619
620 std::vector<std::shared_ptr<Vertex>> Vertex::getReverseChildren() const
621 {
622 std::vector<std::shared_ptr<Vertex>> children;
623 children.reserve(reverseChildren_.size());
624 for (const auto &child : reverseChildren_)
625 {
626 assert(!child.expired());
627 children.emplace_back(child.lock());
628 }
629 return children;
630 }
631
632 void Vertex::setReverseVertexQueuePointer(
633 typename ompl::BinaryHeap<
634 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>>,
635 std::function<bool(const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &,
636 const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &)>>::
637 Element *pointer)
638 {
639 reverseVertexQueuePointerId_ = batchId_;
640 reverseVertexQueuePointer_ = pointer;
641 }
642
643 void Vertex::setForwardVertexQueuePointer(
644 typename ompl::BinaryHeap<
645 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>>,
646 std::function<bool(const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &,
647 const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &)>>::
648 Element *pointer)
649 {
650 forwardVertexQueuePointerId_ = batchId_;
651 forwardVertexQueuePointer_ = pointer;
652 }
653
654 typename ompl::BinaryHeap<
655 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>>,
656 std::function<bool(const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &,
657 const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &)>>::
658 Element *
659 Vertex::getForwardVertexQueuePointer() const
660 {
661 if (batchId_ != forwardVertexQueuePointerId_)
662 {
663 forwardVertexQueuePointer_ = nullptr;
664 }
665 return forwardVertexQueuePointer_;
666 }
667
668 typename ompl::BinaryHeap<
669 std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>>,
670 std::function<bool(const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &,
671 const std::pair<std::array<ompl::base::Cost, 2u>, std::shared_ptr<Vertex>> &)>>::
672 Element *
673 Vertex::getReverseVertexQueuePointer() const
674 {
675 if (batchId_ != reverseVertexQueuePointerId_)
676 {
677 reverseVertexQueuePointer_ = nullptr;
678 }
679 return reverseVertexQueuePointer_;
680 }
681
682 void Vertex::resetForwardVertexQueuePointer()
683 {
684 forwardVertexQueuePointer_ = nullptr;
685 }
686
687 void Vertex::resetReverseVertexQueuePointer()
688 {
689 reverseVertexQueuePointer_ = nullptr;
690 }
691
692 } // namespace blitstar
693
694 } // namespace geometric
695
696} // namespace ompl
This class provides an implementation of an updatable min-heap. Using it is a bit cumbersome,...
Definition BinaryHeap.h:53
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
Definition of a scoped state.
Definition ScopedState.h:57
Definition of an abstract state.
Definition State.h:50
ompl::base::Cost getCostToComeFromGoal() const
Returns the cost to come to this vertex from the goal.
Definition Vertex.cpp:180
This namespace contains code that is specific to planning under geometric constraints.
Message namespace. This contains classes needed to output error messages (or logging) from within the...
Definition Console.h:82
Main namespace. Contains everything in this library.
STL namespace.