Skip to content

Commit 71d61cf

Browse files
committed
Refactor planning algos (#170)
1 parent 17d3551 commit 71d61cf

2 files changed

Lines changed: 679 additions & 0 deletions

File tree

src/bitrl/planning/a_star_search.h

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#ifndef A_STAR_SEARCH_H
2+
#define A_STAR_SEARCH_H
3+
4+
#include "cubeai/base/cubeai_types.h"
5+
6+
//#include "cubeai/data_structs/searchable_priority_queue.h"
7+
//#include "kernel/utilities/map_utilities.h"
8+
9+
#include <utility>
10+
#include <set>
11+
#include <queue>
12+
#include <map>
13+
14+
namespace cubeai{
15+
namespace astar_impl{
16+
17+
18+
19+
///
20+
/// \brief See Scott Meyers Effective STL Item 24
21+
/// for this function. If k isn't in the map
22+
/// efficiently add pair (k,v) otherwise efficiently update
23+
/// to v the value associated with k. Return an interator
24+
/// to the added or modified pair
25+
///
26+
template<typename MapType,
27+
typename KeyArgType,
28+
typename ValueArgType>
29+
typename MapType::iterator
30+
add_or_update_map(MapType& map, const KeyArgType& k, const ValueArgType& v){
31+
32+
//find where k is or should be
33+
typename MapType::iterator lb = map.lower_bound(k);
34+
35+
//if lb points to a pair whose key is equivalent to k
36+
//update the pair's value and return the iterator
37+
if(lb != map.end() &&
38+
!(map.key_comp()(k,lb->first))){
39+
40+
lb->second = v;
41+
return lb;
42+
}
43+
else{ //add pair (k,v) to map and return an iterator
44+
//to the new map element
45+
46+
typedef typename MapType::value_type MVT;
47+
return map.insert(lb,MVT(k,v));
48+
49+
}
50+
}
51+
52+
struct fcost_astar_node_compare
53+
{
54+
template<typename NodeTp>
55+
bool operator()(const NodeTp& n1,const NodeTp& n2)const;
56+
};
57+
58+
template<typename NodeTp>
59+
bool
60+
fcost_astar_node_compare::operator()(const NodeTp& n1,const NodeTp& n2)const{
61+
62+
if(n1.data.f_cost > n2.data.f_cost){
63+
return true;
64+
}
65+
66+
return false;
67+
}
68+
69+
struct id_astar_node_compare
70+
{
71+
template<typename NodeTp>
72+
bool operator()(const NodeTp& n1,const NodeTp& n2)const;
73+
};
74+
75+
template<typename NodeTp>
76+
bool
77+
id_astar_node_compare::operator()(const NodeTp& n1,const NodeTp& n2)const{
78+
79+
if(n1.id > n2.id){
80+
return true;
81+
}
82+
83+
return false;
84+
}
85+
} //astar_impl
86+
87+
///
88+
/// \brief Simple implementation of A* algorithm
89+
/// at the moment the algorithm is only usable with a
90+
/// boost_unidirected_serial_graph graph
91+
///
92+
template<typename GraphTp, typename H>
93+
std::multimap<uint_t, uint_t>
94+
a_star_search(GraphTp& g, typename GraphTp::vertex_type& start, typename GraphTp::vertex_type& end, const H& h){
95+
96+
// for each node hodls where it
97+
// came form
98+
std::multimap<uint_t, uint_t> came_from;
99+
100+
if(start == end){
101+
102+
//we don't have to search for anything
103+
came_from.insert(start.id, start.id);
104+
return came_from;
105+
}
106+
107+
typedef typename H::cost_type cost_t;
108+
typedef typename GraphTp::vertex_type vertex_t;
109+
typedef typename GraphTp::adjacency_iterator adjacency_iterator;
110+
typedef typename GraphTp::vertex_type node_t;
111+
typedef std::priority_queue<node_t, std::vector<node_t>, astar_impl::fcost_astar_node_compare> searchable_priority_queue;
112+
113+
std::set<node_t,astar_impl::id_astar_node_compare> explored;
114+
searchable_priority_queue open;
115+
116+
//the cost of the path so far leading to this
117+
//node is obviously zero at the start node
118+
start.data.g_cost = 0.0;
119+
120+
//calculate the fCost from start node to the goal
121+
//at the moment this can be done only heuristically
122+
//start.data.fcost = h(start.data.position, end.data.position);
123+
start.data.f_cost = h(start, end);
124+
open.push(start);
125+
126+
while(!open.empty()){
127+
128+
//the vertex currently examined
129+
const node_t cv = open.top();
130+
open.pop();
131+
132+
//check if this is the goal
133+
if(cv == end){
134+
break;
135+
}
136+
137+
//current node is not the goal so proceed
138+
//add it to the explored (or else called closed) set
139+
explored.insert(cv);
140+
141+
//get the adjacent neighbors
142+
std::pair<adjacency_iterator,adjacency_iterator> neighbors = g.get_vertex_neighbors(cv);
143+
auto itr = neighbors.first;
144+
145+
// loop over the neighbors
146+
for(; itr != neighbors.second; itr++){
147+
148+
node_t& nv = g.get_vertex(itr);
149+
150+
if(open.contains(nv)){
151+
continue;
152+
}
153+
else{
154+
155+
// we cannot move to the neighbor
156+
// so no reason checking
157+
if(!nv.data.can_move()){
158+
explored.insert(nv);
159+
continue;
160+
}
161+
}
162+
163+
// node id
164+
uint_t nid = nv.id;
165+
166+
//search explored set by id
167+
auto itr = std::find_if(explored.begin(), explored.end(),
168+
[=](const node_t& n){return (n.id == nid);});
169+
170+
//the node has been explored
171+
if(itr != explored.end()){
172+
continue;
173+
}
174+
175+
//this actually the cost of the path from the current node
176+
//to reach its neighbor
177+
cost_t tg_cost = cv.data.g_cost + h(cv, nv);//h(cv.data.position, nv.data.position);
178+
179+
if (tg_cost >= nv.data.g_cost) {
180+
continue; //this is not a better path
181+
}
182+
183+
// This path is the best until now. Record it!
184+
astar_impl::add_or_update_map(came_from,nv.id,cv.id);
185+
186+
//came_from.put(nv.id,cv.id);
187+
nv.data.g_cost = tg_cost;
188+
189+
//acutally calculate f(nn) = g(nn)+h(nn)
190+
nv.data.f_cost = nv.data.g_cost + h(nv, end);//h(nv.data.position, end.data.position);
191+
192+
//if the neighbor not in open set add it
193+
open.push(nv);
194+
195+
}
196+
}
197+
198+
return came_from;
199+
}
200+
201+
template<typename IdTp>
202+
std::vector<IdTp>
203+
reconstruct_a_star_path(const std::multimap<IdTp, IdTp>& map, const IdTp& start){
204+
205+
if(map.empty()){
206+
return std::vector<IdTp>();
207+
}
208+
209+
std::vector<IdTp> path;
210+
path.push_back(start);
211+
212+
auto next_itr = map.find(start);
213+
214+
if(next_itr == map.end()){
215+
216+
//such a key does not exist
217+
throw std::logic_error("Key: "+std::to_string(start)+" does not exist");
218+
}
219+
220+
IdTp next = next_itr->second;
221+
path.push_back(next);
222+
223+
while(next_itr!=map.end()){
224+
225+
next_itr = map.find(next);
226+
if(next_itr != map.end()){
227+
next = next_itr->second;
228+
path.push_back(next);
229+
}
230+
}
231+
232+
//let's reverse the path
233+
std::vector<IdTp> the_path;
234+
the_path.reserve(path.size());
235+
auto itrb = path.rbegin();
236+
auto itre = path.rend();
237+
238+
while(itrb != itre){
239+
the_path.push_back(*itrb++);
240+
}
241+
242+
return the_path;
243+
}
244+
245+
246+
}
247+
248+
#endif // A_STAR_SEARCH_H

0 commit comments

Comments
 (0)