Simulate position in tunnels

This commit is contained in:
vshcherb 2013-10-29 21:13:57 +01:00
parent 37366af643
commit 6c7cd3d3c2
6 changed files with 163 additions and 40 deletions

View file

@ -176,6 +176,20 @@ public class RouteDataObject {
return false;
}
public boolean tunnel(){
int sz = types.length;
for(int i=0; i<sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if(r.getTag().equals("tunnel") && r.getValue().equals("yes")) {
return true;
}
if(r.getTag().equals("layer") && r.getValue().equals("-1")) {
return true;
}
}
return false;
}
public int getOneway() {
int sz = types.length;
for (int i = 0; i < sz; i++) {

View file

@ -35,7 +35,7 @@ public class RouteSegmentResult {
@SuppressWarnings("unchecked")
private void updateCapacity() {
int capacity = Math.abs(endPointIndex - startPointIndex) + 1;
List<RouteSegmentResult>[] old = this.attachedRoutes ;
List<RouteSegmentResult>[] old = this.attachedRoutes;
this.attachedRoutes = new List[capacity];
if(old != null){
System.arraycopy(old, 0, this.attachedRoutes, 0, Math.min(old.length, this.attachedRoutes.length));

View file

@ -405,12 +405,6 @@ public class MapUtils {
}
public static double squareDist31TileMetric(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = convert31YToMeters(y1, y2);
double dx = convert31XToMeters(x1, x2);
return dx * dx + dy * dy;
}
public static double convert31YToMeters(float y1, float y2) {
// translate into meters
return (y1 - y2) * 0.01863d;
@ -453,6 +447,13 @@ public class MapUtils {
// return measuredDist(x1, y1, x2, y2);
}
public static double squareDist31TileMetric(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = convert31YToMeters(y1, y2);
double dx = convert31XToMeters(x1, x2);
return dx * dx + dy * dy;
}
public static double calculateProjection31TileMetric(int xA, int yA, int xB, int yB, int xC, int yC) {
// Scalar multiplication between (AB, AC)
double multiple = MapUtils.convert31XToMeters(xB, xA) * MapUtils.convert31XToMeters(xC, xA) +

View file

@ -15,6 +15,7 @@ import net.osmand.data.LatLon;
import net.osmand.data.QuadPoint;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.router.RouteSegmentResult;
import net.osmand.util.MapUtils;
import android.content.Context;
import android.hardware.GeomagneticField;
@ -43,8 +44,11 @@ public class OsmAndLocationProvider implements SensorEventListener {
}
private static final int INTERVAL_TO_CLEAR_SET_LOCATION = 30 * 1000;
private static final int LOST_LOCATION_MSG_ID = 10;
private static final int LOST_LOCATION_MSG_ID = 53;
private static final int START_SIMULATE_LOCATION_MSG_ID = 54;
private static final int RUN_SIMULATE_LOCATION_MSG_ID = 55;
private static final long LOST_LOCATION_CHECK_DELAY = 18000;
private static final long START_LOCATION_SIMULATION_DELAY = 4000;
private static final float ACCURACY_FOR_GPX_AND_ROUTING = 50;
@ -54,6 +58,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
private long lastTimeGPSLocationFixed = 0;
private boolean gpsSignalLost;
private SimulationProvider simulatePosition = null;
private boolean sensorRegistered = false;
private float[] mGravs = new float[3];
@ -105,19 +110,17 @@ public class OsmAndLocationProvider implements SensorEventListener {
return dx * dx + dy * dy;
}
public class SimulationSegment {
private List<BinaryMapDataObject> simulateRoads = new ArrayList<BinaryMapDataObject>();
private float currentSimulationLength = 0;
public class SimulationProvider {
private int currentRoad;
private int currentSegment;
private double currentProjection;
private QuadPoint currentPoint;
private net.osmand.Location startLocation;
private List<BinaryMapDataObject> roads;
private List<RouteSegmentResult> roads;
public void startSimulation(List<BinaryMapDataObject> roads,
public void startSimulation(List<RouteSegmentResult> roads,
net.osmand.Location currentLocation) {
roads = roads;
this.roads = roads;
startLocation = new net.osmand.Location(currentLocation);
long ms = System.currentTimeMillis();
if(ms - startLocation.getTime() > 5000 ||
@ -129,54 +132,74 @@ public class OsmAndLocationProvider implements SensorEventListener {
int py = MapUtils.get31TileNumberY(currentLocation.getLatitude());
double dist = 1000;
for(int i = 0; i < roads.size(); i++) {
BinaryMapDataObject road = roads.get(i);
for(int j = 1; j < road.getPointsLength(); j++) {
QuadPoint proj = MapUtils.getProjectionPoint31(px, py, road.getPoint31XTile(j-1), road.getPoint31YTile(j-1),
road.getPoint31XTile(j), road.getPoint31YTile(j));
RouteSegmentResult road = roads.get(i);
boolean plus = road.getStartPointIndex() < road.getEndPointIndex();
for(int j = road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) {
RouteDataObject obj = road.getObject();
QuadPoint proj = MapUtils.getProjectionPoint31(px, py, obj.getPoint31XTile(j-1), obj.getPoint31YTile(j-1),
obj.getPoint31XTile(j), obj.getPoint31YTile(j));
double dd = squareDist((int)proj.x, (int)proj.y, px, py);
if (dd < dist) {
dist = dd;
currentRoad = i;
currentSegment = j;
currentProjection = MapUtils.calculateProjection31TileMetric(road.getPoint31XTile(j-1), road.getPoint31YTile(j-1),
road.getPoint31XTile(j), road.getPoint31YTile(j), px, py);
currentPoint = proj;
}
j += plus ? 1 : -1;
}
}
}
private void proceedMeters() {
/*for(int i = 0; i < roads.size(); i++) {
BinaryMapDataObject road = roads.get(i);
for(int j = 1; j < road.getPointsLength(); j++) {
QuadPoint proj = MapUtils.getProjectionPoint31(px, py, road.getPoint31XTile(j-1), road.getPoint31YTile(j-1),
road.getPoint31XTile(j), road.getPoint31YTile(j));
double dd = squareDist((int)proj.x, (int)proj.y, px, py);
if (dd < dist) {
dist = dd;
currentRoad = i;
currentSegment = j;
currentProjection = MapUtils.calculateProjection31TileMetric(road.getPoint31XTile(j-1), road.getPoint31YTile(j-1),
road.getPoint31XTile(j), road.getPoint31YTile(j), px, py);
private float proceedMeters(float meters, net.osmand.Location l) {
for(int i = currentRoad; i < roads.size(); i++) {
RouteSegmentResult road = roads.get(i);
boolean firstRoad = i == currentRoad;
boolean plus = road.getStartPointIndex() < road.getEndPointIndex();
for(int j = firstRoad ? currentSegment : road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) {
RouteDataObject obj = road.getObject();
int st31x = obj.getPoint31XTile(j-1);
int st31y = obj.getPoint31YTile(j-1);
int end31x = obj.getPoint31XTile(j);
int end31y = obj.getPoint31YTile(j);
boolean last = i == roads.size() - 1 && j == road.getEndPointIndex();
boolean first = firstRoad && j == currentSegment;
if(first) {
st31x = (int) currentPoint.x;
st31y = (int) currentPoint.y;
}
double dd = MapUtils.squareRootDist31(st31x, st31y, end31x, end31y);
if(meters > dd && !last){
meters -= dd;
} else {
int prx = (int) (st31x + (end31x - st31x) * (meters / dd));
int pry = (int) (st31y + (end31y - st31y) * (meters / dd));
l.setLongitude(MapUtils.get31LongitudeX(prx));
l.setLatitude(MapUtils.get31LatitudeY(pry));
return (float) Math.max(meters - dd, 0);
}
j += plus ? 1 : -1;
}
}*/
}
return -1;
}
/**
* @return null if it is not available of far from boundaries
*/
public Location getSimulatedLocation() {
public net.osmand.Location getSimulatedLocation() {
if(!isSimulatedDataAvailable()) {
return null;
}
Location loc = new Location("OsmAnd");
net.osmand.Location loc = new net.osmand.Location("OsmAnd");
loc.setSpeed(startLocation.getSpeed());
loc.setAltitude(startLocation.getAltitude());
loc.setTime(System.currentTimeMillis());
float meters = (System.currentTimeMillis() - startLocation.getTime()) / startLocation.getSpeed();
float proc = proceedMeters(meters, loc);
if(proc < 0 || proc >= 100){
return null;
}
return loc;
}
@ -621,7 +644,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
}
private void scheduleCheckIfGpsLost(net.osmand.Location location) {
private void scheduleCheckIfGpsLost(final net.osmand.Location location) {
final RoutingHelper routingHelper = app.getRoutingHelper();
if (location != null) {
final long fixTime = location.getTime();
@ -641,8 +664,47 @@ public class OsmAndLocationProvider implements SensorEventListener {
setLocation(null);
}
}, LOST_LOCATION_CHECK_DELAY);
if (routingHelper.isFollowingMode() && routingHelper.getLeftDistance() > 0 && simulatePosition == null) {
app.runMessageInUIThreadAndCancelPrevious(START_SIMULATE_LOCATION_MSG_ID, new Runnable() {
@Override
public void run() {
net.osmand.Location lastKnown = getLastKnownLocation();
if (lastKnown != null && lastKnown.getTime() > fixTime) {
// false positive case, still strange how we got here with removeMessages
return;
}
List<RouteSegmentResult> tunnel = routingHelper.getUpcomingTunnel(1000);
if(tunnel != null) {
simulatePosition = new SimulationProvider();
simulatePosition.startSimulation(tunnel, location);
simulatePosition();
}
}
}, START_LOCATION_SIMULATION_DELAY);
}
}
}
public void simulatePosition() {
app.runMessageInUIThreadAndCancelPrevious(RUN_SIMULATE_LOCATION_MSG_ID, new Runnable() {
@Override
public void run() {
if(simulatePosition != null){
net.osmand.Location loc = simulatePosition.getSimulatedLocation();
if(loc != null){
setLocation(loc);
simulatePosition();
} else {
simulatePosition = null;
}
}
}
}, 1000);
}
public void setLocationFromService(net.osmand.Location location, boolean continuous) {
// if continuous notify about lost location
if (continuous) {
@ -664,6 +726,9 @@ public class OsmAndLocationProvider implements SensorEventListener {
if(location == null){
updateGPSInfo(null);
}
if(location != null) {
simulatePosition = null;
}
enhanceLocation(location);
scheduleCheckIfGpsLost(location);
final RoutingHelper routingHelper = app.getRoutingHelper();

View file

@ -678,6 +678,45 @@ public class RouteCalculationResult {
return null;
}
public List<RouteSegmentResult> getUpcomingTunnel(float distToStart) {
int cs = currentRoute > 0 ? currentRoute - 1 : 0;
if(cs < segments.size()) {
RouteSegmentResult prev = null;
boolean tunnel = false;
while(cs < segments.size() && distToStart > 0) {
RouteSegmentResult segment = segments.get(cs);
if(segment != prev ) {
if(segment.getObject().tunnel()){
tunnel = true;
break;
} else {
distToStart -= segment.getDistance();
prev = segment;
}
}
cs++;
}
if(tunnel) {
List<RouteSegmentResult> list = new ArrayList<RouteSegmentResult>();
while(cs < segments.size()) {
RouteSegmentResult segment = segments.get(cs);
if(segment != prev ) {
if(segment.getObject().tunnel()) {
list.add(segment);
} else {
break;
}
prev = segment;
}
cs++;
}
return list;
}
}
return null;
}
public float getCurrentMaxSpeed() {
RouteSegmentResult res = getCurrentSegmentResult();
if(res != null) {

View file

@ -669,7 +669,11 @@ public class RoutingHelper {
public RouteSegmentResult getCurrentSegmentResult() {
return route.getCurrentSegmentResult();
}
public List<RouteSegmentResult> getUpcomingTunnel(float distToStart) {
return route.getUpcomingTunnel(distToStart);
}
public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak){
NextDirectionInfo i = route.getNextRouteDirectionInfoAfter(previous, to, toSpeak);
if(i != null) {