Skip to content

Commit 4249656

Browse files
committed
New OSM LTRA* application added. Beta version of new OSM FX framework finished.
1 parent f66d4f9 commit 4249656

File tree

4 files changed

+338
-29
lines changed

4 files changed

+338
-29
lines changed

aimax-osm/src/main/java/aimax/osm/gui/fx/IntegratedAimaOsmFxApp.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import aima.gui.fx.demo.IntegratedAimaFxApp;
44
import aima.gui.fx.framework.IntegratedAppPaneBuilder;
5+
import aimax.osm.gui.fx.applications.OsmLRTAStarAgentApp;
56
import aimax.osm.gui.fx.applications.OsmRouteFindingAgentApp;
67
import aimax.osm.gui.fx.applications.OsmRoutePlannerApp;
78
import javafx.application.Application;
@@ -37,6 +38,7 @@ public static void defineContent(IntegratedAppPaneBuilder builder) {
3738

3839
builder.registerApp(OsmRoutePlannerApp.class);
3940
builder.registerApp(OsmRouteFindingAgentApp.class);
41+
builder.registerApp(OsmLRTAStarAgentApp.class);
4042
}
4143

4244
}
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package aimax.osm.gui.fx.applications;
2+
3+
import aima.core.agent.Action;
4+
import aima.core.agent.Agent;
5+
import aima.core.agent.Environment;
6+
import aima.core.agent.EnvironmentView;
7+
import aima.core.environment.map.*;
8+
import aima.core.search.framework.Node;
9+
import aima.core.search.framework.NodeExpander;
10+
import aima.core.search.framework.SearchForActions;
11+
import aima.core.search.framework.problem.Problem;
12+
import aima.core.search.online.LRTAStarAgent;
13+
import aima.core.search.online.OnlineSearchProblem;
14+
import aima.core.util.CancelableThread;
15+
import aima.core.util.math.geom.shapes.Point2D;
16+
import aima.gui.fx.framework.IntegrableApplication;
17+
import aima.gui.fx.framework.Parameter;
18+
import aima.gui.fx.framework.SimulationPaneBuilder;
19+
import aima.gui.fx.framework.SimulationPaneCtrl;
20+
import aima.gui.fx.views.SimpleEnvironmentViewCtrl;
21+
import aima.gui.util.SearchFactory;
22+
import aimax.osm.data.DataResource;
23+
import aimax.osm.data.EntityClassifier;
24+
import aimax.osm.data.MapWayAttFilter;
25+
import aimax.osm.data.Position;
26+
import aimax.osm.data.entities.EntityViewInfo;
27+
import aimax.osm.data.entities.MapNode;
28+
import aimax.osm.data.entities.MapWay;
29+
import aimax.osm.gui.fx.viewer.MapPaneCtrl;
30+
import aimax.osm.gui.swing.applications.SearchDemoOsmAgentApp;
31+
import aimax.osm.routing.MapAdapter;
32+
import aimax.osm.viewer.DefaultEntityRenderer;
33+
import aimax.osm.viewer.DefaultEntityViewInfo;
34+
import aimax.osm.viewer.MapStyleFactory;
35+
import aimax.osm.viewer.UColor;
36+
import javafx.application.Platform;
37+
import javafx.scene.layout.BorderPane;
38+
import javafx.scene.layout.Pane;
39+
import javafx.scene.layout.StackPane;
40+
41+
import java.text.DecimalFormat;
42+
import java.util.HashSet;
43+
import java.util.List;
44+
45+
/**
46+
* Integrable application which demonstrates how different kinds of search
47+
* algorithms perform an a route finding scenario based on a real OSM map.
48+
* Map locations corresponding to expanded nodes are highlighted in green.
49+
*
50+
* @author Ruediger Lunde
51+
*
52+
*/
53+
public class OsmLRTAStarAgentApp extends IntegrableApplication {
54+
55+
public static void main(String[] args) {
56+
launch(args);
57+
}
58+
59+
public static String PARAM_WAY_SELECTION = "WaySelection";
60+
public static String PARAM_Q_SEARCH_IMPL = "QSearch";
61+
public static String PARAM_HEURISTIC = "Heuristic";
62+
public static String TRACK_NAME = "Track";
63+
64+
private MapPaneCtrl mapPaneCtrl;
65+
private SimulationPaneCtrl simPaneCtrl;
66+
67+
private MapAdapter map;
68+
private MapEnvironment env;
69+
/** Heuristic function to be used when performing informed search. */
70+
protected AdaptableHeuristicFunction heuristic;
71+
72+
/**
73+
* Stores those states (Strings with map node ids), whose corresponding
74+
* search nodes have been expanded during the last search. Quick and dirty
75+
* solution...
76+
*/
77+
static final HashSet<Object> visitedStates = new HashSet<Object>();
78+
79+
80+
@Override
81+
public String getTitle() { return "OSM LRTA* Agent App"; }
82+
83+
/**
84+
* Defines state view, parameters, and call-back functions and calls the
85+
* simulation pane builder to create layout and controller objects.
86+
*/
87+
@Override
88+
public Pane createRootPane() {
89+
BorderPane root = new BorderPane();
90+
91+
Parameter[] params = createParameters();
92+
93+
StackPane mapPane = new StackPane();
94+
mapPaneCtrl = new MapPaneCtrl(mapPane);
95+
mapPaneCtrl.loadMap(DataResource.getULMFileResource());
96+
97+
SimulationPaneBuilder builder = new SimulationPaneBuilder();
98+
builder.defineParameters(params);
99+
builder.defineStateView(mapPane);
100+
builder.defineInitMethod(this::initialize);
101+
builder.defineSimMethod(this::simulate);
102+
simPaneCtrl = builder.getResultFor(root);
103+
simPaneCtrl.setParam(SimulationPaneCtrl.PARAM_SIM_SPEED, 0);
104+
105+
return root;
106+
}
107+
108+
protected Parameter[] createParameters() {
109+
Parameter p1 = new Parameter(PARAM_WAY_SELECTION, "Use any way", "Travel by car", "Travel by bicycle");
110+
Parameter p2 = new Parameter(PARAM_HEURISTIC, "0", "SLD");
111+
p2.setDefaultValueIndex(1);
112+
return new Parameter[] { p1, p2 };
113+
}
114+
115+
/** Is called after each parameter selection change. */
116+
@Override
117+
public void initialize() {
118+
map = new MapAdapter(mapPaneCtrl.getMap());
119+
switch (simPaneCtrl.getParamValueIndex(PARAM_WAY_SELECTION)) {
120+
case 0:
121+
map.setMapWayFilter(MapWayAttFilter.createAnyWayFilter());
122+
map.ignoreOneways(true);
123+
break;
124+
case 1:
125+
map.setMapWayFilter(MapWayAttFilter.createCarWayFilter());
126+
map.ignoreOneways(false);
127+
break;
128+
case 2:
129+
map.setMapWayFilter(MapWayAttFilter.createBicycleWayFilter());
130+
map.ignoreOneways(false);
131+
break;
132+
}
133+
134+
switch (simPaneCtrl.getParamValueIndex(PARAM_HEURISTIC)) {
135+
case 0:
136+
heuristic = new H1();
137+
break;
138+
default:
139+
heuristic = new H2();
140+
}
141+
142+
map.getOsmMap().clearTrack(TRACK_NAME);
143+
}
144+
145+
/** Creates a new agent and adds them to the current environment. */
146+
protected void initAgent(List<MapNode> markers) {
147+
String[] locs = new String[markers.size()];
148+
for (int i = 0; i < markers.size(); i++) {
149+
MapNode node = markers.get(i);
150+
Point2D pt = new Point2D(node.getLon(), node.getLat());
151+
locs[i] = map.getNearestLocation(pt);
152+
}
153+
heuristic.adaptToGoal(locs[1], map);
154+
env = new MapEnvironment(map);
155+
156+
Problem p = new BidirectionalMapProblem(map, null, locs[1]);
157+
OnlineSearchProblem osp = new OnlineSearchProblem(
158+
p.getActionsFunction(), p.getGoalTest(),
159+
p.getStepCostFunction());
160+
Agent agent = new LRTAStarAgent(osp,
161+
MapFunctionFactory.getPerceptToStateFunction(), heuristic);
162+
163+
env.addEnvironmentView(new TrackUpdater());
164+
env.addAgent(agent, locs[0]);
165+
}
166+
167+
168+
/** Starts the experiment. */
169+
public void simulate() {
170+
List<MapNode> markers = map.getOsmMap().getMarkers();
171+
if (markers.size() < 2) {
172+
simPaneCtrl.setStatus("Error: Please set two markers with mouse-left.");
173+
} else {
174+
initAgent(markers);
175+
while (!env.isDone() && !CancelableThread.currIsCanceled()) {
176+
env.step();
177+
simPaneCtrl.waitAfterStep();
178+
}
179+
Double travelDistance = env.getAgentTravelDistance(env.getAgents().get(0));
180+
if (travelDistance != null) {
181+
DecimalFormat f = new DecimalFormat("#0.0");
182+
simPaneCtrl.setStatus("Travel distance: "
183+
+ f.format(travelDistance) + "km");
184+
}
185+
}
186+
}
187+
188+
@Override
189+
public void finalize() {
190+
simPaneCtrl.cancelSimulation();
191+
}
192+
193+
194+
/** Visualizes agent positions. Call from simulation thread. */
195+
private void updateTrack(Agent agent) {
196+
MapAdapter map = (MapAdapter) env.getMap();
197+
MapNode node = map.getWayNode(env.getAgentLocation(agent));
198+
if (node != null) {
199+
Platform.runLater(() -> map.getOsmMap().addToTrack(TRACK_NAME,
200+
new Position(node.getLat(), node.getLon()))
201+
);
202+
}
203+
}
204+
205+
// helper classes...
206+
207+
/**
208+
* Returns always the heuristic value 0.
209+
*/
210+
static class H1 extends AdaptableHeuristicFunction {
211+
212+
public double h(Object state) {
213+
return 0.0;
214+
}
215+
}
216+
217+
/**
218+
* A simple heuristic which interprets <code>state</code> and {@link #goal}
219+
* as location names and uses the straight-line distance between them as
220+
* heuristic value.
221+
*/
222+
static class H2 extends AdaptableHeuristicFunction {
223+
224+
public double h(Object state) {
225+
double result = 0.0;
226+
Point2D pt1 = map.getPosition((String) state);
227+
Point2D pt2 = map.getPosition((String) goal);
228+
if (pt1 != null && pt2 != null)
229+
result = pt1.distance(pt2);
230+
return result;
231+
}
232+
}
233+
234+
class TrackUpdater implements EnvironmentView {
235+
236+
@Override
237+
public void notify(String msg) { }
238+
239+
@Override
240+
public void agentAdded(Agent agent, Environment source) {
241+
updateTrack(agent);
242+
}
243+
244+
/**
245+
* Reacts on environment changes and updates the tracks.
246+
*/
247+
@Override
248+
public void agentActed(Agent agent, Action command, Environment source) {
249+
if (command instanceof MoveToAction) {
250+
updateTrack(agent);
251+
}
252+
}
253+
}
254+
}

0 commit comments

Comments
 (0)