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