package aimax.osm.gui.swing.viewer.agent; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import aima.core.agent.Agent; import aima.core.environment.map.BidirectionalMapProblem; import aima.core.environment.map.MapEnvironment; import aima.core.environment.map.MapFunctionFactory; import aima.core.environment.map.SimpleMapAgent; import aima.core.search.framework.SearchForActions; import aima.core.search.framework.evalfunc.HeuristicFunction; import aima.core.search.framework.problem.Problem; import aima.core.search.online.LRTAStarAgent; import aima.core.search.online.OnlineSearchProblem; import aima.core.util.math.geom.shapes.Point2D; import aima.gui.swing.applications.agent.map.MapAgentFrame; import aima.gui.swing.framework.AgentAppController; import aima.gui.swing.framework.MessageLogger; import aima.gui.swing.framework.SimulationThread; import aima.gui.util.SearchFactory; import aimax.osm.data.MapWayAttFilter; import aimax.osm.data.entities.MapNode; import aimax.osm.routing.MapAdapter; /** * 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 SearchForActions search; /** Heuristic function to be used when performing informed search. */ protected HeuristicFunction 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; } 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 HeuristicFunction createHeuristic(int heuIdx, String goal) { HeuristicFunction ahf = null; switch (heuIdx) { case 0: ahf = MapFunctionFactory.getZeroHeuristicFunction(); break; default: ahf = MapFunctionFactory.getSLDHeuristicFunction(goal, map); } return ahf; } /** * Calls {@link #initAgents(MessageLogger)} if necessary and then starts * simulation until done. */ @Override public void run(MessageLogger logger) { if (env.getAgents().isEmpty()) initAgents(logger); logger.log("<simulation-protocol>"); logger.log("search: " + search.getClass().getName()); logger.log("heuristic: " + heuristic.getClass().getName()); 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); } MapAgentFrame.SelectionState state = frame.getSelection(); heuristic = createHeuristic(state.getIndex(MapAgentFrame.HEURISTIC_SEL), locs[1]); search = SearchFactory.getInstance().createSearch(state.getIndex(MapAgentFrame.SEARCH_SEL), state.getIndex(MapAgentFrame.Q_SEARCH_IMPL_SEL), heuristic); Agent agent = null; switch (state.getIndex(MapAgentFrame.AGENT_SEL)) { case 0: agent = new SimpleMapAgent(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()); } } }