Bench-MR
A Motion Planning Benchmark for Wheeled Mobile Robots
stl_thetastar.h
Go to the documentation of this file.
1/*
2
3Copyright (c) 2015, Luigi Palmieri, Social Robotics Laboratory
4
5All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE.
27
28*/
29
30#pragma once
31
32// used for text debugging
33#include <assert.h>
34#include <stdio.h>
35#include <iostream>
36
37// stl includes
38#include <algorithm>
39#include <cfloat>
40#include <set>
41#include <vector>
42
43#include <unistd.h>
44
45using namespace std;
46
47#define INF_COST 1000000
48
49// disable warning that debugging information has lines that are truncated
50// occurs in stl headers
51#pragma warning(disable : 4786)
52
53template <class T>
55
56// UserState is the users state space type
57template <class UserState>
59 public: // data
60 enum {
67 };
68
72 // A node represents a possible state in the search
73 // The user provided state type is included inside this type
74
75 public:
76 class Node {
77 public:
78 Node *parent; // used during the search to record the parent of successor
79 // nodes
80 Node *child; // used after the search for the application to view the
81 // search in reverse
82 double yaw;
83 float g; // cost of this node + it's predecessors
84 float h; // heuristic estimate of distance to goal
85 float f; // sum of cumulative cost of predecessors and self and heuristic
86
87 Node() : parent(0), child(0), yaw(0.0f), g(0.0f), h(0.0f), f(0.0f) {}
88
89 UserState m_UserState;
90 };
91
92 // For sorting the heap the STL needs compare function that lets us compare
93 // the f value of two nodes
94
96 public:
97 bool operator()(const Node *x, const Node *y) const {
98 if (x->f > y->f) return true;
99
100 if (x->f < y->f) return false;
101
102 // We break ties among vertices with the same
103 // f-values in favor of larger g-values
104 if (x->f == y->f) {
105 return x->g > y->g;
106 }
107
108 return false;
109 }
110 };
111
112 public: // methods
113 // constructor just initialises private data
115 : m_AllocateNodeCount(0),
117 m_CurrentSolutionNode(nullptr),
118 m_CancelRequest(false) {
119 m_useAstar = false;
120 m_connectGrandParent = false;
121 }
122
123 // constructor just initialises private data
124 ThetaStarSearch(bool euclideanCostChoice)
125 : m_AllocateNodeCount(0),
127 m_CurrentSolutionNode(nullptr),
128 m_CancelRequest(false) {
129 m_euclideanCost = euclideanCostChoice;
130 m_useAstar = false;
131 m_connectGrandParent = false;
132 }
133
134 ThetaStarSearch(int MaxNodes)
135 : m_AllocateNodeCount(0),
137 m_CurrentSolutionNode(nullptr),
138 m_CancelRequest(false) {
139 m_useAstar = false;
140 m_connectGrandParent = false;
141 }
142
143 // set Astar Search
144 virtual void useAstar() { m_useAstar = true; }
145
147
148 // call at any time to cancel the search and free up all the memory
149 virtual void CancelSearch() { m_CancelRequest = true; }
150
151 // Set Start and goal states
152 virtual void SetStartAndGoalStates(UserState &Start, UserState &Goal) {
153 m_CancelRequest = false;
154
155 m_Start = AllocateNode();
156 m_Goal = AllocateNode();
157
158 assert((m_Start != nullptr && m_Goal != nullptr));
159
160 m_Start->m_UserState = Start;
161 m_Goal->m_UserState = Goal;
162
163 m_State = SEARCH_STATE_SEARCHING;
164
165 // Initialise the AStar specific parts of the Start Node
166 // The user only needs fill out the state information
167
168 m_Start->g = 0;
169 m_Start->h = m_Start->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
170 m_Start->f = m_Start->g + m_Start->h;
171 m_Start->parent = m_Start; // fix it.
172
173 // Push the start node on the Open list
174
175 m_OpenList.push_back(m_Start); // heap now unsorted
176
177 // Sort back element into heap
178 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
179
180 // Initialise counter for search steps
181 m_Steps = 0;
182 }
183
184 // Advances search one step
185 virtual unsigned int SearchStep() {
186 // Firstly break if the user has not initialised the search
187 assert((m_State > SEARCH_STATE_NOT_INITIALISED) &&
188 (m_State < SEARCH_STATE_INVALID));
189
190 // Next I want it to be safe to do a searchstep once the search has
191 // succeeded...
192 if ((m_State == SEARCH_STATE_SUCCEEDED) ||
193 (m_State == SEARCH_STATE_FAILED)) {
194 return m_State;
195 }
196
197 // Failure is defined as emptying the open list as there is nothing left to
198 // search...
199 // New: Allow user abort
200 if (m_OpenList.empty() || m_CancelRequest) {
201 FreeAllNodes();
202 m_State = SEARCH_STATE_FAILED;
203 return m_State;
204 }
205
206 // Incremement step count
207 m_Steps++;
208
209 // Pop the best node (the one with the lowest f)
210 Node *n = m_OpenList.front(); // get pointer to the node
211 pop_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
212 m_OpenList.pop_back();
213
214 // Check for the goal, once we pop that we're done
215 if (n->m_UserState.IsGoal(m_Goal->m_UserState)) {
216 // The user is going to use the Goal Node he passed in
217 // so copy the parent pointer of n
218 m_Goal->parent = n->parent;
219 m_Goal->g = n->g;
220
221 // OMPL_DEBUG("Setting Goal orientation..");
222
223 if (!(n->m_UserState.lineofsight(&(n->parent->m_UserState),
224 &((m_Goal)->m_UserState)))) {
225 (m_Goal)->m_UserState.setOrientation(&(n->parent->m_UserState));
226 }
227
228 // OMPL_DEBUG("Setting Goal orientation done");
229 m_Goal->m_UserState.steer = n->m_UserState.steer;
230
231 m_Goal->m_UserState.costs = m_Goal->m_UserState.getLineCost();
232
233 // A special case is that the goal was passed in as the start state
234 // so handle that here
235
236 if (!n->m_UserState.IsSameState(m_Start->m_UserState)) {
237 FreeNode(n);
238
239 // set the child pointers in each node (except Goal which has no child)
240 Node *nodeChild = m_Goal;
241 Node *nodeParent = m_Goal->parent;
242
243 do {
244 nodeParent->child = nodeChild;
245 nodeChild = nodeParent;
246 nodeParent = nodeParent->parent;
247
248#ifdef DEBUG
249 nodeParent->m_UserState.PrintNodeInfo();
250 nodeChild->m_UserState.PrintNodeInfo();
251#endif
252
253 if (nodeParent == nodeChild && nodeChild != m_Start) {
254#ifdef DEBUG
255 usleep(200);
256 nodeParent->m_UserState.PrintNodeInfo();
257 nodeChild->m_UserState.PrintNodeInfo();
258#endif
259 std::exit(EXIT_FAILURE);
260 }
261 } while (nodeChild != m_Start &&
262 nodeChild !=
263 nullptr); // Start is always the first node by definition
264 }
265
266 // delete nodes that aren't needed for the solution
267 FreeUnusedNodes();
268 m_State = SEARCH_STATE_SUCCEEDED;
269
270 return m_State;
271 } else // not goal
272 {
273 typename vector<Node *>::iterator closedlist_result;
274 typename vector<Node *>::iterator openlist_result;
275
276 m_ClosedList.push_back(n);
277
278 // We now need to generate the successors of this node
279 // The user helps us to do this, and we keep the new nodes in
280 // m_Successors ...
281
282 m_Successors.clear(); // empty vector of successor nodes to n
283
284 // User provides this functions and uses AddSuccessor to add each
285 // successor of node 'n' to m_Successors
286
287 bool ret = n->m_UserState.GetSuccessors(
288 this, n->parent ? &n->parent->m_UserState : nullptr);
289
290 // Look for continuation with next best open node
291 while (!ret && !m_OpenList.empty()) {
292 n = m_OpenList.front(); // get pointer to the node
293 if (n == nullptr) break;
294 pop_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
295 m_OpenList.pop_back();
296 ret = n->m_UserState.GetSuccessors(
297 this, n->parent ? &n->parent->m_UserState : nullptr);
298 }
299
300 if (!ret) {
301 typename vector<Node *>::iterator successor;
302
303 // free the nodes that may previously have been added
304 for (successor = m_Successors.begin(); successor != m_Successors.end();
305 successor++) {
306 FreeNode((*successor));
307 }
308
309 m_Successors.clear(); // empty vector of successor nodes to n
310
311 // free up everything else we allocated
312 FreeAllNodes();
313
315 return m_State;
316 }
317
318 // Now handle each successor to the current node ...
319 for (typename vector<Node *>::iterator successor = m_Successors.begin();
320 successor != m_Successors.end(); successor++) {
322 for (closedlist_result = m_ClosedList.begin();
323 closedlist_result != m_ClosedList.end(); closedlist_result++) {
324 if ((*closedlist_result)
325 ->m_UserState.IsSameState((*successor)->m_UserState)) {
326 break;
327 }
328 }
329
330 if (closedlist_result != m_ClosedList.end()) {
331 // we found this state on closed
332 // consider the next successor now
333 continue;
334 }
335
337 for (openlist_result = m_OpenList.begin();
338 openlist_result != m_OpenList.end(); openlist_result++) {
339 if ((*openlist_result)
340 ->m_UserState.IsSameState((*successor)->m_UserState)) {
341 break;
342 }
343 }
344
345 if (openlist_result != m_OpenList.end()) {
346 // we found this state on open
347 } else {
348 // State not in open list
349 // Set its g value to inf
350 (*successor)->g = INF_COST;
351 (*successor)->parent = nullptr;
352 }
353
355 UpdateVertex(n, *successor);
356 else
357 UpdateVertexGrandParent(n, *successor);
358 }
359 }
360
361 return m_State; // Succeeded bool is false at this point.
362 }
363
364 virtual bool UpdateVertex(Node *n, Node *successor) {
365 typename vector<Node *>::iterator closedlist_result;
366 typename vector<Node *>::iterator openlist_result;
367
368 double tcost = 0;
369
370 if (n->parent != nullptr &&
371 n->m_UserState.lineofsight(&(n->parent->m_UserState),
372 &((successor)->m_UserState)) &&
373 !m_useAstar) {
374 if (m_euclideanCost)
375 tcost = n->parent->g +
376 n->parent->m_UserState.GetCost((successor)->m_UserState);
377 else
378 tcost = n->parent->g +
379 n->parent->m_UserState.GetCostTrajFromParent(
380 (n->parent->m_UserState), (successor)->m_UserState);
381 // tcost=n->parent->g+n->parent->m_UserState.GetCostTraj((successor)->m_UserState
382 // );
383
384 if (tcost < (successor)->g) {
385 if (n->parent == n && n->parent != m_Start) {
386#ifdef DEBUG
387 n->parent->m_UserState.PrintNodeInfo();
388 n->m_UserState.PrintNodeInfo();
389#endif
390#ifdef DEBUG
391 (successor)->m_UserState.PrintNodeInfo();
392#endif
393 cout << endl;
394 }
395
396 // Update cost and Parent
397 double h_succ =
398 (successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
399
400 (successor)->parent = n->parent;
401 (successor)->yaw = (successor)->m_UserState.theta;
402 (successor)->g = (float)tcost;
403 (successor)->h = (float)h_succ;
404 (successor)->f = (float)(tcost + h_succ);
405 (successor)->m_UserState.setType(1);
406
407 // check if successor is in open list
408 for (openlist_result = m_OpenList.begin();
409 openlist_result != m_OpenList.end(); openlist_result++) {
410 if ((*openlist_result)
411 ->m_UserState.IsSameState((successor)->m_UserState)) {
412 break;
413 }
414 }
415
416 // if in open list remove it
417 if (openlist_result != m_OpenList.end()) {
418 // we found this state on open
419 FreeNode((*openlist_result));
420 m_OpenList.erase(openlist_result);
421 make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
422 }
423
424 // heap now unsorted
425 m_OpenList.push_back((successor));
426
427 // sort back element into heap
428 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
429 }
430 } else {
431 // A* Case
432 float newg = 0;
433
434 if (m_euclideanCost)
435 newg = n->g + n->m_UserState.GetCost((successor)->m_UserState);
436 else
437 newg = n->g + n->m_UserState.GetCostTraj((successor)->m_UserState);
438
439 if (newg < (successor)->g) {
440 // This node is the best node so far with this particular state
441 // so lets keep it and set up its AStar specific data ...
442 if (n->parent == n && n->parent != m_Start) {
443#ifdef DEBUG
444 n->parent->m_UserState.PrintNodeInfo();
445 n->m_UserState.PrintNodeInfo();
446#endif
447#ifdef DEBUG
448 (successor)->m_UserState.PrintNodeInfo();
449#endif
450 cout << endl;
451 }
452
453 double h_succ =
454 (successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
455 (successor)->parent = n;
456 (successor)->g = newg;
457 (successor)->h = (float)h_succ;
458 (successor)->f = (float)(newg + h_succ);
459
460 (successor)->yaw = (successor)->m_UserState.theta;
461 (successor)->m_UserState.costs = (successor)->m_UserState.getLineCost();
462 (successor)->m_UserState.setType(1);
463
464 for (openlist_result = m_OpenList.begin();
465 openlist_result != m_OpenList.end(); openlist_result++) {
466 if ((*openlist_result)
467 ->m_UserState.IsSameState((successor)->m_UserState)) {
468 break;
469 }
470 }
471
472 if (openlist_result != m_OpenList.end()) {
473 // we found this state on open
474 FreeNode((*openlist_result));
475 m_OpenList.erase(openlist_result);
476 make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
477 }
478
479 // heap now unsorted
480 m_OpenList.push_back((successor));
481
482 // sort back element into heap
483 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
484 }
485 }
486
487 return true;
488 }
489
490 virtual bool UpdateVertexGrandParent(Node *n, Node *successor) {
491 typename vector<Node *>::iterator closedlist_result;
492 typename vector<Node *>::iterator openlist_result;
493
494 double tcost = 0;
495
496 if (n->parent->parent != nullptr &&
497 n->m_UserState.lineofsight(&(n->parent->parent->m_UserState),
498 &((successor)->m_UserState)) &&
499 !m_useAstar) {
500 if (m_euclideanCost)
501 tcost = n->parent->parent->g + n->parent->parent->m_UserState.GetCost(
502 (successor)->m_UserState);
503 else
504 tcost = n->parent->parent->g +
505 n->parent->parent->m_UserState.GetCostTrajFromParent(
506 (n->parent->parent->m_UserState), (successor)->m_UserState);
507
508 if (tcost < (successor)->g) {
509 if (n->parent->parent == n && n->parent->parent != m_Start) {
510#ifdef DEBUG
511 n->parent->parent->m_UserState.PrintNodeInfo();
512#endif
513
514#ifdef DEBUG
515 n->m_UserState.PrintNodeInfo();
516 (successor)->m_UserState.PrintNodeInfo();
517#endif
518 cout << endl;
519 }
520
521 // Update cost and Parent
522 double h_succ =
523 (successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
524
525 (successor)->parent = n->parent->parent;
526 (successor)->yaw = (successor)->m_UserState.theta;
527 (successor)->g = (float)tcost;
528 (successor)->h = (float)h_succ;
529 (successor)->f = (float)(tcost + h_succ);
530 (successor)->m_UserState.setType(1);
531
532 // check if successor is in open list
533 for (openlist_result = m_OpenList.begin();
534 openlist_result != m_OpenList.end(); openlist_result++) {
535 if ((*openlist_result)
536 ->m_UserState.IsSameState((successor)->m_UserState)) {
537 break;
538 }
539 }
540
541 // if in open list remove it
542 if (openlist_result != m_OpenList.end()) {
543 // we found this state on open
544 FreeNode((*openlist_result));
545 m_OpenList.erase(openlist_result);
546 make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
547 }
548
549 // heap now unsorted
550 m_OpenList.push_back((successor));
551
552 // sort back element into heap
553 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
554 }
555 } else if (n->parent != nullptr &&
556 n->m_UserState.lineofsight(&(n->parent->m_UserState),
557 &((successor)->m_UserState)) &&
558 !m_useAstar) {
559 if (m_euclideanCost)
560 tcost = n->parent->g +
561 n->parent->m_UserState.GetCost((successor)->m_UserState);
562 else
563 tcost = n->parent->g +
564 n->parent->m_UserState.GetCostTrajFromParent(
565 (n->parent->m_UserState), (successor)->m_UserState);
566 // tcost=n->parent->g+n->parent->m_UserState.GetCostTraj((successor)->m_UserState
567 // );
568
569 if (tcost < (successor)->g) {
570 if (n->parent == n && n->parent != m_Start) {
571#ifdef DEBUG
572 n->parent->m_UserState.PrintNodeInfo();
573 n->m_UserState.PrintNodeInfo();
574#endif
575#ifdef DEBUG
576 (successor)->m_UserState.PrintNodeInfo();
577#endif
578 cout << endl;
579 }
580
581 // Update cost and Parent
582 double h_succ =
583 (successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
584
585 (successor)->parent = n->parent;
586 (successor)->yaw = (successor)->m_UserState.theta;
587 (successor)->g = (float)tcost;
588 (successor)->h = (float)h_succ;
589 (successor)->f = (float)(tcost + h_succ);
590 (successor)->m_UserState.setType(1);
591
592 // check if successor is in open list
593 for (openlist_result = m_OpenList.begin();
594 openlist_result != m_OpenList.end(); openlist_result++) {
595 if ((*openlist_result)
596 ->m_UserState.IsSameState((successor)->m_UserState)) {
597 break;
598 }
599 }
600
601 // if in open list remove it
602 if (openlist_result != m_OpenList.end()) {
603 // we found this state on open
604 FreeNode((*openlist_result));
605 m_OpenList.erase(openlist_result);
606 make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
607 }
608
609 // heap now unsorted
610 m_OpenList.push_back((successor));
611
612 // sort back element into heap
613 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
614 }
615 } else {
616 // A* Case
617
618 float newg = 0;
619
620 if (m_euclideanCost)
621 newg = n->g + n->m_UserState.GetCost((successor)->m_UserState);
622 else
623 newg = n->g + n->m_UserState.GetCostTraj((successor)->m_UserState);
624
625 if (newg < (successor)->g) {
626 // This node is the best node so far with this particular state
627 // so lets keep it and set up its AStar specific data ...
628 if (n->parent == n && n->parent != m_Start) {
629#ifdef DEBUG
630 n->parent->m_UserState.PrintNodeInfo();
631 n->m_UserState.PrintNodeInfo();
632#endif
633#ifdef DEBUG
634 (successor)->m_UserState.PrintNodeInfo();
635#endif
636 cout << endl;
637 }
638
639 double h_succ =
640 (successor)->m_UserState.GoalDistanceEstimate(m_Goal->m_UserState);
641 (successor)->parent = n;
642 (successor)->g = newg;
643 (successor)->h = (float)h_succ;
644 (successor)->f = (float)(newg + h_succ);
645
646 (successor)->yaw = (successor)->m_UserState.theta;
647 (successor)->m_UserState.costs = (successor)->m_UserState.getLineCost();
648 (successor)->m_UserState.setType(1);
649
650 for (openlist_result = m_OpenList.begin();
651 openlist_result != m_OpenList.end(); openlist_result++) {
652 if ((*openlist_result)
653 ->m_UserState.IsSameState((successor)->m_UserState)) {
654 break;
655 }
656 }
657
658 if (openlist_result != m_OpenList.end()) {
659 // we found this state on open
660 FreeNode((*openlist_result));
661 m_OpenList.erase(openlist_result);
662 make_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
663 }
664
665 // heap now unsorted
666 m_OpenList.push_back((successor));
667
668 // sort back element into heap
669 push_heap(m_OpenList.begin(), m_OpenList.end(), HeapCompare_f());
670 }
671 }
672
673 return true;
674 }
675
676 // User calls this to add a successor to a list of successors
677 // when expanding the search frontier
678 virtual bool AddSuccessor(UserState &State) {
679 Node *node = AllocateNode();
680
681 if (node) {
682 node->m_UserState = State;
683 node->yaw = State.theta;
684 m_Successors.push_back(node);
685
686 return true;
687 }
688
689 return false;
690 }
691
692 // Free the solution nodes
693 // This is done to clean up all used Node memory when you are done with the
694 // search
695 virtual void FreeSolutionNodes() {
696 Node *n = m_Start;
697
698 if (m_Start->child) {
699 do {
700 Node *del = n;
701 n = n->child;
702 FreeNode(del);
703 } while (n != m_Goal);
704
705 FreeNode(n); // Delete the goal
706 } else {
707 // if the start node is the solution we need to just delete the start and
708 // goal nodes
709 FreeNode(m_Start);
710 FreeNode(m_Goal);
711 }
712 }
713
714 // Functions for traversing the solution
715
716 // Get start node
717 virtual UserState *GetSolutionStart() {
718 m_CurrentSolutionNode = m_Start;
719 if (m_Start) {
720 return &m_Start->m_UserState;
721 } else {
722 return nullptr;
723 }
724 }
725
726 // Get next node
727 virtual UserState *GetSolutionNext() {
728 if (m_CurrentSolutionNode) {
729 if (m_CurrentSolutionNode->child) {
730 Node *child = m_CurrentSolutionNode->child;
731 m_CurrentSolutionNode = m_CurrentSolutionNode->child;
732 return &child->m_UserState;
733 }
734 }
735
736 return nullptr;
737 }
738
739 // Get end node
740 virtual UserState *GetSolutionEnd() {
741 m_CurrentSolutionNode = m_Goal;
742 if (m_Goal) {
743 return &m_Goal->m_UserState;
744 } else {
745 return nullptr;
746 }
747 }
748
749 // Step solution iterator backwards
750 virtual UserState *GetSolutionPrev() {
751 if (m_CurrentSolutionNode) {
752 if (m_CurrentSolutionNode->parent) {
753 Node *parent = m_CurrentSolutionNode->parent;
754 m_CurrentSolutionNode = m_CurrentSolutionNode->parent;
755 return &parent->m_UserState;
756 }
757 }
758
759 return nullptr;
760 }
761
762 // Get final cost of solution
763 // Returns FLT_MAX if goal is not defined or there is no solution
764 virtual float GetSolutionCost() {
765 if (m_Goal && m_State == SEARCH_STATE_SUCCEEDED) {
766 return m_Goal->g;
767 } else {
768 return FLT_MAX;
769 }
770 }
771
772 // For educational use and debugging it is useful to be able to view
773 // the open and closed list at each step, here are two functions to allow
774 // that.
775
776 virtual UserState *GetOpenListStart() {
777 float f, g, h;
778 return GetOpenListStart(f, g, h);
779 }
780
781 virtual UserState *GetOpenListStart(float &f, float &g, float &h) {
782 iterDbgOpen = m_OpenList.begin();
783 if (iterDbgOpen != m_OpenList.end()) {
784 f = (*iterDbgOpen)->f;
785 g = (*iterDbgOpen)->g;
786 h = (*iterDbgOpen)->h;
787 return &(*iterDbgOpen)->m_UserState;
788 }
789
790 return nullptr;
791 }
792
793 virtual UserState *GetOpenListNext() {
794 float f, g, h;
795 return GetOpenListNext(f, g, h);
796 }
797
798 virtual UserState *GetOpenListNext(float &f, float &g, float &h) {
799 iterDbgOpen++;
800 if (iterDbgOpen != m_OpenList.end()) {
801 f = (*iterDbgOpen)->f;
802 g = (*iterDbgOpen)->g;
803 h = (*iterDbgOpen)->h;
804 return &(*iterDbgOpen)->m_UserState;
805 }
806
807 return nullptr;
808 }
809
810 Node *GetCurrentBestRawNode() { return m_OpenList.front(); }
811
812 virtual UserState *GetClosedListStart() {
813 float f, g, h;
814 return GetClosedListStart(f, g, h);
815 }
816
817 virtual UserState *GetClosedListStart(float &f, float &g, float &h) {
818 iterDbgClosed = m_ClosedList.begin();
819 if (iterDbgClosed != m_ClosedList.end()) {
820 f = (*iterDbgClosed)->f;
821 g = (*iterDbgClosed)->g;
822 h = (*iterDbgClosed)->h;
823
824 return &(*iterDbgClosed)->m_UserState;
825 }
826
827 return nullptr;
828 }
829
830 virtual UserState *GetClosedListNext() {
831 float f, g, h;
832 return GetClosedListNext(f, g, h);
833 }
834
835 virtual UserState *GetClosedListNext(float &f, float &g, float &h) {
836 iterDbgClosed++;
837 if (iterDbgClosed != m_ClosedList.end()) {
838 f = (*iterDbgClosed)->f;
839 g = (*iterDbgClosed)->g;
840 h = (*iterDbgClosed)->h;
841
842 return &(*iterDbgClosed)->m_UserState;
843 }
844
845 return nullptr;
846 }
847
848 // Get the number of steps
849
850 virtual int GetStepCount() { return m_Steps; }
851
852 virtual void EnsureMemoryFreed() {
853 // if (m_AllocateNodeCount == 0) std::cout << "memory clean" <<
854 // std::endl;
855 }
856
857 private:
858 // delete all nodes
859 void FreeAllNodes() {
860 typename vector<Node *>::iterator iterOpen = m_OpenList.begin();
861
862 while (iterOpen != m_OpenList.end()) {
863 Node *n = (*iterOpen);
864 FreeNode(n);
865
866 iterOpen++;
867 }
868
869 m_OpenList.clear();
870
871 typename vector<Node *>::iterator iterClosed;
872
873 for (iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end();
874 iterClosed++) {
875 Node *n = (*iterClosed);
876 FreeNode(n);
877 }
878
879 m_ClosedList.clear();
880
881 // delete the goal
882
883 FreeNode(m_Goal);
884 }
885
886 void FreeUnusedNodes() {
887 // iterate open list and delete unused nodes
888 typename vector<Node *>::iterator iterOpen = m_OpenList.begin();
889
890 while (iterOpen != m_OpenList.end()) {
891 Node *n = (*iterOpen);
892
893 if (!n->child) {
894 FreeNode(n);
895 }
896
897 iterOpen++;
898 }
899
900 m_OpenList.clear();
901
902 // iterate closed list and delete unused nodes
903 typename vector<Node *>::iterator iterClosed;
904
905 for (iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end();
906 iterClosed++) {
907 Node *n = (*iterClosed);
908
909 if (!n->child) {
910 FreeNode(n);
911 }
912 }
913
914 m_ClosedList.clear();
915 }
916
917 // Node memory management
918 Node *AllocateNode() {
919 m_AllocateNodeCount++;
920 Node *p = new Node;
921 return p;
922 }
923
924 void FreeNode(Node *node) {
925 m_AllocateNodeCount--;
926 delete node;
927 }
928
929 private:
930 // Heap using std:vector
931 vector<Node *> m_OpenList;
932
933 // Closed list is a std::vector.
934 vector<Node *> m_ClosedList;
935
936 // Contains the successors of the current node evaluated during the search
937 vector<Node *> m_Successors;
938
939 // Status of the State
940 unsigned int m_State;
941
942 // Counts steps
943 int m_Steps;
944
945 // Start and goal state pointers
946 Node *m_Start;
947 Node *m_Goal;
948
949 Node *m_CurrentSolutionNode;
950
951 // Two iterators that keep debug info
952 typename vector<Node *>::iterator iterDbgOpen;
953 typename vector<Node *>::iterator iterDbgClosed;
954
955 // debugging : count memory allocation and free's
956 int m_AllocateNodeCount;
957
958 bool m_CancelRequest;
959};
ob::SE2StateSpace::StateType State
Definition: Primitives.h:12
Definition: stl_thetastar.h:95
bool operator()(const Node *x, const Node *y) const
Definition: stl_thetastar.h:97
Definition: stl_thetastar.h:76
float g
Definition: stl_thetastar.h:83
Node * parent
Definition: stl_thetastar.h:78
double yaw
Definition: stl_thetastar.h:82
Node * child
Definition: stl_thetastar.h:80
Node()
Definition: stl_thetastar.h:87
float f
Definition: stl_thetastar.h:85
float h
Definition: stl_thetastar.h:84
UserState m_UserState
Definition: stl_thetastar.h:89
Definition: stl_thetastar.h:58
virtual unsigned int SearchStep()
Definition: stl_thetastar.h:185
virtual void useAstar()
Definition: stl_thetastar.h:144
virtual UserState * GetSolutionNext()
Definition: stl_thetastar.h:727
virtual bool AddSuccessor(UserState &State)
Definition: stl_thetastar.h:678
virtual UserState * GetSolutionStart()
Definition: stl_thetastar.h:717
virtual UserState * GetClosedListStart(float &f, float &g, float &h)
Definition: stl_thetastar.h:817
virtual UserState * GetSolutionEnd()
Definition: stl_thetastar.h:740
virtual UserState * GetOpenListNext(float &f, float &g, float &h)
Definition: stl_thetastar.h:798
bool m_connectGrandParent
Definition: stl_thetastar.h:71
virtual bool UpdateVertexGrandParent(Node *n, Node *successor)
Definition: stl_thetastar.h:490
virtual UserState * GetClosedListNext(float &f, float &g, float &h)
Definition: stl_thetastar.h:835
ThetaStarSearch()
Definition: stl_thetastar.h:114
@ SEARCH_STATE_SEARCHING
Definition: stl_thetastar.h:62
@ SEARCH_STATE_SUCCEEDED
Definition: stl_thetastar.h:63
@ SEARCH_STATE_FAILED
Definition: stl_thetastar.h:64
@ SEARCH_STATE_INVALID
Definition: stl_thetastar.h:66
@ SEARCH_STATE_OUT_OF_MEMORY
Definition: stl_thetastar.h:65
@ SEARCH_STATE_NOT_INITIALISED
Definition: stl_thetastar.h:61
bool m_euclideanCost
Definition: stl_thetastar.h:69
virtual bool UpdateVertex(Node *n, Node *successor)
Definition: stl_thetastar.h:364
virtual UserState * GetOpenListStart()
Definition: stl_thetastar.h:776
virtual void FreeSolutionNodes()
Definition: stl_thetastar.h:695
virtual void CancelSearch()
Definition: stl_thetastar.h:149
virtual void use_connectGrandParent()
Definition: stl_thetastar.h:146
bool m_useAstar
Definition: stl_thetastar.h:70
virtual UserState * GetClosedListStart()
Definition: stl_thetastar.h:812
virtual int GetStepCount()
Definition: stl_thetastar.h:850
virtual float GetSolutionCost()
Definition: stl_thetastar.h:764
virtual UserState * GetClosedListNext()
Definition: stl_thetastar.h:830
Node * GetCurrentBestRawNode()
Definition: stl_thetastar.h:810
virtual UserState * GetSolutionPrev()
Definition: stl_thetastar.h:750
virtual UserState * GetOpenListNext()
Definition: stl_thetastar.h:793
virtual UserState * GetOpenListStart(float &f, float &g, float &h)
Definition: stl_thetastar.h:781
virtual void SetStartAndGoalStates(UserState &Start, UserState &Goal)
Definition: stl_thetastar.h:152
ThetaStarSearch(int MaxNodes)
Definition: stl_thetastar.h:134
virtual void EnsureMemoryFreed()
Definition: stl_thetastar.h:852
ThetaStarSearch(bool euclideanCostChoice)
Definition: stl_thetastar.h:124
Definition: stl_thetastar.h:54
double std(const std::vector< double > &values)
Definition: PathStatistics.hpp:85
#define INF_COST
Definition: stl_thetastar.h:47