Update Routing helper
This commit is contained in:
parent
6a0b93ea63
commit
7e59d34941
9 changed files with 119 additions and 1517 deletions
|
@ -130,7 +130,7 @@ public class OsmandApplication extends Application implements ClientContext {
|
|||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
if (routingHelper != null) {
|
||||
routingHelper.getVoiceRouter().onApplicationTerminate(getApplicationContext());
|
||||
routingHelper.getVoiceRouter().onApplicationTerminate(this);
|
||||
}
|
||||
if (bidforfix != null) {
|
||||
bidforfix.onDestroy();
|
||||
|
@ -619,4 +619,14 @@ public class OsmandApplication extends Application implements ClientContext {
|
|||
return sqliteAPI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInUIThread(Runnable run) {
|
||||
uiHandler.post(run);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInUIThread(Runnable run, long delay) {
|
||||
uiHandler.postDelayed(run, delay);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
package net.osmand.plus;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class TargetPointsHelper {
|
||||
|
||||
private List<LatLon> intermediatePoints = new ArrayList<LatLon>();
|
||||
private List<String> intermediatePointNames = new ArrayList<String>();
|
||||
private LatLon pointToNavigate = null;
|
||||
private OsmandSettings settings;
|
||||
private RoutingHelper routingHelper;
|
||||
|
||||
public TargetPointsHelper(OsmandSettings settings, RoutingHelper routingHelper){
|
||||
this.settings = settings;
|
||||
this.routingHelper = routingHelper;
|
||||
readFromSettings(settings);
|
||||
}
|
||||
|
||||
private void readFromSettings(OsmandSettings settings) {
|
||||
pointToNavigate = settings.getPointToNavigate();
|
||||
intermediatePoints.clear();
|
||||
intermediatePointNames.clear();
|
||||
intermediatePoints.addAll(settings.getIntermediatePoints());
|
||||
intermediatePointNames.addAll(settings.getIntermediatePointDescriptions(intermediatePoints.size()));
|
||||
}
|
||||
|
||||
public LatLon getPointToNavigate() {
|
||||
return pointToNavigate;
|
||||
}
|
||||
|
||||
public String getPointNavigateDescription(){
|
||||
return settings.getPointNavigateDescription();
|
||||
}
|
||||
|
||||
public List<String> getIntermediatePointNames() {
|
||||
return intermediatePointNames;
|
||||
}
|
||||
|
||||
public List<LatLon> getIntermediatePoints() {
|
||||
return intermediatePoints;
|
||||
}
|
||||
|
||||
public List<LatLon> getIntermediatePointsWithTarget() {
|
||||
List<LatLon> res = new ArrayList<LatLon>();
|
||||
res.addAll(intermediatePoints);
|
||||
if(pointToNavigate != null) {
|
||||
res.add(pointToNavigate);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<String> getIntermediatePointNamesWithTarget() {
|
||||
List<String> res = new ArrayList<String>();
|
||||
res.addAll(intermediatePointNames);
|
||||
if(pointToNavigate != null) {
|
||||
res.add(getPointNavigateDescription());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public LatLon getFirstIntermediatePoint(){
|
||||
if(intermediatePoints.size() > 0) {
|
||||
return intermediatePoints.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void removeWayPoint(MapActivity map, boolean updateRoute, int index){
|
||||
if(index < 0){
|
||||
settings.clearPointToNavigate();
|
||||
pointToNavigate = null;
|
||||
int sz = intermediatePoints.size();
|
||||
if(sz > 0) {
|
||||
settings.deleteIntermediatePoint(sz- 1);
|
||||
pointToNavigate = intermediatePoints.remove(sz - 1);
|
||||
settings.setPointToNavigate(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(),
|
||||
intermediatePointNames.remove(sz - 1));
|
||||
}
|
||||
} else {
|
||||
settings.deleteIntermediatePoint(index);
|
||||
intermediatePoints.remove(index);
|
||||
intermediatePointNames.remove(index);
|
||||
}
|
||||
updateRouteAndReferesh(map, updateRoute);
|
||||
}
|
||||
|
||||
private void updateRouteAndReferesh(MapActivity map, boolean updateRoute) {
|
||||
if(updateRoute && ( routingHelper.isRouteBeingCalculated() || routingHelper.isRouteCalculated() ||
|
||||
routingHelper.isFollowingMode())) {
|
||||
Location lastKnownLocation = map == null ? routingHelper.getLastProjection() : map.getLastKnownLocation();
|
||||
routingHelper.setFinalAndCurrentLocation(settings.getPointToNavigate(),
|
||||
settings.getIntermediatePoints(), lastKnownLocation, routingHelper.getCurrentGPXRoute());
|
||||
}
|
||||
if(map != null) {
|
||||
map.getMapView().refreshMap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clearPointToNavigate(MapActivity map, boolean updateRoute) {
|
||||
settings.clearPointToNavigate();
|
||||
settings.clearIntermediatePoints();
|
||||
readFromSettings(settings);
|
||||
updateRouteAndReferesh(map, updateRoute);
|
||||
}
|
||||
|
||||
public void reorderAllTargetPoints(MapActivity map, List<LatLon> point,
|
||||
List<String> names, boolean updateRoute){
|
||||
settings.clearPointToNavigate();
|
||||
if (point.size() > 0) {
|
||||
settings.saveIntermediatePoints(point.subList(0, point.size() - 1), names.subList(0, point.size() - 1));
|
||||
LatLon p = point.get(point.size() - 1);
|
||||
String nm = names.get(point.size() - 1);
|
||||
settings.setPointToNavigate(p.getLatitude(), p.getLongitude(), nm);
|
||||
} else {
|
||||
settings.clearIntermediatePoints();
|
||||
}
|
||||
readFromSettings(settings);
|
||||
updateRouteAndReferesh(map, updateRoute);
|
||||
}
|
||||
|
||||
public void navigateToPoint(MapActivity map, LatLon point, boolean updateRoute, int intermediate){
|
||||
if(point != null){
|
||||
if(intermediate < 0) {
|
||||
settings.setPointToNavigate(point.getLatitude(), point.getLongitude(), null);
|
||||
} else {
|
||||
settings.insertIntermediatePoint(point.getLatitude(), point.getLongitude(), null,
|
||||
intermediate, false);
|
||||
}
|
||||
} else {
|
||||
settings.clearPointToNavigate();
|
||||
settings.clearIntermediatePoints();
|
||||
}
|
||||
readFromSettings(settings);
|
||||
updateRouteAndReferesh(map, updateRoute);
|
||||
|
||||
}
|
||||
|
||||
public boolean checkPointToNavigate(Context ctx ){
|
||||
if(pointToNavigate == null){
|
||||
AccessibleToast.makeText(ctx, R.string.mark_final_location_first, Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void navigatePointDialogAndLaunchMap(final Context ctx, final double lat, final double lon, final String name){
|
||||
if(pointToNavigate != null) {
|
||||
Builder builder = new AlertDialog.Builder(ctx);
|
||||
builder.setTitle(R.string.new_destination_point_dialog);
|
||||
builder.setItems(new String[] {
|
||||
ctx.getString(R.string.replace_destination_point),
|
||||
ctx.getString(R.string.add_as_first_destination_point),
|
||||
ctx.getString(R.string.add_as_last_destination_point)
|
||||
}, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if(which == 0) {
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
} else if(which == 2) {
|
||||
int sz = intermediatePoints.size();
|
||||
LatLon pt = pointToNavigate;
|
||||
settings.insertIntermediatePoint(pt.getLatitude(), pt.getLongitude(),
|
||||
settings.getPointNavigateDescription(), sz, true);
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
} else {
|
||||
settings.insertIntermediatePoint(lat, lon, name, 0, true);
|
||||
}
|
||||
readFromSettings(settings);
|
||||
MapActivity.launchMapActivityMoveToTop(ctx);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
} else {
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
readFromSettings(settings);
|
||||
MapActivity.launchMapActivityMoveToTop(ctx);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import net.osmand.plus.BusyIndicator;
|
|||
import net.osmand.plus.FavouritesDbHelper;
|
||||
import net.osmand.plus.GPXUtilities;
|
||||
import net.osmand.plus.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.MapScreen;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
|
@ -35,6 +36,7 @@ import net.osmand.plus.Version;
|
|||
import net.osmand.plus.activities.search.SearchActivity;
|
||||
import net.osmand.plus.routing.RouteProvider.GPXRouteParams;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import net.osmand.plus.routing.RoutingHelper.RouteCalculationProgressCallback;
|
||||
import net.osmand.plus.views.AnimateDraggingMapThread;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
|
@ -89,7 +91,7 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class MapActivity extends AccessibleActivity implements IMapLocationListener, SensorEventListener {
|
||||
public class MapActivity extends AccessibleActivity implements IMapLocationListener, SensorEventListener, MapScreen {
|
||||
|
||||
// stupid error but anyway hero 2.1 : always lost gps signal (temporarily unavailable) for timeout = 2000
|
||||
private static final int GPS_TIMEOUT_REQUEST = 0;
|
||||
|
@ -251,14 +253,27 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
|
|||
Gravity.CENTER_HORIZONTAL | Gravity.TOP);
|
||||
DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||
params.topMargin = (int) (60 * dm.density);
|
||||
ProgressBar pb = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
|
||||
final ProgressBar pb = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
|
||||
pb.setIndeterminate(false);
|
||||
pb.setMax(100);
|
||||
pb.setLayoutParams(params);
|
||||
pb.setVisibility(View.GONE);
|
||||
|
||||
parent.addView(pb);
|
||||
routingHelper.setProgressBar(pb, new Handler());
|
||||
routingHelper.setProgressBar(new RouteCalculationProgressCallback() {
|
||||
|
||||
@Override
|
||||
public void updateProgress(int progress) {
|
||||
pb.setVisibility(View.VISIBLE);
|
||||
pb.setProgress(progress);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
pb.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -1460,4 +1475,10 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
|
|||
OsmandPlugin.onMapActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshMap() {
|
||||
getMapView().refreshMap();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,10 +50,12 @@ import net.osmand.plus.views.OsmandMapTileView;
|
|||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Application;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
||||
import android.content.Intent;
|
||||
|
@ -579,7 +581,7 @@ public class MapActivityActions implements DialogProvider {
|
|||
if (to != null) {
|
||||
targets.navigateToPoint(mapActivity, to, false, -1);
|
||||
}
|
||||
if (!targets.checkPointToNavigate(mapActivity)) {
|
||||
if (!targets.checkPointToNavigate(getMyApplication())) {
|
||||
return;
|
||||
}
|
||||
Location from = fromOrCurrent;
|
||||
|
@ -614,7 +616,7 @@ public class MapActivityActions implements DialogProvider {
|
|||
if(to != null) {
|
||||
targets.navigateToPoint(mapActivity, to, false, -1);
|
||||
}
|
||||
if (!targets.checkPointToNavigate(mapActivity)) {
|
||||
if (!targets.checkPointToNavigate(getMyApplication())) {
|
||||
return;
|
||||
}
|
||||
boolean msg = true;
|
||||
|
@ -875,7 +877,7 @@ public class MapActivityActions implements DialogProvider {
|
|||
getDirections(null, new LatLon(latitude, longitude), true);
|
||||
}
|
||||
} else if (standardId == R.string.context_menu_item_show_route) {
|
||||
if (targets.checkPointToNavigate(mapActivity)) {
|
||||
if (targets.checkPointToNavigate(getMyApplication())) {
|
||||
Location loc = new Location("map");
|
||||
loc.setLatitude(latitude);
|
||||
loc.setLongitude(longitude);
|
||||
|
@ -1250,7 +1252,7 @@ public class MapActivityActions implements DialogProvider {
|
|||
if(onShow != null) {
|
||||
onShow.onClick(v);
|
||||
}
|
||||
app.getTargetPointsHelper().navigatePointDialogAndLaunchMap(activity,
|
||||
navigatePointDialogAndLaunchMap(activity,
|
||||
location.getLatitude(), location.getLongitude(), name);
|
||||
qa.dismiss();
|
||||
}
|
||||
|
@ -1273,4 +1275,42 @@ public class MapActivityActions implements DialogProvider {
|
|||
// qa.addActionItem(directionsTo);
|
||||
}
|
||||
|
||||
|
||||
public static void navigatePointDialogAndLaunchMap(final Activity act, final double lat, final double lon, final String name){
|
||||
OsmandApplication ctx = (OsmandApplication) act.getApplication();
|
||||
final TargetPointsHelper targetPointsHelper = ctx.getTargetPointsHelper();
|
||||
final OsmandSettings settings = ctx.getSettings();
|
||||
if(targetPointsHelper.getPointToNavigate() != null) {
|
||||
Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setTitle(R.string.new_destination_point_dialog);
|
||||
builder.setItems(new String[] {
|
||||
act.getString(R.string.replace_destination_point),
|
||||
act.getString(R.string.add_as_first_destination_point),
|
||||
act.getString(R.string.add_as_last_destination_point)
|
||||
}, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if(which == 0) {
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
} else if(which == 2) {
|
||||
int sz = targetPointsHelper.getIntermediatePoints().size();
|
||||
LatLon pt = targetPointsHelper.getPointToNavigate();
|
||||
settings.insertIntermediatePoint(pt.getLatitude(), pt.getLongitude(),
|
||||
settings.getPointNavigateDescription(), sz, true);
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
} else {
|
||||
settings.insertIntermediatePoint(lat, lon, name, 0, true);
|
||||
}
|
||||
targetPointsHelper.updatePointsFromSettings();
|
||||
MapActivity.launchMapActivityMoveToTop(act);
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
} else {
|
||||
settings.setPointToNavigate(lat, lon, true, name);
|
||||
targetPointsHelper.updatePointsFromSettings();
|
||||
MapActivity.launchMapActivityMoveToTop(act);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -256,12 +256,11 @@ public class NavigatePointActivity extends Activity implements SearchActivityChi
|
|||
double lon = convert(((TextView) findViewById(R.id.LongitudeEdit)).getText().toString());
|
||||
|
||||
if(navigate){
|
||||
|
||||
if(activity != null) {
|
||||
OsmandApplication app = (OsmandApplication) activity.getApplication();
|
||||
app.getTargetPointsHelper().navigatePointDialogAndLaunchMap(activity, lat, lon, getString(R.string.point_on_map, lat, lon));
|
||||
MapActivityActions.navigatePointDialogAndLaunchMap(activity, lat, lon, getString(R.string.point_on_map, lat, lon));
|
||||
} else {
|
||||
OsmandApplication app = (OsmandApplication) getApplication();
|
||||
app.getTargetPointsHelper().navigatePointDialogAndLaunchMap(this, lat, lon, getString(R.string.point_on_map, lat, lon));
|
||||
MapActivityActions.navigatePointDialogAndLaunchMap(this, lat, lon, getString(R.string.point_on_map, lat, lon));
|
||||
}
|
||||
if(dlg != null){
|
||||
dlg.dismiss();
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.osmand.plus.OsmandSettings;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.RegionAddressRepository;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.MapActivityActions;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
@ -236,7 +237,7 @@ public class SearchAddressActivity extends Activity {
|
|||
} else {
|
||||
if (navigateTo) {
|
||||
OsmandApplication app = (OsmandApplication) getApplication();
|
||||
app.getTargetPointsHelper().navigatePointDialogAndLaunchMap(SearchAddressActivity.this, searchPoint.getLatitude(), searchPoint.getLongitude(), historyName);
|
||||
MapActivityActions.navigatePointDialogAndLaunchMap(SearchAddressActivity.this, searchPoint.getLatitude(), searchPoint.getLongitude(), historyName);
|
||||
} else {
|
||||
osmandSettings.setMapLocationToShow(searchPoint.getLatitude(), searchPoint.getLongitude(), zoom, historyName);
|
||||
MapActivity.launchMapActivityMoveToTop(SearchAddressActivity.this);
|
||||
|
|
|
@ -8,9 +8,11 @@ import java.util.List;
|
|||
import net.osmand.NativeLibrary;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.plus.NavigationService;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.PoiFilter;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.TargetPointsHelper;
|
||||
import net.osmand.plus.access.AccessibilityMode;
|
||||
import net.osmand.plus.render.NativeOsmandLibrary;
|
||||
|
||||
|
@ -18,6 +20,7 @@ import org.xmlpull.v1.XmlPullParser;
|
|||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Build;
|
||||
|
@ -128,5 +131,37 @@ public class InternalOsmAndAPIImpl implements InternalOsmAndAPI {
|
|||
return Build.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPointsHelper getTargetPointsHelper() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNavigationServiceStarted() {
|
||||
return app.getNavigationService() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNavigationServiceStartedForNavigation() {
|
||||
return app.getNavigationService() != null && app.getNavigationService().startedForNavigation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startNavigationService(boolean forNavigation) {
|
||||
Intent serviceIntent = new Intent(app, NavigationService.class);
|
||||
if(forNavigation) {
|
||||
serviceIntent.putExtra(NavigationService.NAVIGATION_START_SERVICE_PARAM, true);
|
||||
}
|
||||
app.startService(serviceIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNavigationService() {
|
||||
Intent serviceIntent = new Intent(app, NavigationService.class);
|
||||
app.stopService(serviceIntent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,744 +0,0 @@
|
|||
package net.osmand.plus.routing;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.osm.MapUtils;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.NavigationService;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.OsmandSettings.MetricsConstants;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.TargetPointsHelper;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.routing.RouteProvider.GPXRouteParams;
|
||||
import net.osmand.plus.routing.RouteProvider.RouteService;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.router.RouteCalculationProgress;
|
||||
import net.osmand.router.RouteSegmentResult;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class RoutingHelper {
|
||||
|
||||
private static final org.apache.commons.logging.Log log = LogUtil.getLog(RoutingHelper.class);
|
||||
|
||||
public static interface IRouteInformationListener {
|
||||
|
||||
public void newRouteIsCalculated(boolean newRoute);
|
||||
|
||||
public void routeWasCancelled();
|
||||
}
|
||||
|
||||
private final float POSITION_TOLERANCE = 60;
|
||||
|
||||
private List<IRouteInformationListener> listeners = new ArrayList<IRouteInformationListener>();
|
||||
|
||||
private OsmandApplication app;
|
||||
|
||||
private boolean isFollowingMode = false;
|
||||
|
||||
private GPXRouteParams currentGPXRoute = null;
|
||||
|
||||
private RouteCalculationResult route = new RouteCalculationResult("");
|
||||
|
||||
private LatLon finalLocation;
|
||||
private List<LatLon> intermediatePoints;
|
||||
private Location lastProjection;
|
||||
private Location lastFixedLocation;
|
||||
|
||||
private RouteRecalculationThread currentRunningJob;
|
||||
private long lastTimeEvaluatedRoute = 0;
|
||||
private int evalWaitInterval = 3000;
|
||||
|
||||
private ApplicationMode mode;
|
||||
private OsmandSettings settings;
|
||||
|
||||
private RouteProvider provider = new RouteProvider();
|
||||
private VoiceRouter voiceRouter;
|
||||
|
||||
private Handler uiHandler;
|
||||
private boolean makeUturnWhenPossible = false;
|
||||
private long makeUTwpDetected = 0;
|
||||
//private long wrongMovementDetected = 0;
|
||||
|
||||
private ProgressBar progress;
|
||||
private Handler progressHandler;
|
||||
|
||||
|
||||
|
||||
public boolean makeUturnWhenPossible() {
|
||||
return makeUturnWhenPossible;
|
||||
}
|
||||
|
||||
|
||||
public RoutingHelper(OsmandApplication context, CommandPlayer player){
|
||||
this.app = context;
|
||||
settings = context.getSettings();
|
||||
voiceRouter = new VoiceRouter(this, player);
|
||||
uiHandler = new Handler();
|
||||
}
|
||||
|
||||
public boolean isFollowingMode() {
|
||||
return isFollowingMode;
|
||||
}
|
||||
|
||||
public void setFollowingMode(boolean follow) {
|
||||
isFollowingMode = follow;
|
||||
Intent serviceIntent = new Intent(app, NavigationService.class);
|
||||
if(follow) {
|
||||
if(app.getNavigationService() == null) {
|
||||
serviceIntent.putExtra(NavigationService.NAVIGATION_START_SERVICE_PARAM, true);
|
||||
app.startService(serviceIntent);
|
||||
}
|
||||
} else {
|
||||
if(app.getNavigationService() != null && app.getNavigationService().startedForNavigation()) {
|
||||
app.stopService(serviceIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public synchronized void setFinalAndCurrentLocation(LatLon finalLocation, List<LatLon> intermediatePoints, Location currentLocation, GPXRouteParams gpxRoute){
|
||||
clearCurrentRoute(finalLocation, intermediatePoints);
|
||||
currentGPXRoute = gpxRoute;
|
||||
// to update route
|
||||
setCurrentLocation(currentLocation, false);
|
||||
|
||||
}
|
||||
|
||||
public synchronized void clearCurrentRoute(LatLon newFinalLocation, List<LatLon> newIntermediatePoints) {
|
||||
route = new RouteCalculationResult("");
|
||||
makeUturnWhenPossible = false;
|
||||
evalWaitInterval = 3000;
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (IRouteInformationListener l : listeners) {
|
||||
l.routeWasCancelled();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.finalLocation = newFinalLocation;
|
||||
this.intermediatePoints = newIntermediatePoints;
|
||||
if(currentRunningJob != null) {
|
||||
currentRunningJob.stopCalculation();
|
||||
}
|
||||
if (newFinalLocation == null) {
|
||||
settings.FOLLOW_THE_ROUTE.set(false);
|
||||
settings.FOLLOW_THE_GPX_ROUTE.set(null);
|
||||
// clear last fixed location
|
||||
this.lastProjection = null;
|
||||
setFollowingMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
public GPXRouteParams getCurrentGPXRoute() {
|
||||
return currentGPXRoute;
|
||||
}
|
||||
|
||||
public List<Location> getCurrentRoute() {
|
||||
return currentGPXRoute == null || currentGPXRoute.points.isEmpty() ? route.getImmutableLocations() : Collections
|
||||
.unmodifiableList(currentGPXRoute.points);
|
||||
}
|
||||
|
||||
public void setAppMode(ApplicationMode mode){
|
||||
this.mode = mode;
|
||||
voiceRouter.updateAppMode();
|
||||
}
|
||||
|
||||
public ApplicationMode getAppMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public LatLon getFinalLocation() {
|
||||
return finalLocation;
|
||||
}
|
||||
|
||||
public List<LatLon> getIntermediatePoints() {
|
||||
return intermediatePoints;
|
||||
}
|
||||
|
||||
public boolean isRouteCalculated(){
|
||||
return route.isCalculated();
|
||||
}
|
||||
|
||||
public VoiceRouter getVoiceRouter() {
|
||||
return voiceRouter;
|
||||
}
|
||||
|
||||
public Location getLastProjection(){
|
||||
return lastProjection;
|
||||
}
|
||||
|
||||
public void addListener(IRouteInformationListener l){
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
public boolean removeListener(IRouteInformationListener l){
|
||||
return listeners.remove(l);
|
||||
}
|
||||
|
||||
|
||||
public Location setCurrentLocation(Location currentLocation, boolean returnUpdatedLocation ) {
|
||||
Location locationProjection = currentLocation;
|
||||
if (finalLocation == null || currentLocation == null) {
|
||||
makeUturnWhenPossible = false;
|
||||
return locationProjection;
|
||||
}
|
||||
float posTolerance = POSITION_TOLERANCE;
|
||||
if(currentLocation.hasAccuracy()) {
|
||||
posTolerance = POSITION_TOLERANCE / 2 + currentLocation.getAccuracy();
|
||||
}
|
||||
boolean calculateRoute = false;
|
||||
synchronized (this) {
|
||||
// 0. Route empty or needs to be extended? Then re-calculate route.
|
||||
if(route.isEmpty()) {
|
||||
calculateRoute = true;
|
||||
} else {
|
||||
// 1. Update current route position status according to latest received location
|
||||
boolean finished = updateCurrentRouteStatus(currentLocation, posTolerance);
|
||||
if (finished) {
|
||||
return null;
|
||||
}
|
||||
List<Location> routeNodes = route.getImmutableLocations();
|
||||
int currentRoute = route.currentRoute;
|
||||
|
||||
// 2. Analyze if we need to recalculate route
|
||||
// >100m off current route (sideways)
|
||||
if (currentRoute > 0) {
|
||||
double dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
|
||||
if (dist > 1.7 * posTolerance) {
|
||||
log.info("Recalculate route, because correlation : " + dist); //$NON-NLS-1$
|
||||
calculateRoute = true;
|
||||
}
|
||||
}
|
||||
// 3. Identify wrong movement direction
|
||||
Location next = route.getNextRouteLocation();
|
||||
boolean wrongMovementDirection = checkWrongMovementDirection(currentLocation, next);
|
||||
if (wrongMovementDirection && currentLocation.distanceTo(routeNodes.get(currentRoute)) > 2 * posTolerance) {
|
||||
log.info("Recalculate route, because wrong movement direction: " + currentLocation.distanceTo(routeNodes.get(currentRoute))); //$NON-NLS-1$
|
||||
calculateRoute = true;
|
||||
}
|
||||
// 4. Identify if UTurn is needed
|
||||
boolean uTurnIsNeeded = identifyUTurnIsNeeded(currentLocation, posTolerance);
|
||||
// 5. Update Voice router
|
||||
boolean inRecalc = calculateRoute || isRouteBeingCalculated();
|
||||
if (!inRecalc && !uTurnIsNeeded && !wrongMovementDirection) {
|
||||
voiceRouter.updateStatus(currentLocation);
|
||||
} else if (uTurnIsNeeded) {
|
||||
voiceRouter.makeUTStatus();
|
||||
}
|
||||
|
||||
// calculate projection of current location
|
||||
if (currentRoute > 0) {
|
||||
locationProjection = new Location(currentLocation);
|
||||
Location nextLocation = routeNodes.get(currentRoute);
|
||||
LatLon project = getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
|
||||
|
||||
locationProjection.setLatitude(project.getLatitude());
|
||||
locationProjection.setLongitude(project.getLongitude());
|
||||
// we need to update bearing too
|
||||
float bearingTo = locationProjection.bearingTo(nextLocation);
|
||||
locationProjection.setBearing(bearingTo);
|
||||
}
|
||||
}
|
||||
lastFixedLocation = currentLocation;
|
||||
lastProjection = locationProjection;
|
||||
}
|
||||
|
||||
if (calculateRoute) {
|
||||
recalculateRouteInBackground(currentLocation, finalLocation, intermediatePoints, currentGPXRoute, route.isCalculated() ? route
|
||||
: null);
|
||||
}
|
||||
double projectDist = mode == ApplicationMode.CAR ? posTolerance : posTolerance / 2;
|
||||
if(returnUpdatedLocation && locationProjection != null && currentLocation.distanceTo(locationProjection) < projectDist) {
|
||||
return locationProjection;
|
||||
} else {
|
||||
return currentLocation;
|
||||
}
|
||||
}
|
||||
|
||||
private static double getOrthogonalDistance(Location loc, Location from, Location to) {
|
||||
return MapUtils.getOrthogonalDistance(loc.getLatitude(),
|
||||
loc.getLongitude(), from.getLatitude(), from.getLongitude(),
|
||||
to.getLatitude(), to.getLongitude());
|
||||
}
|
||||
|
||||
private static LatLon getProject(Location loc, Location from, Location to) {
|
||||
return MapUtils.getProjection(loc.getLatitude(),
|
||||
loc.getLongitude(), from.getLatitude(), from.getLongitude(),
|
||||
to.getLatitude(), to.getLongitude());
|
||||
}
|
||||
|
||||
private static int lookAheadFindMinOrthogonalDistance(Location currentLocation, List<Location> routeNodes, int currentRoute, int iterations) {
|
||||
double newDist;
|
||||
double dist = Double.POSITIVE_INFINITY;
|
||||
int index = currentRoute;
|
||||
while (iterations > 0 && currentRoute + 1 < routeNodes.size()) {
|
||||
newDist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute), routeNodes.get(currentRoute + 1));
|
||||
if (newDist < dist) {
|
||||
index = currentRoute;
|
||||
dist = newDist;
|
||||
}
|
||||
currentRoute++;
|
||||
iterations--;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private boolean updateCurrentRouteStatus(Location currentLocation, float posTolerance) {
|
||||
List<Location> routeNodes = route.getImmutableLocations();
|
||||
int currentRoute = route.currentRoute;
|
||||
// 1. Try to proceed to next point using orthogonal distance (finding minimum orthogonal dist)
|
||||
while (currentRoute + 1 < routeNodes.size()) {
|
||||
double dist = currentLocation.distanceTo(routeNodes.get(currentRoute));
|
||||
if(currentRoute > 0) {
|
||||
dist = getOrthogonalDistance(currentLocation, routeNodes.get(currentRoute - 1),
|
||||
routeNodes.get(currentRoute));
|
||||
}
|
||||
boolean processed = false;
|
||||
// if we are still too far try to proceed many points
|
||||
// if not then look ahead only 3 in order to catch sharp turns
|
||||
boolean longDistance = dist >= 250;
|
||||
int newCurrentRoute = lookAheadFindMinOrthogonalDistance(currentLocation, routeNodes, currentRoute, longDistance ? 15 : 8);
|
||||
double newDist = getOrthogonalDistance(currentLocation, routeNodes.get(newCurrentRoute),
|
||||
routeNodes.get(newCurrentRoute + 1));
|
||||
if(longDistance) {
|
||||
if(newDist < dist) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processed by distance : (new) " + newDist + " (old) " + dist); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
} else if (newDist < dist || newDist < 10) {
|
||||
// newDist < 10 (avoid distance 0 till next turn)
|
||||
if (dist > posTolerance) {
|
||||
processed = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processed by distance : " + newDist + " " + dist); //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
} else {
|
||||
// case if you are getting close to the next point after turn
|
||||
// but you have not yet turned (could be checked bearing)
|
||||
if (currentLocation.hasBearing() || lastFixedLocation != null) {
|
||||
float bearingToRoute = currentLocation.bearingTo(routeNodes.get(currentRoute));
|
||||
float bearingRouteNext = routeNodes.get(newCurrentRoute).bearingTo(routeNodes.get(newCurrentRoute + 1));
|
||||
float bearingMotion = currentLocation.hasBearing() ? currentLocation.getBearing() : lastFixedLocation
|
||||
.bearingTo(currentLocation);
|
||||
double diff = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingToRoute));
|
||||
double diffToNext = Math.abs(MapUtils.degreesDiff(bearingMotion, bearingRouteNext));
|
||||
if (diff > diffToNext) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processed point bearing deltas : " + diff + " " + diffToNext);
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (processed) {
|
||||
// that node already passed
|
||||
route.updateCurrentRoute(newCurrentRoute + 1);
|
||||
currentRoute = newCurrentRoute + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. check if intermediate found
|
||||
if(route.getIntermediatePointsToPass() > 0 && route.getDistanceToNextIntermediate(lastFixedLocation) < POSITION_TOLERANCE * 2) {
|
||||
showMessage(app.getString(R.string.arrived_at_intermediate_point));
|
||||
voiceRouter.arrivedIntermediatePoint();
|
||||
route.passIntermediatePoint();
|
||||
TargetPointsHelper targets = app.getTargetPointsHelper();
|
||||
int toDel = targets.getIntermediatePoints().size() - route.getIntermediatePointsToPass();
|
||||
while(toDel > 0) {
|
||||
targets.removeWayPoint(null, false, 0);
|
||||
toDel--;
|
||||
}
|
||||
while(intermediatePoints != null && route.getIntermediatePointsToPass() < intermediatePoints.size()) {
|
||||
intermediatePoints.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. check if destination found
|
||||
Location lastPoint = routeNodes.get(routeNodes.size() - 1);
|
||||
if (currentRoute > routeNodes.size() - 3 && currentLocation.distanceTo(lastPoint) < POSITION_TOLERANCE * 1.5) {
|
||||
showMessage(app.getString(R.string.arrived_at_destination));
|
||||
voiceRouter.arrivedDestinationPoint();
|
||||
clearCurrentRoute(null, null);
|
||||
TargetPointsHelper targets = app.getTargetPointsHelper();
|
||||
targets.clearPointToNavigate(null, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean identifyUTurnIsNeeded(Location currentLocation, float posTolerance) {
|
||||
if (finalLocation == null || currentLocation == null || !route.isCalculated()) {
|
||||
this.makeUturnWhenPossible = false;
|
||||
return makeUturnWhenPossible;
|
||||
}
|
||||
boolean makeUturnWhenPossible = false;
|
||||
if (currentLocation.hasBearing()) {
|
||||
float bearingMotion = currentLocation.getBearing() ;
|
||||
Location nextRoutePosition = route.getNextRouteLocation();
|
||||
float bearingToRoute = currentLocation.bearingTo(nextRoutePosition);
|
||||
double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute);
|
||||
// 7. Check if you left the route and an unscheduled U-turn would bring you back (also Issue 863)
|
||||
// This prompt is an interim advice and does only sound if a new route in forward direction could not be found in x seconds
|
||||
if (Math.abs(diff) > 135f) {
|
||||
float d = currentLocation.distanceTo(nextRoutePosition);
|
||||
// 60m tolerance to allow for GPS inaccuracy
|
||||
if (d > posTolerance) {
|
||||
// require x sec continuous since first detection
|
||||
if (makeUTwpDetected == 0) {
|
||||
makeUTwpDetected = System.currentTimeMillis();
|
||||
} else if ((System.currentTimeMillis() - makeUTwpDetected > 10000)) {
|
||||
makeUturnWhenPossible = true;
|
||||
//log.info("bearingMotion is opposite to bearingRoute"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
} else {
|
||||
makeUTwpDetected = 0;
|
||||
}
|
||||
}
|
||||
this.makeUturnWhenPossible = makeUturnWhenPossible;
|
||||
return makeUturnWhenPossible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrong movement direction is considered when between
|
||||
* current location bearing (determines by 2 last fixed position or provided)
|
||||
* and bearing from currentLocation to next (current) point
|
||||
* the difference is more than 60 degrees
|
||||
*/
|
||||
public boolean checkWrongMovementDirection(Location currentLocation, Location nextRouteLocation) {
|
||||
// measuring without bearing could be really error prone (with last fixed location)
|
||||
// this code has an effect on route recalculation which should be detected without mistakes
|
||||
if (currentLocation.hasBearing() && nextRouteLocation != null) {
|
||||
float bearingMotion = currentLocation.getBearing();
|
||||
float bearingToRoute = currentLocation.bearingTo(nextRouteLocation);
|
||||
double diff = MapUtils.degreesDiff(bearingMotion, bearingToRoute);
|
||||
if (Math.abs(diff) > 60f) {
|
||||
// require delay interval since first detection, to avoid false positive
|
||||
//but leave out for now, as late detection is worse than false positive (it may reset voice router then cause bogus turn and u-turn prompting)
|
||||
//if (wrongMovementDetected == 0) {
|
||||
// wrongMovementDetected = System.currentTimeMillis();
|
||||
//} else if ((System.currentTimeMillis() - wrongMovementDetected > 500)) {
|
||||
return true;
|
||||
//}
|
||||
} else {
|
||||
//wrongMovementDetected = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//wrongMovementDetected = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized void setNewRoute(RouteCalculationResult res, Location start){
|
||||
final boolean newRoute = !this.route.isCalculated();
|
||||
route = res;
|
||||
if (isFollowingMode) {
|
||||
if(lastFixedLocation != null) {
|
||||
start = lastFixedLocation;
|
||||
}
|
||||
// try remove false route-recalculated prompts by checking direction to second route node
|
||||
boolean wrongMovementDirection = false;
|
||||
List<Location> routeNodes = res.getImmutableLocations();
|
||||
if (routeNodes != null && !routeNodes.isEmpty()) {
|
||||
int newCurrentRoute = lookAheadFindMinOrthogonalDistance(start, routeNodes, res.currentRoute, 15);
|
||||
if (newCurrentRoute + 1 < routeNodes.size()) {
|
||||
// This check is valid for Online/GPX services (offline routing is aware of route direction)
|
||||
wrongMovementDirection = checkWrongMovementDirection(start, routeNodes.get(newCurrentRoute + 1));
|
||||
// set/reset evalWaitInterval only if new route is in forward direction
|
||||
if (!wrongMovementDirection) {
|
||||
evalWaitInterval = 3000;
|
||||
} else {
|
||||
evalWaitInterval = evalWaitInterval * 3 / 2;
|
||||
evalWaitInterval = Math.min(evalWaitInterval, 120000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// trigger voice prompt only if new route is in forward direction
|
||||
// If route is in wrong direction after one more setLocation it will be recalculated
|
||||
if (!wrongMovementDirection || newRoute) {
|
||||
voiceRouter.newRouteIsCalculated(newRoute);
|
||||
}
|
||||
}
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (IRouteInformationListener l : listeners) {
|
||||
l.newRouteIsCalculated(newRoute);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public synchronized int getLeftDistance(){
|
||||
return route.getDistanceToFinish(lastFixedLocation);
|
||||
}
|
||||
|
||||
public synchronized int getLeftDistanceNextIntermediate() {
|
||||
return route.getDistanceToNextIntermediate(lastFixedLocation);
|
||||
}
|
||||
|
||||
public synchronized int getLeftTime() {
|
||||
return route.getLeftTime(lastFixedLocation);
|
||||
}
|
||||
|
||||
public String getGeneralRouteInformation(){
|
||||
int dist = getLeftDistance();
|
||||
int hours = getLeftTime() / (60 * 60);
|
||||
int minutes = (getLeftTime() / 60) % 60;
|
||||
return app.getString(R.string.route_general_information, OsmAndFormatter.getFormattedDistance(dist, app),
|
||||
hours, minutes);
|
||||
}
|
||||
|
||||
public Location getLocationFromRouteDirection(RouteDirectionInfo i){
|
||||
return route.getLocationFromRouteDirection(i);
|
||||
}
|
||||
|
||||
public synchronized NextDirectionInfo getNextRouteDirectionInfo(NextDirectionInfo info, boolean toSpeak){
|
||||
NextDirectionInfo i = route.getNextRouteDirectionInfo(info, lastProjection, toSpeak);
|
||||
if(i != null) {
|
||||
i.imminent = voiceRouter.calculateImminent(i.distanceTo, lastProjection);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public synchronized float getCurrentMaxSpeed() {
|
||||
return route.getCurrentMaxSpeed();
|
||||
}
|
||||
|
||||
public synchronized AlarmInfo getMostImportantAlarm(MetricsConstants mc, boolean showCameras){
|
||||
float mxspeed = route.getCurrentMaxSpeed();
|
||||
AlarmInfo speedAlarm = null;
|
||||
if(mxspeed != 0 && lastProjection != null && lastProjection.hasSpeed()) {
|
||||
float delta = 5f/3.6f;
|
||||
if(lastProjection.getSpeed() > mxspeed + delta) {
|
||||
int speed;
|
||||
if(mc == MetricsConstants.KILOMETERS_AND_METERS) {
|
||||
speed = Math.round(mxspeed * 3.6f);
|
||||
} else {
|
||||
speed = Math.round(mxspeed * 3.6f / 1.6f);
|
||||
}
|
||||
speedAlarm = AlarmInfo.createSpeedLimit(speed);
|
||||
}
|
||||
}
|
||||
return route.getMostImportantAlarm(lastProjection, speedAlarm, showCameras);
|
||||
}
|
||||
|
||||
public String formatStreetName(String name, String ref) {
|
||||
if(name != null && name.length() > 0){
|
||||
if(ref != null && ref.length() > 0) {
|
||||
name = ref + " " + name;
|
||||
}
|
||||
return name;
|
||||
} else {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized String getCurrentName(){
|
||||
NextDirectionInfo n = getNextRouteDirectionInfo(new NextDirectionInfo(), false);
|
||||
if((n.imminent == 0 || n.imminent == 1) && (n.directionInfo != null)) {
|
||||
String nm = n.directionInfo.getStreetName();
|
||||
String rf = n.directionInfo.getRef();
|
||||
return formatStreetName(nm, rf);
|
||||
}
|
||||
RouteSegmentResult rs = route.getCurrentSegmentResult();
|
||||
if(rs != null) {
|
||||
String nm = rs.getObject().getName();
|
||||
String rf = rs.getObject().getRef();
|
||||
return formatStreetName(nm, rf);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized NextDirectionInfo getNextRouteDirectionInfoAfter(NextDirectionInfo previous, NextDirectionInfo to, boolean toSpeak){
|
||||
NextDirectionInfo i = route.getNextRouteDirectionInfoAfter(previous, to, toSpeak);
|
||||
if(i != null) {
|
||||
i.imminent = voiceRouter.calculateImminent(i.distanceTo, null);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public List<RouteDirectionInfo> getRouteDirections(){
|
||||
return route.getRouteDirections();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class RouteRecalculationThread extends Thread {
|
||||
|
||||
private final RouteCalculationParams params;
|
||||
|
||||
public RouteRecalculationThread(String name, RouteCalculationParams params) {
|
||||
super(name);
|
||||
this.params = params;
|
||||
if(params.calculationProgress == null) {
|
||||
params.calculationProgress = new RouteCalculationProgress();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopCalculation(){
|
||||
params.calculationProgress.isCancelled = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
RouteCalculationResult res = provider.calculateRouteImpl(params);
|
||||
if (params.calculationProgress.isCancelled) {
|
||||
currentRunningJob = null;
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (RoutingHelper.this) {
|
||||
if (res.isCalculated()) {
|
||||
setNewRoute(res, params.start);
|
||||
} else {
|
||||
evalWaitInterval = evalWaitInterval * 3 / 2;
|
||||
evalWaitInterval = Math.min(evalWaitInterval, 120000);
|
||||
}
|
||||
currentRunningJob = null;
|
||||
}
|
||||
|
||||
if (res.isCalculated()) {
|
||||
showMessage(app.getString(R.string.new_route_calculated_dist)
|
||||
+ ": " + OsmAndFormatter.getFormattedDistance(res.getWholeDistance(), app)); //$NON-NLS-1$
|
||||
} else if (params.type != RouteService.OSMAND && !settings.isInternetConnectionAvailable()) {
|
||||
showMessage(app.getString(R.string.error_calculating_route)
|
||||
+ ":\n" + app.getString(R.string.internet_connection_required_for_online_route), Toast.LENGTH_LONG); //$NON-NLS-1$
|
||||
} else {
|
||||
if (res.getErrorMessage() != null) {
|
||||
showMessage(app.getString(R.string.error_calculating_route) + ":\n" + res.getErrorMessage(), Toast.LENGTH_LONG); //$NON-NLS-1$
|
||||
} else {
|
||||
showMessage(app.getString(R.string.empty_route_calculated), Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
lastTimeEvaluatedRoute = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void recalculateRouteInBackground(final Location start, final LatLon end, final List<LatLon> intermediates, final GPXRouteParams gpxRoute, final RouteCalculationResult previousRoute){
|
||||
if (start == null || end == null) {
|
||||
return;
|
||||
}
|
||||
if(currentRunningJob == null){
|
||||
// do not evaluate very often
|
||||
if (System.currentTimeMillis() - lastTimeEvaluatedRoute > evalWaitInterval) {
|
||||
RouteCalculationParams params = new RouteCalculationParams();
|
||||
params.start = start;
|
||||
params.end = end;
|
||||
params.intermediates = intermediates;
|
||||
params.gpxRoute = gpxRoute;
|
||||
params.previousToRecalculate = previousRoute;
|
||||
params.leftSide = settings.LEFT_SIDE_NAVIGATION.get();
|
||||
params.optimal = settings.OPTIMAL_ROUTE_MODE.getModeValue(mode);
|
||||
params.fast = settings.FAST_ROUTE_MODE.getModeValue(mode);
|
||||
params.type = settings.ROUTER_SERVICE.getModeValue(mode);
|
||||
params.mode = mode;
|
||||
params.ctx = app;
|
||||
if(previousRoute == null && params.type == RouteService.OSMAND) {
|
||||
params.calculationProgress = new RouteCalculationProgress();
|
||||
updateProgress(params.calculationProgress);
|
||||
}
|
||||
synchronized (this) {
|
||||
currentRunningJob = new RouteRecalculationThread("Calculating route", params); //$NON-NLS-1$
|
||||
currentRunningJob.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateProgress(final RouteCalculationProgress calculationProgress) {
|
||||
if(progress != null) {
|
||||
progressHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isRouteBeingCalculated()) {
|
||||
progress.setVisibility(View.VISIBLE);
|
||||
float p = calculationProgress.distanceFromBegin + calculationProgress.distanceFromEnd;
|
||||
float all = calculationProgress.totalEstimatedDistance * 1.5f;
|
||||
if (all > 0) {
|
||||
int t = (int) Math.min(p * p / (all * all) * 100f, 99);
|
||||
progress.setProgress(t);
|
||||
}
|
||||
updateProgress(calculationProgress);
|
||||
} else {
|
||||
progress.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isRouteBeingCalculated(){
|
||||
return currentRunningJob != null;
|
||||
}
|
||||
|
||||
private void showMessage(final String msg, final int length) {
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AccessibleToast.makeText(app, msg, length).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
private void showMessage(final String msg){
|
||||
showMessage(msg, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
|
||||
// NEVER returns null
|
||||
public RouteCalculationResult getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
public GPXFile generateGPXFileWithRoute(){
|
||||
return provider.createOsmandRouterGPX(route);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setProgressBar(ProgressBar pb, Handler handler) {
|
||||
progress = pb;
|
||||
progressHandler = handler;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,566 +0,0 @@
|
|||
package net.osmand.plus.routing;
|
||||
|
||||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.voice.AbstractPrologCommandPlayer;
|
||||
import net.osmand.plus.voice.CommandBuilder;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.router.TurnType;
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
public class VoiceRouter {
|
||||
private final int STATUS_UTWP_TOLD = -1;
|
||||
private final int STATUS_UNKNOWN = 0;
|
||||
private final int STATUS_LONG_PREPARE = 1;
|
||||
private final int STATUS_PREPARE = 2;
|
||||
private final int STATUS_TURN_IN = 3;
|
||||
private final int STATUS_TURN = 4;
|
||||
private final int STATUS_TOLD = 5;
|
||||
|
||||
private final RoutingHelper router;
|
||||
private boolean mute = false;
|
||||
private CommandPlayer player;
|
||||
|
||||
|
||||
private int currentStatus = STATUS_UNKNOWN;
|
||||
private float playGoAheadDist = 0;
|
||||
|
||||
// private long lastTimeRouteRecalcAnnounced = 0;
|
||||
|
||||
// default speed to have comfortable announcements (if actual speed is higher than it would be problem)
|
||||
// Speed in m/s
|
||||
protected float DEFAULT_SPEED = 12;
|
||||
protected float TURN_DEFAULT_SPEED = 5;
|
||||
|
||||
protected int PREPARE_LONG_DISTANCE = 0;
|
||||
protected int PREPARE_LONG_DISTANCE_END = 0;
|
||||
protected int PREPARE_DISTANCE = 0;
|
||||
protected int PREPARE_DISTANCE_END = 0;
|
||||
protected int TURN_IN_DISTANCE = 0;
|
||||
protected int TURN_IN_DISTANCE_END = 0;
|
||||
protected int TURN_DISTANCE = 0;
|
||||
|
||||
protected VoiceCommandPending pendingCommand = null;
|
||||
private RouteDirectionInfo nextRouteDirection;
|
||||
|
||||
|
||||
public VoiceRouter(RoutingHelper router, CommandPlayer player) {
|
||||
this.router = router;
|
||||
this.player = player;
|
||||
updateAppMode();
|
||||
}
|
||||
|
||||
public void setPlayer(CommandPlayer player) {
|
||||
this.player = player;
|
||||
if(pendingCommand != null && player != null){
|
||||
CommandBuilder newCommand = getNewCommandPlayerToPlay();
|
||||
if (newCommand != null) {
|
||||
pendingCommand.play(newCommand);
|
||||
}
|
||||
pendingCommand = null;
|
||||
}
|
||||
}
|
||||
|
||||
public CommandPlayer getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public void setMute(boolean mute) {
|
||||
this.mute = mute;
|
||||
}
|
||||
|
||||
public boolean isMute() {
|
||||
return mute;
|
||||
}
|
||||
|
||||
|
||||
protected CommandBuilder getNewCommandPlayerToPlay(){
|
||||
if(player == null || mute){
|
||||
return null;
|
||||
}
|
||||
return player.newCommandBuilder();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void updateAppMode(){
|
||||
// turn prompt starts either at distance, or if actual-lead-time(currentSpeed) < maximum-lead-time
|
||||
// lead time criterion only for TURN_IN and TURN
|
||||
PREPARE_LONG_DISTANCE = 3500; // (105 sec) - 120 km/h
|
||||
PREPARE_LONG_DISTANCE_END = 3000; // (90 sec) - 120 km/h
|
||||
if(router.getAppMode() == ApplicationMode.PEDESTRIAN){
|
||||
// prepare distance is not needed for pedestrian
|
||||
PREPARE_DISTANCE = 200; //(100 sec)
|
||||
PREPARE_DISTANCE_END = 150 + 100; //( 75 sec) + not play
|
||||
TURN_IN_DISTANCE = 100; // 50 sec
|
||||
TURN_IN_DISTANCE_END = 70; // 35 sec
|
||||
TURN_DISTANCE = 25; // 12 sec
|
||||
TURN_DEFAULT_SPEED = DEFAULT_SPEED = 2f; // 7,2 km/h
|
||||
} else if(router.getAppMode() == ApplicationMode.BICYCLE){
|
||||
PREPARE_DISTANCE = 500; //(100 sec)
|
||||
PREPARE_DISTANCE_END = 350; //( 70 sec)
|
||||
TURN_IN_DISTANCE = 225; // 45 sec
|
||||
TURN_IN_DISTANCE_END = 80; // 16 sec
|
||||
TURN_DISTANCE = 45; // 9 sec
|
||||
TURN_DEFAULT_SPEED = DEFAULT_SPEED = 5; // 18 km/h
|
||||
} else {
|
||||
PREPARE_DISTANCE = 1500; //(125 sec)
|
||||
PREPARE_DISTANCE_END = 1200;//(100 sec)
|
||||
TURN_IN_DISTANCE = 390; // 30 sec
|
||||
TURN_IN_DISTANCE_END = 182; // 14 sec
|
||||
TURN_DISTANCE = 50; // 7 sec
|
||||
TURN_DEFAULT_SPEED = 7f; // 25 km/h
|
||||
DEFAULT_SPEED = 13; // 48 km/h
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isDistanceLess(float currentSpeed, double dist, double etalon){
|
||||
if(dist < etalon || ((dist / currentSpeed) < (etalon / DEFAULT_SPEED))){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isDistanceLess(float currentSpeed, double dist, double etalon, double defSpeed){
|
||||
if(dist < etalon || ((dist / currentSpeed) < (etalon / defSpeed))){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int calculateImminent(float dist, Location loc){
|
||||
float speed = DEFAULT_SPEED;
|
||||
if(loc != null && loc.hasSpeed()) {
|
||||
speed = loc.getSpeed();
|
||||
}
|
||||
if (isDistanceLess(speed, dist, TURN_IN_DISTANCE_END)) {
|
||||
return 0;
|
||||
} else if ( dist <= PREPARE_DISTANCE) {
|
||||
return 1;
|
||||
} else if (dist <= PREPARE_LONG_DISTANCE) {
|
||||
return 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void nextStatusAfter(int previousStatus){
|
||||
//STATUS_UNKNOWN=0 -> STATUS_LONG_PREPARE=1 -> STATUS_PREPARE=2 -> STATUS_TURN_IN=3 -> STATUS_TURN=4 -> STATUS_TOLD=5
|
||||
if(previousStatus != STATUS_TOLD){
|
||||
this.currentStatus = previousStatus + 1;
|
||||
} else {
|
||||
this.currentStatus = previousStatus;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean statusNotPassed(int statusToCheck){
|
||||
return currentStatus <= statusToCheck;
|
||||
}
|
||||
|
||||
protected void makeUTStatus() {
|
||||
// Mechanism via STATUS_UTWP_TOLD: Until turn in the right direction, or route is re-calculated in forward direction
|
||||
if (currentStatus != STATUS_UTWP_TOLD) {
|
||||
if (playMakeUTwp()) {
|
||||
currentStatus = STATUS_UTWP_TOLD;
|
||||
playGoAheadDist = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates status of voice guidance
|
||||
* @param currentLocation
|
||||
*/
|
||||
protected void updateStatus(Location currentLocation) {
|
||||
// Directly after turn: goAhead (dist), unless:
|
||||
// < PREPARE_LONG_DISTANCE (3000m): playPrepareTurn
|
||||
// < PREPARE_DISTANCE (1500m): playPrepareTurn
|
||||
// < TURN_IN_DISTANCE (300m or 25sec): playMakeTurnIn
|
||||
// < TURN_DISTANCE (60m or 5sec): playMakeTurn
|
||||
float speed = DEFAULT_SPEED;
|
||||
if (currentLocation != null && currentLocation.hasSpeed()) {
|
||||
speed = Math.max(currentLocation.getSpeed(), speed);
|
||||
}
|
||||
|
||||
|
||||
NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true);
|
||||
// after last turn say:
|
||||
if (nextInfo == null || nextInfo.directionInfo == null || nextInfo.directionInfo.distance == 0) {
|
||||
// if(currentStatus <= STATUS_UNKNOWN && currentDirection > 0){ This caused this prompt to be suppressed when coming back from a
|
||||
if (currentStatus <= STATUS_UNKNOWN) {
|
||||
if (playGoAheadToDestination()) {
|
||||
currentStatus = STATUS_TOLD;
|
||||
playGoAheadDist = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(nextInfo.intermediatePoint){
|
||||
if (currentStatus <= STATUS_UNKNOWN) {
|
||||
if (playGoAheadToIntermediate()) {
|
||||
currentStatus = STATUS_TOLD;
|
||||
playGoAheadDist = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
int dist = nextInfo.distanceTo;
|
||||
RouteDirectionInfo next = nextInfo.directionInfo;
|
||||
|
||||
// if routing is changed update status to unknown
|
||||
if (next != nextRouteDirection) {
|
||||
nextRouteDirection = next;
|
||||
currentStatus = STATUS_UNKNOWN;
|
||||
playGoAheadDist = 0;
|
||||
}
|
||||
|
||||
if (dist == 0 || currentStatus == STATUS_TOLD) {
|
||||
// nothing said possibly that's wrong case we should say before that
|
||||
// however it should be checked manually ?
|
||||
return;
|
||||
}
|
||||
// say how much to go if there is next turn is a bit far
|
||||
if (currentStatus == STATUS_UNKNOWN) {
|
||||
if (!isDistanceLess(speed, dist, TURN_IN_DISTANCE * 1.3)) {
|
||||
playGoAheadDist = dist - 80;
|
||||
}
|
||||
// say long distance message only for long distances > 10 km
|
||||
// if (dist >= PREPARE_LONG_DISTANCE && !isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE)) {
|
||||
if (dist > PREPARE_LONG_DISTANCE + 300) {
|
||||
nextStatusAfter(STATUS_UNKNOWN);
|
||||
} else if (dist > PREPARE_DISTANCE + 300) {
|
||||
// say prepare message if it is far enough and don't say preare long distance
|
||||
nextStatusAfter(STATUS_LONG_PREPARE);
|
||||
} else {
|
||||
// don't say even prepare message
|
||||
nextStatusAfter(STATUS_PREPARE);
|
||||
}
|
||||
}
|
||||
|
||||
NextDirectionInfo nextNextInfo = router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), true);
|
||||
if (statusNotPassed(STATUS_TURN) && isDistanceLess(speed, dist, TURN_DISTANCE, TURN_DEFAULT_SPEED)) {
|
||||
if (next.distance < TURN_IN_DISTANCE_END && nextNextInfo != null) {
|
||||
playMakeTurn(next, nextNextInfo.directionInfo);
|
||||
} else {
|
||||
playMakeTurn(next, null);
|
||||
}
|
||||
nextStatusAfter(STATUS_TURN);
|
||||
} else if (statusNotPassed(STATUS_TURN_IN) && isDistanceLess(speed, dist, TURN_IN_DISTANCE)) {
|
||||
if (dist >= TURN_IN_DISTANCE_END) {
|
||||
if ((isDistanceLess(speed, next.distance, TURN_DISTANCE) || next.distance < TURN_IN_DISTANCE_END) &&
|
||||
nextNextInfo != null) {
|
||||
playMakeTurnIn(next, dist, nextNextInfo.directionInfo);
|
||||
} else {
|
||||
playMakeTurnIn(next, dist, null);
|
||||
}
|
||||
}
|
||||
nextStatusAfter(STATUS_TURN_IN);
|
||||
// } else if (statusNotPassed(STATUS_PREPARE) && isDistanceLess(speed, dist, PREPARE_DISTANCE)) {
|
||||
} else if (statusNotPassed(STATUS_PREPARE) && (dist <= PREPARE_DISTANCE)) {
|
||||
if (dist >= PREPARE_DISTANCE_END) {
|
||||
if(next.getTurnType().keepLeft() || next.getTurnType().keepRight()){
|
||||
// do not play prepare for keep left/right
|
||||
} else {
|
||||
playPrepareTurn(next, dist);
|
||||
}
|
||||
}
|
||||
nextStatusAfter(STATUS_PREPARE);
|
||||
// } else if (statusNotPassed(STATUS_LONG_PREPARE) && isDistanceLess(speed, dist, PREPARE_LONG_DISTANCE)){
|
||||
} else if (statusNotPassed(STATUS_LONG_PREPARE) && (dist <= PREPARE_LONG_DISTANCE)) {
|
||||
if (dist >= PREPARE_LONG_DISTANCE_END) {
|
||||
playPrepareTurn(next, dist);
|
||||
}
|
||||
nextStatusAfter(STATUS_LONG_PREPARE);
|
||||
} else if (statusNotPassed(STATUS_UNKNOWN)) {
|
||||
// strange how we get here but
|
||||
nextStatusAfter(STATUS_UNKNOWN);
|
||||
} else if (statusNotPassed(STATUS_TURN_IN) && dist < playGoAheadDist) {
|
||||
playGoAheadDist = 0;
|
||||
playGoAhead(dist);
|
||||
}
|
||||
}
|
||||
|
||||
public void announceCurrentDirection(Location currentLocation) {
|
||||
NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true);
|
||||
if(nextInfo == null) {
|
||||
playGoAheadToDestination();
|
||||
return;
|
||||
}
|
||||
NextDirectionInfo nextNextInfo = router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), false);
|
||||
float speed = DEFAULT_SPEED;
|
||||
RouteDirectionInfo next = nextInfo.directionInfo;
|
||||
int dist = nextInfo.distanceTo;
|
||||
|
||||
if(currentLocation != null && currentLocation.hasSpeed()){
|
||||
speed = Math.max(currentLocation.getSpeed(), speed);
|
||||
}
|
||||
|
||||
switch (currentStatus) {
|
||||
case STATUS_UTWP_TOLD:
|
||||
playMakeUTwp();
|
||||
break;
|
||||
case STATUS_UNKNOWN:
|
||||
if (nextRouteDirection != null && ((next == null) || (next.distance == 0))) {
|
||||
playGoAheadToDestination();
|
||||
} else {
|
||||
playGoAhead(dist);
|
||||
}
|
||||
break;
|
||||
case STATUS_TOLD:
|
||||
if (nextRouteDirection != null) {
|
||||
playGoAheadToDestination();
|
||||
}
|
||||
break;
|
||||
case STATUS_TURN:
|
||||
if(next.distance < TURN_IN_DISTANCE_END && nextNextInfo != null) {
|
||||
playMakeTurn(next, nextNextInfo.directionInfo);
|
||||
} else {
|
||||
playMakeTurn(next, null);
|
||||
}
|
||||
break;
|
||||
case STATUS_TURN_IN:
|
||||
if((isDistanceLess(speed, next.distance, TURN_DISTANCE) || next.distance < TURN_IN_DISTANCE_END) &&
|
||||
nextNextInfo != null) {
|
||||
playMakeTurnIn(next, dist, nextNextInfo.directionInfo);
|
||||
} else {
|
||||
playMakeTurnIn(next, dist, null);
|
||||
}
|
||||
break;
|
||||
case STATUS_PREPARE:
|
||||
playPrepareTurn(next, dist);
|
||||
break;
|
||||
case STATUS_LONG_PREPARE:
|
||||
playPrepareTurn(next, dist);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean playGoAheadToDestination() {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.goAhead(router.getLeftDistance()).andArriveAtDestination().play();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean playGoAheadToIntermediate() {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.goAhead(router.getLeftDistanceNextIntermediate()).andArriveAtIntermediatePoint().play();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean playMakeUTwp() {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.makeUTwp().play();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void playGoAhead(int dist) {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.goAhead(dist).play();
|
||||
}
|
||||
}
|
||||
|
||||
private void playPrepareTurn(RouteDirectionInfo next, int dist) {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
String tParam = getTurnType(next.getTurnType());
|
||||
if(tParam != null){
|
||||
play.prepareTurn(tParam, dist).play();
|
||||
} else if(next.getTurnType().isRoundAbout()){
|
||||
play.prepareRoundAbout(dist).play();
|
||||
} else if(next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)){
|
||||
play.prepareMakeUT(dist).play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void playMakeTurnIn(RouteDirectionInfo next, int dist, RouteDirectionInfo pronounceNextNext) {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if (play != null) {
|
||||
String tParam = getTurnType(next.getTurnType());
|
||||
boolean isPlay = true;
|
||||
if (tParam != null) {
|
||||
play.turn(tParam, dist);
|
||||
} else if (next.getTurnType().isRoundAbout()) {
|
||||
play.roundAbout(dist, next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut());
|
||||
} else if (next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)) {
|
||||
play.makeUT(dist);
|
||||
} else {
|
||||
isPlay = false;
|
||||
}
|
||||
// small preparation to next after next
|
||||
if (pronounceNextNext != null) {
|
||||
TurnType t = pronounceNextNext.getTurnType();
|
||||
isPlay = true;
|
||||
if (next.getTurnType().getValue().equals(TurnType.C) &&
|
||||
!TurnType.C.equals(t.getValue())) {
|
||||
play.goAhead(dist);
|
||||
}
|
||||
if (TurnType.TL.equals(t.getValue()) || TurnType.TSHL.equals(t.getValue()) || TurnType.TSLL.equals(t.getValue())
|
||||
|| TurnType.TU.equals(t.getValue()) || TurnType.KL.equals(t.getValue())) {
|
||||
play.then().bearLeft();
|
||||
} else if (TurnType.TR.equals(t.getValue()) || TurnType.TSHR.equals(t.getValue()) || TurnType.TSLR.equals(t.getValue())
|
||||
|| TurnType.KR.equals(t.getValue())) {
|
||||
play.then().bearRight();
|
||||
}
|
||||
}
|
||||
if(isPlay){
|
||||
play.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void playMakeTurn(RouteDirectionInfo next, RouteDirectionInfo nextNext) {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
String tParam = getTurnType(next.getTurnType());
|
||||
boolean isplay = true;
|
||||
if(tParam != null){
|
||||
play.turn(tParam);
|
||||
} else if(next.getTurnType().isRoundAbout()){
|
||||
play.roundAbout(next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut());
|
||||
} else if(next.getTurnType().getValue().equals(TurnType.TU) || next.getTurnType().getValue().equals(TurnType.TRU)){
|
||||
play.makeUT();
|
||||
// do not say it
|
||||
// } else if(next.getTurnType().getValue().equals(TurnType.C)){
|
||||
// play.goAhead();
|
||||
} else {
|
||||
isplay = false;
|
||||
}
|
||||
// add turn after next
|
||||
if (nextNext != null) {
|
||||
String t2Param = getTurnType(nextNext.getTurnType());
|
||||
if (t2Param != null) {
|
||||
if(isplay) { play.then(); }
|
||||
play.turn(t2Param, next.distance);
|
||||
} else if (nextNext.getTurnType().isRoundAbout()) {
|
||||
if(isplay) { play.then(); }
|
||||
play.roundAbout(next.distance, nextNext.getTurnType().getTurnAngle(), nextNext.getTurnType().getExitOut());
|
||||
} else if (nextNext.getTurnType().getValue().equals(TurnType.TU)) {
|
||||
if(isplay) { play.then(); }
|
||||
play.makeUT(next.distance);
|
||||
}
|
||||
isplay = true;
|
||||
}
|
||||
if(isplay){
|
||||
play.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getTurnType(TurnType t){
|
||||
if(TurnType.TL.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_LEFT;
|
||||
} else if(TurnType.TSHL.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SH;
|
||||
} else if(TurnType.TSLL.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SL;
|
||||
} else if(TurnType.TR.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_RIGHT;
|
||||
} else if(TurnType.TSHR.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SH;
|
||||
} else if(TurnType.TSLR.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SL;
|
||||
} else if(TurnType.KL.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_LEFT_KEEP;
|
||||
} else if(TurnType.KR.equals(t.getValue())){
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_KEEP;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void gpsLocationLost(){
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if (play != null) {
|
||||
play.gpsLocationLost().play();
|
||||
}
|
||||
}
|
||||
|
||||
public void newRouteIsCalculated(boolean newRoute) {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if (play != null) {
|
||||
if (!newRoute) {
|
||||
// suppress "route recalculated" prompt for GPX-routing, it makes no sense
|
||||
// suppress "route recalculated" prompt for 60sec (this workaround now outdated after more intelligent route recalculation and directional voice prompt suppression)
|
||||
// if (router.getCurrentGPXRoute() == null && (System.currentTimeMillis() - lastTimeRouteRecalcAnnounced > 60000)) {
|
||||
if (router.getCurrentGPXRoute() == null) {
|
||||
play.routeRecalculated(router.getLeftDistance()).play();
|
||||
currentStatus = STATUS_UNKNOWN;
|
||||
// lastTimeRouteRecalcAnnounced = System.currentTimeMillis();
|
||||
}
|
||||
} else {
|
||||
play.newRouteCalculated(router.getLeftDistance()).play();
|
||||
currentStatus = STATUS_UNKNOWN;
|
||||
}
|
||||
} else if (player == null) {
|
||||
pendingCommand = new VoiceCommandPending(!newRoute ? VoiceCommandPending.ROUTE_RECALCULATED
|
||||
: VoiceCommandPending.ROUTE_CALCULATED, this);
|
||||
currentStatus = STATUS_UNKNOWN;
|
||||
}
|
||||
nextRouteDirection = null;
|
||||
}
|
||||
|
||||
public void arrivedDestinationPoint() {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.arrivedAtDestination().play();
|
||||
}
|
||||
}
|
||||
|
||||
public void arrivedIntermediatePoint() {
|
||||
CommandBuilder play = getNewCommandPlayerToPlay();
|
||||
if(play != null){
|
||||
play.arrivedAtIntermediatePoint().play();
|
||||
}
|
||||
}
|
||||
|
||||
public void onApplicationTerminate(Context ctx) {
|
||||
if (player != null) {
|
||||
player.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command to wait until voice player is initialized
|
||||
*/
|
||||
private class VoiceCommandPending {
|
||||
public static final int ROUTE_CALCULATED = 1;
|
||||
public static final int ROUTE_RECALCULATED = 2;
|
||||
protected final int type;
|
||||
private final VoiceRouter voiceRouter;
|
||||
|
||||
public VoiceCommandPending(int type, VoiceRouter voiceRouter){
|
||||
this.type = type;
|
||||
this.voiceRouter = voiceRouter;
|
||||
}
|
||||
|
||||
public void play(CommandBuilder newCommand) {
|
||||
int left = voiceRouter.router.getLeftDistance();
|
||||
if (left > 0) {
|
||||
if (type == ROUTE_CALCULATED) {
|
||||
newCommand.newRouteCalculated(left).play();
|
||||
} else if (type == ROUTE_RECALCULATED) {
|
||||
newCommand.routeRecalculated(left).play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue