package aimax.osm.routing.agent; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import aima.core.agent.Agent; import aima.core.environment.map.AdaptableHeuristicFunction; import aima.core.environment.map.BidirectionalMapProblem; import aima.core.environment.map.MapAgent; import aima.core.environment.map.MapEnvironment; import aima.core.environment.map.MapFunctionFactory; import aima.core.search.framework.Problem; import aima.core.search.framework.Search; import aima.core.search.online.LRTAStarAgent; import aima.core.search.online.OnlineSearchProblem; import aima.core.util.datastructure.Point2D; import aima.gui.applications.search.map.MapAgentFrame; import aima.gui.applications.search.map.SearchFactory; import aima.gui.framework.AgentAppController; import aima.gui.framework.MessageLogger; import aima.gui.framework.SimulationThread; import aimax.osm.data.MapWayAttFilter; import aimax.osm.data.entities.MapNode; /** * Controller for graphical OSM map agent applications. * @author Ruediger Lunde */ public class OsmAgentController extends AgentAppController { protected MapAdapter map; protected MapEnvironment env; /** Search method to be used. */ protected Search search; /** Heuristic function to be used when performing informed search. */ protected AdaptableHeuristicFunction heuristic; protected List<String> markedLocations; protected boolean isPrepared; /** Sleep time between two steps during simulation in msec. */ protected long sleepTime = 0l; public OsmAgentController(MapAdapter map) { this.map = map; markedLocations = new ArrayList<String>(); } @Override public void clear() { map.getOsmMap().clearMarkersAndTracks(); prepare(null); } @Override public void prepare(String changedSelector) { env = new MapEnvironment(map); MapAgentFrame.SelectionState state = frame.getSelection(); map.getOsmMap().getTracks().clear(); switch (state.getIndex(MapAgentFrame.SCENARIO_SEL)) { case 0: map.setMapWayFilter (MapWayAttFilter.createAnyWayFilter()); map.ignoreOneways(true); break; case 1: map.setMapWayFilter (MapWayAttFilter.createCarWayFilter()); map.ignoreOneways(false); break; case 2: map.setMapWayFilter (MapWayAttFilter.createBicycleWayFilter()); map.ignoreOneways(false); break; } heuristic = createHeuristic(state.getIndex(MapAgentFrame.HEURISTIC_SEL)); search = SearchFactory.getInstance().createSearch( state.getIndex(MapAgentFrame.SEARCH_SEL), state.getIndex(MapAgentFrame.SEARCH_MODE_SEL), heuristic); frame.getEnvView().setEnvironment(env); isPrepared = true; } /** * Checks whether the current environment is ready to start * simulation. */ @Override public boolean isPrepared() { return isPrepared && (env.getAgents().isEmpty() || !env.isDone()); } /** * Returns the trivial zero function or a simple heuristic which is * based on straight-line distance computation. */ protected AdaptableHeuristicFunction createHeuristic(int heuIdx) { AdaptableHeuristicFunction ahf = null; switch (heuIdx) { case 0: ahf = new H1(); break; default: ahf = new H2(); } return ahf; } /** * Calls {@link #initAgents(MessageLogger)} if necessary and * then starts simulation until done. */ @Override public void run(MessageLogger logger) { logger.log("<simulation-protocol>"); logger.log("search: " + search.getClass().getName()); logger.log("heuristic: " + heuristic.getClass().getName()); if (env.getAgents().isEmpty()) initAgents(logger); try { while (!env.isDone() && !frame.simulationPaused()) { Thread.sleep(sleepTime); env.step(); } } catch (InterruptedException e) {} logger.log("</simulation-protocol>\n"); } /** * Calls {@link #initAgents(MessageLogger)} if necessary and * then executes one simulation step. */ @Override public void step(MessageLogger logger) { if (env.getAgents().isEmpty()) initAgents(logger); env.step(); } /** Creates new agents and adds them to the current environment. */ protected void initAgents(MessageLogger logger) { List<MapNode> markers = map.getOsmMap().getMarkers(); if (markers.size() < 2) { logger.log("Error: Please set two markers with mouse-left."); return; } String[] locs = new String[markers.size()]; for (int i = 0; i < markers.size(); i++) { MapNode node = markers.get(i); Point2D pt = new Point2D(node.getLon(), node.getLat()); locs[i] = map.getNearestLocation(pt); } heuristic.adaptToGoal(locs[1], map); Agent agent = null; MapAgentFrame.SelectionState state = frame.getSelection(); switch (state.getIndex(MapAgentFrame.AGENT_SEL)) { case 0: agent = new MapAgent(map, env, search, new String[] { locs[1] }); break; case 1: Problem p = new BidirectionalMapProblem(map, null, locs[1]); OnlineSearchProblem osp = new OnlineSearchProblem (p.getActionsFunction(), p.getGoalTest(), p.getStepCostFunction()); agent = new LRTAStarAgent (osp, MapFunctionFactory.getPerceptToStateFunction(), heuristic); break; } env.addAgent(agent, locs[0]); } /** Updates the status of the frame. */ @Override public void update(SimulationThread simulationThread) { if (simulationThread.isCanceled()) { frame.setStatus("Task canceled."); isPrepared = false; } else if (frame.simulationPaused()){ frame.setStatus("Task paused."); } else { StringBuffer statusMsg = new StringBuffer(); statusMsg.append("Task completed"); List<Agent> agents = env.getAgents(); if (agents.size() == 1) { Double travelDistance = env.getAgentTravelDistance( agents.get(0)); if (travelDistance != null) { DecimalFormat f = new DecimalFormat("#0.0"); statusMsg.append("; travel distance: " + f.format(travelDistance) + "km"); } } statusMsg.append("."); frame.setStatus(statusMsg.toString()); } } //////////////////////////////////////////////////////////// // local classes /** * Returns always the heuristic value 0. */ static class H1 extends AdaptableHeuristicFunction { public double h(Object state) { return 0.0; } } /** * A simple heuristic which interprets <code>state</code> and * {@link #goal} as location names and uses the straight-line distance * between them as heuristic value. */ static class H2 extends AdaptableHeuristicFunction { public double h(Object state) { double result = 0.0; Point2D pt1 = map.getPosition((String) state); Point2D pt2 = map.getPosition((String) goal); if (pt1 != null && pt2 != null) result = pt1.distance(pt2); //System.out.println(state + ": " + result); return result; } } }