OnlineMapQuestMovement.java 7.13 KB
Newer Older
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
/*
 * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.movement.local;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
28

29
30
31
32
33
34
35
36
37
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;

38
import de.tud.kom.p2psim.api.topology.Topology;
39
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
40
41
42
43
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left;
44
import de.tudarmstadt.maki.simonstrator.api.Binder;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

/**
 * This movement strategy uses the data from MapQuest
 * 
 * @author Martin Hellwig
 * @version 1.0, 24.07.2015
 */
public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
	
	private PositionVector worldDimensions;
	
	private static HashMap<Integer, RealWorldMovementPoints> movementPoints = new HashMap<>();
	
	private String movementType; // {Fastest, Shortest, Pedestrian, Bicycle}
	private String mapQuestKey;
	private double latLeft; //Values from -90 to 90; always smaller than latRight
	private double latRight; //Values from -90 to 90
	private double lonLeft; //Values from -180 to 180; Always smaller than lonRight
	private double lonRight; //Values from -180 to 180
	private double maxDistanceNextPoint; //This defines the maximum distance to the next point in line; 
										//if the distance is smaller than the given one, the node will choose the next point in the list
	
	public OnlineMapQuestMovement() {
68
69
		this.worldDimensions = Binder.getComponentOrNull(Topology.class)
				.getWorldDimensions();
70
71
72
73
74
75
		latLeft = GPSCalculation.getLatLower();
		latRight = GPSCalculation.getLatUpper();
		lonLeft = GPSCalculation.getLonLeft();
		lonRight = GPSCalculation.getLonRight();
	}

76
	public Either<PositionVector, Boolean> nextPosition(SimLocationActuator comp,
77
78
79
			PositionVector destination) {
		PositionVector newPosition = null;
		
80
81
		if (destination
				.distanceTo(comp.getRealPosition()) < getMovementSpeed(comp)) {
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
			newPosition = destination.clone();
		} else {
			//if not set already for this node or new destination is different than last one
			PointList pointList;
			if(!movementPoints.containsKey(comp.hashCode()) || destination.distanceTo(movementPoints.get(comp.hashCode()).getDestination()) > 1.0) {
				double[] startPosition = transformOwnWorldWindowToGPS(comp.getRealPosition().getX(), comp.getRealPosition().getY());
				double[] destinationPosition = transformOwnWorldWindowToGPS(destination.getX(), destination.getY());
				
				//Get Json data from page
				String directionsString = "";
				JSONArray allDirections = null;
				InputStream in;
				try {
					String url = "http://www.mapquestapi.com/directions/v2/route?key=" + mapQuestKey + "&outFormat=json&routeType=" + movementType + 
							"&shapeFormat=raw&locale=de_DE&unit=k&from=" + startPosition[0] + "," + startPosition[1] + "&to=" + 
							destinationPosition[0] + "," + destinationPosition[1];
					in = new URL(url).openStream();
					directionsString = IOUtils.toString(in);
					JSONObject directionsData = new JSONObject(directionsString);
					allDirections = directionsData.getJSONObject("route").getJSONArray("legs").getJSONObject(0).getJSONArray("maneuvers");
				} catch (JSONException e) {
					e.printStackTrace();
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				//read in all waypoints
				pointList = new PointList();
				if(allDirections != null) {
					for(int i = 0; i < allDirections.length(); i++) {
						try {
							double lat = allDirections.getJSONObject(i).getJSONObject("startPoint").getDouble("lat");
							double lon = allDirections.getJSONObject(i).getJSONObject("startPoint").getDouble("lng");
							pointList.add(new GHPoint(lat, lon));
						}
						catch (JSONException e) {
							//This bar had no name defined, so there was an error. Not so bad
						}
					}
				}
				movementPoints.put(comp.hashCode(), new RealWorldMovementPoints(comp.getRealPosition(), destination, pointList, 0));
			}
			else {
				pointList = movementPoints.get(comp.hashCode()).getPointList();
			}
			
			int actualIndex = movementPoints.get(comp.hashCode()).getActualIndex();
			int i = 0;
			for(GHPoint3D temp : pointList) {
				if(i==actualIndex) {
					PositionVector nextPoint = transformGPSWindowToOwnWorld(temp.getLat(), temp.getLon());
					newPosition = comp.getRealPosition().moveStep(nextPoint, getMovementSpeed(comp));
					
					if(nextPoint.distanceTo(comp.getRealPosition()) < maxDistanceNextPoint) actualIndex++;
				}
				i++;
			}
			
			movementPoints.put(comp.hashCode(), new RealWorldMovementPoints(movementPoints.get(comp.hashCode()).getStart(), destination, pointList, actualIndex));
		}
		return new Left<PositionVector, Boolean>(newPosition);
	}
	
	/**
	 * Projects the world coordinates in the given gps window to the gps-coordinates
	 * @param x
	 * @param y
	 * @return The projected position in gps-coordinates (lat, long)
	 */
	private double[] transformOwnWorldWindowToGPS(double x, double y) {
		double[] gps_coordinates = new double[2];
		gps_coordinates[0] = latLeft + (latRight - latLeft) * (worldDimensions.getY() - y)/worldDimensions.getY();
		gps_coordinates[1] = lonLeft + (lonRight - lonLeft) * x/worldDimensions.getX();
		return gps_coordinates;
	}
	
	/**
	 * Projects the gps coordinates in the given gps window to the world-coordinates given in world-dimensions
	 * @param lat
	 * @param lon
	 * @return The projected position in world-dimensions
	 */
	private PositionVector transformGPSWindowToOwnWorld(double lat, double lon) {
		double x = worldDimensions.getX() * (lon - lonLeft)/(lonRight - lonLeft);
		double y = worldDimensions.getY() - worldDimensions.getY() * (lat - latLeft)/(latRight - latLeft);
		return new PositionVector(x, y);
	}
	
	public void setMovementType(String movementType) {
		this.movementType = movementType;
	}
	
	public void setMaxDistanceNextPoint(double maxDistanceNextPoint) {
		this.maxDistanceNextPoint = maxDistanceNextPoint;
	}
	
	public void setMapQuestKey(String mapQuestKey) {
		this.mapQuestKey = mapQuestKey;
	}
}