-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAStar.java
144 lines (122 loc) · 3.81 KB
/
AStar.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
/**
* @author Hieu Dao Trung, Antonia Schmalstieg, Joschka Fischer, August 2011
*/
public class AStar {
/**
* Our own implementation of the A-Star algorithm, for use with our Node
* class and custom heuristic function.
*/
static public List<Node> findPath(Node start, Node goal, Node[] blockedNodes) {
// create all needed maps
Map<Node, Object> closedMap = new HashMap<Node, Object>();
PriorityQueue<FScoreNode> openQueue = new PriorityQueue<FScoreNode>();
Map<Node, Node> predMap = new HashMap<Node, Node>();
Map<Node, Double> gScore = new HashMap<Node, Double>();
Map<Node, Double> hScore = new HashMap<Node, Double>();
Map<Node, Double> fScore = new HashMap<Node, Double>();
// add blocked positions to closedMap to ignore those positions
for (Node node : blockedNodes) {
closedMap.put(node, null);
}
// set scores for start Node
gScore.put(start, 0.0);
hScore.put(start, heuristic(start, goal));
fScore.put(start, hScore.get(start));
// at the beginning, only the start node has to be considered
openQueue.add(new FScoreNode(fScore.get(start), start));
// work through all the nodes in the openQueue, which are sorted by
// their fScore
while (!openQueue.isEmpty()) {
// move node from openQueue to closedMap
Node current = openQueue.remove().node;
closedMap.put(current, null);
// arrived? if yes -> build the path from the predecessor map
if (current.equals(goal)) {
List<Node> path = reconstructPath(predMap, predMap.get(goal));
path.add(goal);
return path;
}
// not done yet -> check out the neighbors that we can reach and did
// not check yet
for (Node neighbor : current.e) {
if (neighbor == null || closedMap.containsKey(neighbor))
continue;
// calculate temporary gScore
double g = 1000.0;
if (gScore.get(neighbor) != null)
g = gScore.get(neighbor);
double tempGScore = g + 1;
// check if its better to go this way
boolean neighborNotInQueue = false;
boolean tempScoreBetter = false;
if (!openQueue.contains(neighbor)) {
neighborNotInQueue = true;
tempScoreBetter = true;
} else if (tempGScore < g) {
tempScoreBetter = true;
} else {
tempScoreBetter = false;
}
if (tempScoreBetter) {
predMap.put(neighbor, current);
gScore.put(neighbor, tempGScore);
hScore.put(neighbor, heuristic(neighbor, goal));
fScore.put(neighbor,
gScore.get(neighbor) + hScore.get(neighbor));
}
if (neighborNotInQueue) {
openQueue
.add(new FScoreNode(fScore.get(neighbor), neighbor));
}
}
}
return null;
}
/**
* Heuristic function for A-Star, using the Tie-Breaker Manhattan Distance <br>
* As tie-breaker the delta y * 0.001 was chosen.
*/
static private double heuristic(Node n, Node m) {
return Math.abs(n.p.x - m.p.x) + Math.abs(n.p.y - m.p.y) * 0.001;
}
/**
* Reconstructs path recursively
*/
static private List<Node> reconstructPath(Map<Node, Node> predMap,
Node current) {
if (predMap.containsKey(current)) {
List<Node> path = reconstructPath(predMap, predMap.get(current));
path.add(current);
return path;
} else {
List<Node> path = new LinkedList<Node>();
path.add(current);
return path;
}
}
}
/**
* Data structure to bundle a double fScore with a Node object to create a
* sorted Queue with Nodes, sorted by a the given temporary fScore value
*/
class FScoreNode implements Comparable<FScoreNode> {
public double fscore;
public Node node;
public FScoreNode(double d, Node n) {
this.fscore = d;
this.node = n;
}
@Override
public int compareTo(FScoreNode o) {
if (fscore < o.fscore)
return -1;
else if (fscore > o.fscore)
return 1;
return 0;
}
}