Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
1dfb6988a9
[routing] Implement request queuing for AsyncRouter
Each request is queued and processed sequentially.
A request is a delegate proxy and an edge estimator strategy.

Signed-off-by: tmpod <tom@tmpod.dev>
2024-08-26 17:05:52 +01:00
Viktor Govako
b65605c0b7
[routing] Alternative routes after GSoC 2022.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2024-08-26 16:52:53 +01:00
c6d8adc2fd
Improve clangd support
clangd is a very useful tool, serving as a Language Server for C/C++,
helping non-IDE editors tremendously.
With these tweaks, it works flawlessly on my setup.

Add a .clangd config file to exclude the `-mno-direct-extern-access`
flag which works fine on gcc but not on clang.
Also tell CMake to export a thing called "compile commands", which is
essentially a JSON file detailing all the commands used in compilation,
so that clangd can correctly process headers and allow you to jump
between definitions, uses and whatnot.
Finally, adds `.cache/clangd` to the gitignore file.

Signed-off-by: tmpod <tom@tmpod.dev>
2024-08-26 16:52:52 +01:00
33 changed files with 1089 additions and 778 deletions

4
.clangd Normal file
View file

@ -0,0 +1,4 @@
CompileFlags:
Remove:
# clang has an issue with this flag, while gcc does not
- "-mno-direct-extern-access"

3
.gitignore vendored
View file

@ -188,3 +188,6 @@ screenshots/
android/src/google/play/listings/
keywords/
iphone/metadata/**/keywords.txt
# clangd cache
.cache/clangd/

View file

@ -11,6 +11,8 @@ set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Fixes warning ld: warning: ignoring duplicate libraries on Mac and Windows.
if (POLICY CMP0156)
cmake_policy(SET CMP0156 NEW)

View file

@ -10,6 +10,12 @@ routing::RoutingOptions::Road makeValue(jint option)
return static_cast<routing::RoutingOptions::Road>(road);
}
routing::EdgeEstimator::Strategy makeStrategyValue(jint strategy)
{
int convertedStrat = static_cast<int>(strategy);
return static_cast<routing::EdgeEstimator::Strategy>(convertedStrat);
}
extern "C"
{
@ -22,6 +28,14 @@ Java_app_organicmaps_routing_RoutingOptions_nativeHasOption(JNIEnv * env, jclass
return static_cast<jboolean>(routingOptions.Has(road));
}
JNIEXPORT jint JNICALL
Java_com_mapswithme_maps_routing_RoutingOptions_nativeGetStrategy(JNIEnv * env, jclass clazz)
{
CHECK(g_framework, ("Framework isn't created yet!"));
routing::EdgeEstimator::Strategy routingStrategy = routing::EdgeEstimator::LoadRoutingStrategyFromSettings();
return static_cast<jint>(routingStrategy);
}
JNIEXPORT void JNICALL
Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass clazz, jint option)
{
@ -32,7 +46,6 @@ Java_app_organicmaps_routing_RoutingOptions_nativeAddOption(JNIEnv * env, jclass
routing::RoutingOptions::SaveCarOptionsToSettings(routingOptions);
}
JNIEXPORT void JNICALL
Java_app_organicmaps_routing_RoutingOptions_nativeRemoveOption(JNIEnv * env, jclass clazz, jint option)
{
@ -42,4 +55,11 @@ Java_app_organicmaps_routing_RoutingOptions_nativeRemoveOption(JNIEnv * env, jcl
routingOptions.Remove(road);
routing::RoutingOptions::SaveCarOptionsToSettings(routingOptions);
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_routing_RoutingOptions_nativeSetStrategy(JNIEnv * env, jclass clazz, jint strategy)
{
CHECK(g_framework, ("Framework isn't created yet!"));
routing::EdgeEstimator::SaveRoutingStrategyToSettings(makeStrategyValue(strategy));
}
}

View file

@ -3,6 +3,7 @@ package app.organicmaps.routing;
import androidx.annotation.NonNull;
import app.organicmaps.settings.RoadType;
import app.organicmaps.settings.RoutingStrategyType;
import java.util.HashSet;
import java.util.Set;
@ -24,9 +25,21 @@ public class RoutingOptions
return nativeHasOption(roadType.ordinal());
}
public static int getStrategy()
{
return nativeGetStrategy();
}
public static void setStrategy(@NonNull RoutingStrategyType routingStrategyType)
{
nativeSetStrategy(routingStrategyType.ordinal());
}
private static native void nativeAddOption(int option);
private static native void nativeRemoveOption(int option);
private static native boolean nativeHasOption(int option);
private static native int nativeGetStrategy();
private static native void nativeSetStrategy(int strategy);
public static boolean hasAnyOptions()
{
@ -49,4 +62,10 @@ public class RoutingOptions
}
return roadTypes;
}
public static RoutingStrategyType getActiveRoutingStrategyType()
{
int strategyType = getStrategy();
return RoutingStrategyType.values()[strategyType];
}
}

View file

@ -6,6 +6,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.RadioGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -25,8 +26,11 @@ import java.util.Set;
public class DrivingOptionsFragment extends BaseMwmToolbarFragment
{
public static final String BUNDLE_ROAD_TYPES = "road_types";
public static final String BUNDLE_ROUTING_STRATEGY_TYPE = "routing_strategy_type";
@NonNull
private Set<RoadType> mRoadTypes = Collections.emptySet();
@NonNull
private RoutingStrategyType mStrategy = RoutingStrategyType.Fastest;
@Nullable
@Override
@ -38,6 +42,9 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
mRoadTypes = savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_ROAD_TYPES)
? makeRouteTypes(savedInstanceState)
: RoutingOptions.getActiveRoadTypes();
mStrategy = savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_ROUTING_STRATEGY_TYPE)
? makeRoutingStrategyType(savedInstanceState)
: RoutingOptions.getActiveRoutingStrategyType();
return root;
}
@ -53,6 +60,13 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
return result;
}
@NonNull
private RoutingStrategyType makeRoutingStrategyType(@NonNull Bundle bundle)
{
RoutingStrategyType result = Objects.requireNonNull((RoutingStrategyType)bundle.getSerializable(BUNDLE_ROUTING_STRATEGY_TYPE));
return result;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState)
{
@ -63,12 +77,15 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
savedRoadTypes.add(each.ordinal());
}
outState.putIntegerArrayList(BUNDLE_ROAD_TYPES, savedRoadTypes);
outState.putSerializable(BUNDLE_ROUTING_STRATEGY_TYPE, mStrategy);
}
private boolean areSettingsNotChanged()
{
Set<RoadType> lastActiveRoadTypes = RoutingOptions.getActiveRoadTypes();
return mRoadTypes.equals(lastActiveRoadTypes);
RoutingStrategyType lastActiveStrategyType = RoutingOptions.getActiveRoutingStrategyType();
return mRoadTypes.equals(lastActiveRoadTypes) && mStrategy.equals(lastActiveStrategyType);
}
@Override
@ -104,6 +121,26 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
CompoundButton.OnCheckedChangeListener dirtyBtnListener =
new ToggleRoutingOptionListener(RoadType.Dirty);
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
RadioGroup strategyRadioGroup = root.findViewById(R.id.routing_strategy_types);
RoutingStrategyType currentStrategy = RoutingOptions.getActiveRoutingStrategyType();
int currentCheckedStrategyId;
switch (currentStrategy)
{
case Shortest:
currentCheckedStrategyId = R.id.use_strategy_shortest;
break;
case FewerTurns:
currentCheckedStrategyId = R.id.use_strategy_fewerTurns;
break;
default:
currentCheckedStrategyId = R.id.use_strategy_fastest;
break;
}
strategyRadioGroup.check(currentCheckedStrategyId);
RadioGroup.OnCheckedChangeListener strategyRadioGroupListener =
new ToggleRoutingStrategyListener();
strategyRadioGroup.setOnCheckedChangeListener(strategyRadioGroupListener);
}
private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener
@ -125,4 +162,26 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
RoutingOptions.removeOption(mRoadType);
}
}
private static class ToggleRoutingStrategyListener implements RadioGroup.OnCheckedChangeListener
{
private ToggleRoutingStrategyListener() {}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
switch (checkedId)
{
case R.id.use_strategy_fastest:
RoutingOptions.setStrategy(RoutingStrategyType.Fastest);
break;
case R.id.use_strategy_shortest:
RoutingOptions.setStrategy(RoutingStrategyType.Shortest);
break;
case R.id.use_strategy_fewerTurns:
RoutingOptions.setStrategy(RoutingStrategyType.FewerTurns);
break;
}
}
}
}

View file

@ -0,0 +1,8 @@
package app.organicmaps.settings;
public enum RoutingStrategyType
{
Fastest,
Shortest,
FewerTurns
}

View file

@ -104,4 +104,46 @@
android:padding="@dimen/margin_half_double_plus"
android:layout_height="match_parent"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@android:color/darker_gray"/>
<TextView
android:text="@string/driving_options_subheader2"
android:textAppearance="?android:attr/textAppearance"
android:textColor="?colorAccent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="@dimen/margin_half_double_plus"
android:paddingEnd="@dimen/margin_base"
android:paddingStart="@dimen/margin_base"/>
<RadioGroup
android:id="@+id/routing_strategy_types"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_base">
<RadioButton
android:id="@+id/use_strategy_fastest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_half_plus"
android:checked="true"
android:text="@string/use_strategy_fastest"/>
<RadioButton
android:id="@+id/use_strategy_shortest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_half_plus"
android:checked="false"
android:text="@string/use_strategy_shortest"/>
<RadioButton
android:id="@+id/use_strategy_fewerTurns"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_half_plus"
android:checked="false"
android:text="@string/use_strategy_fewerTurns"/>
</RadioGroup>
</LinearLayout>

View file

@ -697,12 +697,16 @@
<string name="access_rules_author_only">Online editing</string>
<string name="driving_options_title">Routing options</string>
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
<string name="driving_options_subheader2">Routing Strategy</string>
<string name="avoid_tolls">Avoid tolls</string>
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
<string name="avoid_unpaved">Avoid unpaved roads</string>
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
<string name="avoid_ferry">Avoid ferries</string>
<string name="avoid_motorways">Avoid freeways</string>
<string name="use_strategy_fastest">Fastest</string>
<string name="use_strategy_shortest">Shortest</string>
<string name="use_strategy_fewerTurns">Fewer turns</string>
<string name="unable_to_calc_alert_title">Unable to calculate route</string>
<string name="unable_to_calc_alert_subtitle">A route could not be found. This may be caused by your routing options or incomplete OpenStreetMap data. Please change your routing options and retry.</string>
<string name="define_to_avoid_btn">Define roads to avoid</string>

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,7 @@ class DataSource;
namespace power_management
{
class PowerManager;
class PowerManager;
}
struct RoutePointInfo
@ -79,12 +79,11 @@ public:
using GetStringsBundleFn = std::function<StringsBundle const &()>;
using PowerManagerGetter = std::function<power_management::PowerManager const &()>;
template <typename DataSourceGetter, typename CountryInfoGetter,
typename CountryParentNameGetter, typename StringsBundleGetter,
typename PowerManagerGetter>
template <typename DataSourceGetter, typename CountryInfoGetter, typename CountryParentNameGetter,
typename StringsBundleGetter, typename PowerManagerGetter>
Callbacks(DataSourceGetter && dataSourceGetter, CountryInfoGetter && countryInfoGetter,
CountryParentNameGetter && countryParentNameGetter,
StringsBundleGetter && stringsBundleGetter, PowerManagerGetter && powerManagerGetter)
CountryParentNameGetter && countryParentNameGetter, StringsBundleGetter && stringsBundleGetter,
PowerManagerGetter && powerManagerGetter)
: m_dataSourceGetter(std::forward<DataSourceGetter>(dataSourceGetter))
, m_countryInfoGetter(std::forward<CountryInfoGetter>(countryInfoGetter))
, m_countryParentNameGetterFn(std::forward<CountryParentNameGetter>(countryParentNameGetter))
@ -100,12 +99,9 @@ public:
PowerManagerGetter m_powerManagerGetter;
};
using RouteBuildingCallback =
std::function<void(routing::RouterResultCode, storage::CountriesSet const &)>;
using RouteSpeedCamShowCallback =
std::function<void(m2::PointD const &, double)>;
using RouteSpeedCamsClearCallback =
std::function<void()>;
using RouteBuildingCallback = std::function<void(routing::RouterResultCode, storage::CountriesSet const &)>;
using RouteSpeedCamShowCallback = std::function<void(m2::PointD const &, double)>;
using RouteSpeedCamsClearCallback = std::function<void()>;
using RouteStartBuildCallback = std::function<void(std::vector<RouteMarkData> const & points)>;
@ -169,40 +165,27 @@ public:
}
void FollowRoute();
void CloseRouting(bool removeRoutePoints);
void GetRouteFollowingInfo(routing::FollowingInfo & info) const
{
m_routingSession.GetRouteFollowingInfo(info);
}
void GetRouteFollowingInfo(routing::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info); }
TransitRouteInfo GetTransitRouteInfo() const;
m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); }
/// Returns the most situable router engine type.
routing::RouterType GetBestRouter(m2::PointD const & startPoint,
m2::PointD const & finalPoint) const;
routing::RouterType GetBestRouter(m2::PointD const & startPoint, m2::PointD const & finalPoint) const;
routing::RouterType GetLastUsedRouter() const;
void SetLastUsedRouter(routing::RouterType type);
// Sound notifications for turn instructions.
void EnableTurnNotifications(bool enable) { m_routingSession.EnableTurnNotifications(enable); }
bool AreTurnNotificationsEnabled() const
{
return m_routingSession.AreTurnNotificationsEnabled();
}
bool AreTurnNotificationsEnabled() const { return m_routingSession.AreTurnNotificationsEnabled(); }
/// \brief Sets a locale for TTS.
/// \param locale is a string with locale code. For example "en", "ru", "zh-Hant" and so on.
/// \note See sound/tts/languages.txt for the full list of available locales.
void SetTurnNotificationsLocale(std::string const & locale)
{
m_routingSession.SetTurnNotificationsLocale(locale);
}
void SetTurnNotificationsLocale(std::string const & locale) { m_routingSession.SetTurnNotificationsLocale(locale); }
/// @return current TTS locale. For example "en", "ru", "zh-Hant" and so on.
/// In case of error returns an empty string.
/// \note The method returns correct locale after SetTurnNotificationsLocale has been called.
/// If not, it returns an empty string.
std::string GetTurnNotificationsLocale() const
{
return m_routingSession.GetTurnNotificationsLocale();
}
std::string GetTurnNotificationsLocale() const { return m_routingSession.GetTurnNotificationsLocale(); }
// @return polyline of the route.
routing::FollowedPolyline const & GetRoutePolylineForTests() const
{
@ -234,8 +217,8 @@ public:
void RemoveRoutePoints();
void RemoveIntermediateRoutePoints();
void MoveRoutePoint(size_t currentIndex, size_t targetIndex);
void MoveRoutePoint(RouteMarkType currentType, size_t currentIntermediateIndex,
RouteMarkType targetType, size_t targetIntermediateIndex);
void MoveRoutePoint(RouteMarkType currentType, size_t currentIntermediateIndex, RouteMarkType targetType,
size_t targetIntermediateIndex);
void HideRoutePoint(RouteMarkType type, size_t intermediateIndex = 0);
bool CouldAddIntermediatePoint() const;
bool IsMyPosition(RouteMarkType type, size_t intermediateIndex = 0);
@ -244,8 +227,7 @@ public:
void RemoveRoute(bool deactivateFollowing);
void CheckLocationForRouting(location::GpsInfo const & info);
void CallRouteBuilded(routing::RouterResultCode code,
storage::CountriesSet const & absentCountries);
void CallRouteBuilded(routing::RouterResultCode code, storage::CountriesSet const & absentCountries);
void OnBuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
void OnRebuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
void OnNeedMoreMaps(uint64_t routeId, storage::CountriesSet const & absentCountries);
@ -329,10 +311,7 @@ private:
{
RoadInfo() = default;
explicit RoadInfo(m2::PointD const & pt, FeatureID const & featureId)
: m_startPoint(pt)
, m_featureId(featureId)
{}
explicit RoadInfo(m2::PointD const & pt, FeatureID const & featureId) : m_startPoint(pt), m_featureId(featureId) {}
m2::PointD m_startPoint;
FeatureID m_featureId;
@ -340,15 +319,14 @@ private:
};
using RoadWarningsCollection = std::map<routing::RoutingOptions::Road, std::vector<RoadInfo>>;
using GetMwmIdFn = std::function<MwmSet::MwmId (routing::NumMwmId numMwmId)>;
using GetMwmIdFn = std::function<MwmSet::MwmId(routing::NumMwmId numMwmId)>;
void CollectRoadWarnings(std::vector<routing::RouteSegment> const & segments, m2::PointD const & startPt,
double baseDistance, GetMwmIdFn const & getMwmIdFn, RoadWarningsCollection & roadWarnings);
void CreateRoadWarningMarks(RoadWarningsCollection && roadWarnings);
/// \returns false if the location could not be matched to the route and should be matched to the
/// road graph. Otherwise returns true.
void MatchLocationToRoute(location::GpsInfo & info,
location::RouteMatchingInfo & routeMatchingInfo);
void MatchLocationToRoute(location::GpsInfo & info, location::RouteMatchingInfo & routeMatchingInfo);
location::RouteMatchingInfo GetRouteMatchingInfo(location::GpsInfo & info);
uint32_t GenerateRoutePointsTransactionId() const;

View file

@ -3,6 +3,7 @@
#include "map/framework.hpp"
#include "routing/router.hpp"
#include "routing/edge_estimator.hpp"
#include "platform/settings.hpp"
@ -24,12 +25,26 @@ std::string const kUseCachedRoutingSettings = "use_cached_settings_desktop";
std::string const kStartCoordsCachedSettings = "start_coords_desktop";
std::string const kFinishCoordsCachedSettings = "finish_coords_desktop";
std::string const kRouterTypeCachedSettings = "router_type_desktop";
std::string const kRouterStrategyCachedSettings = "router_strategy";
std::string const kAvoidRoutingOptionSettings = "avoid_routing_options_car";
int constexpr DefaultRouterIndex()
{
// Car router by default.
return static_cast<int>(routing::RouterType::Vehicle);
}
int constexpr DefaultStrategyIndex()
{
// Routing strategy by default
return static_cast<int>(routing::EdgeEstimator::Strategy::Fastest);
}
int constexpr DefaultAvoidOptionIndex()
{
// Avoid routing option by default
return static_cast<int>(routing::RoutingOptions::Road::Usual);
}
} // namespace
// static
@ -93,6 +108,8 @@ void RoutingSettings::LoadSession(Framework & framework)
settings::Delete(kStartCoordsCachedSettings);
settings::Delete(kFinishCoordsCachedSettings);
settings::Delete(kRouterTypeCachedSettings);
settings::Delete(kRouterStrategyCachedSettings);
settings::Delete(kAvoidRoutingOptionSettings);
}
}
@ -134,6 +151,20 @@ RoutingSettings::RoutingSettings(QWidget * parent, Framework & framework)
m_routerType->insertItem(static_cast<int>(RouterType::Ruler), "ruler");
form->addRow("Choose router:", m_routerType);
m_routerStrategy = new QComboBox(frame);
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::Fastest), "fastest");
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::Shortest), "shortest");
m_routerStrategy->insertItem(static_cast<int>(EdgeEstimator::Strategy::FewerTurns), "fewer turns");
form->addRow("Choose strategy:", m_routerStrategy);
m_avoidRoutingOptions = new QComboBox(frame);
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Dirty), "dirty");
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Ferry), "ferry");
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Motorway), "motorway");
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Toll), "toll");
m_avoidRoutingOptions->insertItem(static_cast<int>(RoutingOptions::Road::Usual), "usual");
form->addRow("Choose avoid option:", m_avoidRoutingOptions);
m_showTurnsCheckbox = new QCheckBox({}, frame);
form->addRow("Show turns:", m_showTurnsCheckbox);
@ -190,6 +221,8 @@ bool RoutingSettings::SaveSettings()
settings::Set(kUseDebugGuideSettings, m_useDebugGuideCheckbox->isChecked());
settings::Set(kUseCachedRoutingSettings, m_saveSessionCheckbox->isChecked());
settings::Set(kRouterTypeCachedSettings, m_routerType->currentIndex());
settings::Set(kRouterStrategyCachedSettings, m_routerStrategy->currentIndex());
settings::Set(kAvoidRoutingOptionSettings, m_avoidRoutingOptions->currentIndex());
return ValidateAndSaveCoordsFromInput();
}
@ -207,6 +240,14 @@ void RoutingSettings::LoadSettings()
settings::TryGet(kRouterTypeCachedSettings, routerType);
m_routerType->setCurrentIndex(routerType);
int routerStrategy = DefaultStrategyIndex();
settings::TryGet(kRouterStrategyCachedSettings, routerStrategy);
m_routerStrategy->setCurrentIndex(routerStrategy);
int avoidRoutingOption = DefaultAvoidOptionIndex();
settings::TryGet(kAvoidRoutingOptionSettings, avoidRoutingOption);
m_avoidRoutingOptions->setCurrentIndex(avoidRoutingOption);
bool showTurns = false;
settings::TryGet(kShowTurnsSettings, showTurns);
m_showTurnsCheckbox->setChecked(showTurns);

View file

@ -40,6 +40,8 @@ private:
QLineEdit * m_finishInput;
QComboBox * m_routerType;
QComboBox * m_routerStrategy;
QComboBox * m_avoidRoutingOptions;
QCheckBox * m_showTurnsCheckbox;
QCheckBox * m_useDebugGuideCheckbox;
QCheckBox * m_saveSessionCheckbox;

View file

@ -5,9 +5,6 @@
#include "routing/turns.hpp"
#include "drape_frontend/drape_api.hpp"
#include "drape_frontend/drape_engine.hpp"
#include "geometry/point2d.hpp"
#include <string>
#include <unordered_set>

View file

@ -1,6 +1,8 @@
#include "routing/async_router.hpp"
#include "geometry/mercator.hpp"
#include "routing/routing_options.hpp"
#include "platform/platform.hpp"
#include "base/logging.hpp"
#include "base/macros.hpp"
@ -19,8 +21,7 @@ AsyncRouter::RouterDelegateProxy::RouterDelegateProxy(ReadyCallbackOwnership con
NeedMoreMapsCallback const & onNeedMoreMaps,
RemoveRouteCallback const & onRemoveRoute,
PointCheckCallback const & onPointCheck,
ProgressCallback const & onProgress,
uint32_t timeoutSec)
ProgressCallback const & onProgress, uint32_t timeoutSec)
: m_onReadyOwnership(onReady)
, m_onNeedMoreMaps(onNeedMoreMaps)
, m_onRemoveRoute(onRemoveRoute)
@ -45,8 +46,7 @@ void AsyncRouter::RouterDelegateProxy::OnReady(std::shared_ptr<Route> route, Rou
m_onReadyOwnership(std::move(route), resultCode);
}
void AsyncRouter::RouterDelegateProxy::OnNeedMoreMaps(uint64_t routeId,
std::set<std::string> const & absentCounties)
void AsyncRouter::RouterDelegateProxy::OnNeedMoreMaps(uint64_t routeId, std::set<std::string> const & absentCounties)
{
if (!m_onNeedMoreMaps)
return;
@ -76,8 +76,7 @@ void AsyncRouter::RouterDelegateProxy::Cancel()
m_delegate.Cancel();
}
bool AsyncRouter::FindClosestProjectionToRoad(m2::PointD const & point,
m2::PointD const & direction, double radius,
bool AsyncRouter::FindClosestProjectionToRoad(m2::PointD const & point, m2::PointD const & direction, double radius,
EdgeProj & proj)
{
return m_router->FindClosestProjectionToRoad(point, direction, radius, proj);
@ -96,9 +95,7 @@ void AsyncRouter::RouterDelegateProxy::OnProgress(float progress)
return;
onProgress = m_onProgress;
GetPlatform().RunTask(Platform::Thread::Gui, [onProgress, progress]() {
onProgress(progress);
});
GetPlatform().RunTask(Platform::Thread::Gui, [onProgress, progress]() { onProgress(progress); });
}
}
@ -127,10 +124,7 @@ void AsyncRouter::RouterDelegateProxy::OnPointCheck(ms::LatLon const & pt)
// -------------------------------------------------------------------------------------------------
AsyncRouter::AsyncRouter(PointCheckCallback const & pointCheckCallback)
: m_threadExit(false)
, m_hasRequest(false)
, m_clearState(false)
, m_pointCheckCallback(pointCheckCallback)
: m_threadExit(false), m_clearState(false), m_pointCheckCallback(pointCheckCallback)
{
m_thread = threads::SimpleThread(&AsyncRouter::ThreadFunc, this);
}
@ -149,8 +143,7 @@ AsyncRouter::~AsyncRouter()
m_thread.join();
}
void AsyncRouter::SetRouter(std::unique_ptr<IRouter> && router,
std::unique_ptr<AbsentRegionsFinder> && finder)
void AsyncRouter::SetRouter(std::unique_ptr<IRouter> && router, std::unique_ptr<AbsentRegionsFinder> && finder)
{
unique_lock ul(m_guard);
@ -160,8 +153,8 @@ void AsyncRouter::SetRouter(std::unique_ptr<IRouter> && router,
m_absentRegionsFinder = std::move(finder);
}
void AsyncRouter::CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & direction,
bool adjustToPrevRoute,
void AsyncRouter::CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & direction, bool adjustToPrevRoute,
std::vector<EdgeEstimator::Strategy> strategies,
ReadyCallbackOwnership const & readyCallback,
NeedMoreMapsCallback const & needMoreMapsCallback,
RemoveRouteCallback const & removeRouteCallback,
@ -175,11 +168,17 @@ void AsyncRouter::CalculateRoute(Checkpoints const & checkpoints, m2::PointD con
ResetDelegate();
m_delegateProxy =
std::make_shared<RouterDelegateProxy>(readyCallback, needMoreMapsCallback, removeRouteCallback,
m_pointCheckCallback, progressCallback, timeoutSec);
for (auto strategy : strategies)
{
// TODO: investigate why make_shared was being problematic; something to do with implicitly
// deleted constructors on RouterDelegateProxy??
m_requestQueue.push(std::shared_ptr<Request>(
new Request{RouterDelegateProxy(readyCallback, needMoreMapsCallback, removeRouteCallback, m_pointCheckCallback,
progressCallback, timeoutSec),
strategy}));
LOG(LINFO, ("Pushed request", static_cast<int>(strategy), m_requestQueue.size()));
}
m_hasRequest = true;
m_threadCondVar.notify_one();
}
@ -204,68 +203,48 @@ void AsyncRouter::LogCode(RouterResultCode code, double const elapsedSec)
{
switch (code)
{
case RouterResultCode::StartPointNotFound:
LOG(LWARNING, ("Can't find start or end node"));
break;
case RouterResultCode::EndPointNotFound:
LOG(LWARNING, ("Can't find end point node"));
break;
case RouterResultCode::PointsInDifferentMWM:
LOG(LWARNING, ("Points are in different MWMs"));
break;
case RouterResultCode::RouteNotFound:
LOG(LWARNING, ("Route not found"));
break;
case RouterResultCode::RouteFileNotExist:
LOG(LWARNING, ("There is no routing file"));
break;
case RouterResultCode::NeedMoreMaps:
LOG(LINFO,
("Routing can find a better way with additional maps, elapsed seconds:", elapsedSec));
break;
case RouterResultCode::Cancelled:
LOG(LINFO, ("Route calculation cancelled, elapsed seconds:", elapsedSec));
break;
case RouterResultCode::NoError:
LOG(LINFO, ("Route found, elapsed seconds:", elapsedSec));
break;
case RouterResultCode::NoCurrentPosition:
LOG(LINFO, ("No current position"));
break;
case RouterResultCode::InconsistentMWMandRoute:
LOG(LINFO, ("Inconsistent mwm and route"));
break;
case RouterResultCode::InternalError:
LOG(LINFO, ("Internal error"));
break;
case RouterResultCode::FileTooOld:
LOG(LINFO, ("File too old"));
break;
case RouterResultCode::IntermediatePointNotFound:
LOG(LWARNING, ("Can't find intermediate point node"));
break;
case RouterResultCode::TransitRouteNotFoundNoNetwork:
LOG(LWARNING, ("No transit route is found because there's no transit network in the mwm of "
"the route point"));
break;
case RouterResultCode::TransitRouteNotFoundTooLongPedestrian:
LOG(LWARNING, ("No transit route is found because pedestrian way is too long"));
break;
case RouterResultCode::RouteNotFoundRedressRouteError:
LOG(LWARNING, ("Route not found because of a redress route error"));
break;
case RouterResultCode::HasWarnings:
LOG(LINFO, ("Route has warnings, elapsed seconds:", elapsedSec));
break;
case RouterResultCode::StartPointNotFound: LOG(LWARNING, ("Can't find start or end node")); break;
case RouterResultCode::EndPointNotFound: LOG(LWARNING, ("Can't find end point node")); break;
case RouterResultCode::PointsInDifferentMWM: LOG(LWARNING, ("Points are in different MWMs")); break;
case RouterResultCode::RouteNotFound: LOG(LWARNING, ("Route not found")); break;
case RouterResultCode::RouteFileNotExist: LOG(LWARNING, ("There is no routing file")); break;
case RouterResultCode::NeedMoreMaps:
LOG(LINFO, ("Routing can find a better way with additional maps, elapsed seconds:", elapsedSec));
break;
case RouterResultCode::Cancelled: LOG(LINFO, ("Route calculation cancelled, elapsed seconds:", elapsedSec)); break;
case RouterResultCode::NoError: LOG(LINFO, ("Route found, elapsed seconds:", elapsedSec)); break;
case RouterResultCode::NoCurrentPosition: LOG(LINFO, ("No current position")); break;
case RouterResultCode::InconsistentMWMandRoute: LOG(LINFO, ("Inconsistent mwm and route")); break;
case RouterResultCode::InternalError: LOG(LINFO, ("Internal error")); break;
case RouterResultCode::FileTooOld: LOG(LINFO, ("File too old")); break;
case RouterResultCode::IntermediatePointNotFound: LOG(LWARNING, ("Can't find intermediate point node")); break;
case RouterResultCode::TransitRouteNotFoundNoNetwork:
LOG(LWARNING, ("No transit route is found because there's no transit network in the mwm of "
"the route point"));
break;
case RouterResultCode::TransitRouteNotFoundTooLongPedestrian:
LOG(LWARNING, ("No transit route is found because pedestrian way is too long"));
break;
case RouterResultCode::RouteNotFoundRedressRouteError:
LOG(LWARNING, ("Route not found because of a redress route error"));
break;
case RouterResultCode::HasWarnings: LOG(LINFO, ("Route has warnings, elapsed seconds:", elapsedSec)); break;
}
}
void AsyncRouter::ResetDelegate()
{
if (m_delegateProxy)
if (m_request)
{
m_delegateProxy->Cancel();
m_delegateProxy.reset();
m_request->m_delegateProxy.Cancel();
m_request.reset();
}
// also have to cancel and clear all queued requests
while (!m_requestQueue.empty())
{
m_requestQueue.front()->m_delegateProxy.Cancel();
m_requestQueue.pop();
}
}
@ -275,7 +254,14 @@ void AsyncRouter::ThreadFunc()
{
{
unique_lock ul(m_guard);
m_threadCondVar.wait(ul, [this](){ return m_threadExit || m_hasRequest || m_clearState; });
LOG(LINFO, ("Waiting for queued request"));
m_threadCondVar.wait(ul,
[this]()
{
LOG(LINFO, ("Testing queued request", m_requestQueue.size()));
return m_threadExit || !m_requestQueue.empty() || m_clearState;
});
if (m_clearState && m_router)
{
@ -286,8 +272,10 @@ void AsyncRouter::ThreadFunc()
if (m_threadExit)
break;
if (!m_hasRequest)
if (m_requestQueue.empty())
continue;
LOG(LINFO, ("CalculateRoute dequeued:", static_cast<int>(m_requestQueue.front()->m_strategy)));
}
CalculateRoute();
@ -297,7 +285,7 @@ void AsyncRouter::ThreadFunc()
void AsyncRouter::CalculateRoute()
{
Checkpoints checkpoints;
std::shared_ptr<RouterDelegateProxy> delegateProxy;
std::shared_ptr<Request> request;
m2::PointD startDirection;
bool adjustToPrevRoute = false;
std::shared_ptr<AbsentRegionsFinder> absentRegionsFinder;
@ -308,21 +296,22 @@ void AsyncRouter::CalculateRoute()
{
unique_lock ul(m_guard);
bool hasRequest = m_hasRequest;
m_hasRequest = false;
bool hasRequest = !m_requestQueue.empty();
if (!hasRequest)
return;
if (!m_router)
return;
if (!m_delegateProxy)
return;
m_request = m_requestQueue.front();
m_requestQueue.pop();
LOG(LINFO, ("CalculateRoute POPPED:", static_cast<int>(m_request->m_strategy), m_requestQueue.size()));
checkpoints = m_checkpoints;
startDirection = m_startDirection;
adjustToPrevRoute = m_adjustToPrevRoute;
delegateProxy = m_delegateProxy;
router = m_router;
absentRegionsFinder = m_absentRegionsFinder;
request = m_request;
routeId = ++m_routeCounter;
routerName = router->GetName();
router->SetGuides(std::move(m_guides));
@ -330,6 +319,7 @@ void AsyncRouter::CalculateRoute()
}
auto route = std::make_shared<Route>(router->GetName(), routeId);
route->SetStrategy(request->m_strategy);
RouterResultCode code;
base::Timer timer;
@ -341,15 +331,20 @@ void AsyncRouter::CalculateRoute()
"m. checkpoints:", checkpoints, "startDirection:", startDirection, "router name:", router->GetName()));
if (absentRegionsFinder)
absentRegionsFinder->GenerateAbsentRegions(checkpoints, delegateProxy->GetDelegate());
absentRegionsFinder->GenerateAbsentRegions(checkpoints, request->m_delegateProxy.GetDelegate());
RoutingOptions const routingOptions = RoutingOptions::LoadCarOptionsFromSettings();
router->SetEstimatorOptions(routingOptions.GetOptions());
router->SetEstimatorStrategy(request->m_strategy);
// Run basic request.
code = router->CalculateRoute(checkpoints, startDirection, adjustToPrevRoute,
delegateProxy->GetDelegate(), *route);
request->m_delegateProxy.GetDelegate(), *route);
router->SetGuides({});
elapsedSec = timer.ElapsedSeconds(); // routing time
elapsedSec = timer.ElapsedSeconds(); // routing time
LogCode(code, elapsedSec);
LOG(LINFO, ("ETA:", route->GetTotalTimeSec(), "sec."));
LOG(LINFO, ("ETA:", route->GetTotalTimeSec(), "sec.", static_cast<int>(request->m_strategy)));
}
catch (RootException const & e)
{
@ -358,7 +353,7 @@ void AsyncRouter::CalculateRoute()
// Note. After call of this method |route| should be used only on ui thread.
// And |route| should stop using on routing background thread, in this method.
GetPlatform().RunTask(Platform::Thread::Gui,
[delegateProxy, route, code]() { delegateProxy->OnReady(route, code); });
[request, route, code]() { request->m_delegateProxy.OnReady(route, code); });
return;
}
@ -368,11 +363,10 @@ void AsyncRouter::CalculateRoute()
// Note. After call of this method |route| should be used only on ui thread.
// And |route| should stop using on routing background thread, in this method.
GetPlatform().RunTask(Platform::Thread::Gui,
[delegateProxy, route, code]() { delegateProxy->OnReady(route, code); });
[request, route, code]() { request->m_delegateProxy.OnReady(route, code); });
}
bool const needAbsentRegions = (code != RouterResultCode::Cancelled &&
route->GetRouterId() != "ruler-router");
bool const needAbsentRegions = (code != RouterResultCode::Cancelled && route->GetRouterId() != "ruler-router");
std::set<std::string> absent;
if (needAbsentRegions)
@ -388,7 +382,7 @@ void AsyncRouter::CalculateRoute()
}
}
elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time
elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time
LogCode(code, elapsedSec);
// Call callback only if we have some new data.
@ -396,14 +390,12 @@ void AsyncRouter::CalculateRoute()
{
if (code == RouterResultCode::NeedMoreMaps)
{
GetPlatform().RunTask(Platform::Thread::Gui, [delegateProxy, routeId, absent]() {
delegateProxy->OnNeedMoreMaps(routeId, absent);
});
GetPlatform().RunTask(Platform::Thread::Gui,
[request, routeId, absent]() { request->m_delegateProxy.OnNeedMoreMaps(routeId, absent); });
}
else
{
GetPlatform().RunTask(Platform::Thread::Gui,
[delegateProxy, code]() { delegateProxy->OnRemoveRoute(code); });
GetPlatform().RunTask(Platform::Thread::Gui, [request, code]() { request->m_delegateProxy.OnRemoveRoute(code); });
}
}
}

View file

@ -7,18 +7,15 @@
#include "routing/router_delegate.hpp"
#include "routing/routing_callbacks.hpp"
#include "platform/platform.hpp"
#include "base/thread.hpp"
#include <condition_variable>
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
#include <queue>
#include <set>
#include <string>
#include <utility>
namespace routing
{
@ -34,8 +31,7 @@ public:
/// Sets a synchronous router, current route calculation will be cancelled
/// @param router pointer to a router implementation
/// @param finder pointer to a router for generated absent wmwms.
void SetRouter(std::unique_ptr<IRouter> && router,
std::unique_ptr<AbsentRegionsFinder> && finder);
void SetRouter(std::unique_ptr<IRouter> && router, std::unique_ptr<AbsentRegionsFinder> && finder);
/// Main method to calculate new route from startPt to finalPt with start direction
/// Processed result will be passed to callback. Callback will be called at the GUI thread.
@ -48,19 +44,18 @@ public:
/// @param timeoutSec timeout to cancel routing. 0 is infinity.
// @TODO(bykoianko) Gather |readyCallback|, |needMoreMapsCallback| and |removeRouteCallback|
// to one delegate. No need to add |progressCallback| to the delegate.
void CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & direction,
bool adjustToPrevRoute, ReadyCallbackOwnership const & readyCallback,
void CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & direction, bool adjustToPrevRoute,
std::vector<EdgeEstimator::Strategy> strategies, ReadyCallbackOwnership const & readyCallback,
NeedMoreMapsCallback const & needMoreMapsCallback,
RemoveRouteCallback const & removeRouteCallback,
ProgressCallback const & progressCallback,
RemoveRouteCallback const & removeRouteCallback, ProgressCallback const & progressCallback,
uint32_t timeoutSec = RouterDelegate::kNoTimeout);
void SetGuidesTracks(GuidesTracks && guides);
/// Interrupt routing and clear buffers
void ClearState();
bool FindClosestProjectionToRoad(m2::PointD const & point, m2::PointD const & direction,
double radius, EdgeProj & proj);
bool FindClosestProjectionToRoad(m2::PointD const & point, m2::PointD const & direction, double radius,
EdgeProj & proj);
private:
/// Worker thread function
@ -75,12 +70,9 @@ private:
class RouterDelegateProxy
{
public:
RouterDelegateProxy(ReadyCallbackOwnership const & onReady,
NeedMoreMapsCallback const & onNeedMoreMaps,
RemoveRouteCallback const & onRemoveRoute,
PointCheckCallback const & onPointCheck,
ProgressCallback const & onProgress,
uint32_t timeoutSec);
RouterDelegateProxy(ReadyCallbackOwnership const & onReady, NeedMoreMapsCallback const & onNeedMoreMaps,
RemoveRouteCallback const & onRemoveRoute, PointCheckCallback const & onPointCheck,
ProgressCallback const & onProgress, uint32_t timeoutSec);
void OnReady(std::shared_ptr<Route> route, RouterResultCode resultCode);
void OnNeedMoreMaps(uint64_t routeId, std::set<std::string> const & absentCounties);
@ -105,6 +97,12 @@ private:
RouterDelegate m_delegate;
};
struct Request
{
RouterDelegateProxy m_delegateProxy;
EdgeEstimator::Strategy m_strategy;
};
private:
std::mutex m_guard;
@ -112,7 +110,6 @@ private:
threads::SimpleThread m_thread;
std::condition_variable m_threadCondVar;
bool m_threadExit;
bool m_hasRequest;
/// Current request parameters
bool m_clearState = false;
@ -121,7 +118,8 @@ private:
m2::PointD m_startDirection = m2::PointD::Zero();
bool m_adjustToPrevRoute = false;
std::shared_ptr<RouterDelegateProxy> m_delegateProxy;
std::shared_ptr<Request> m_request;
std::queue<std::shared_ptr<Request>> m_requestQueue;
std::shared_ptr<AbsentRegionsFinder> m_absentRegionsFinder;
std::shared_ptr<IRouter> m_router;

View file

@ -1,8 +1,11 @@
#include "routing/edge_estimator.hpp"
#include "platform/settings.hpp"
#include "routing/geometry.hpp"
#include "routing/latlon_with_altitude.hpp"
#include "routing/routing_helpers.hpp"
#include "routing/routing_options.hpp"
#include "routing/traffic_stash.hpp"
#include "traffic/speed_groups.hpp"
@ -60,12 +63,15 @@ bool IsTransit(std::optional<HighwayType> type)
}
template <class CalcSpeed>
double CalcClimbSegment(EdgeEstimator::Purpose purpose, Segment const & segment,
RoadGeometry const & road, CalcSpeed && calcSpeed)
double CalcClimbSegment(EdgeEstimator::Purpose purpose, EdgeEstimator::Strategy strategy,
Segment const & segment, RoadGeometry const & road, CalcSpeed && calcSpeed)
{
double const distance = road.GetDistance(segment.GetSegmentIdx());
double speedMpS = GetSpeedMpS(purpose, segment, road);
if (strategy == EdgeEstimator::Strategy::Shortest && purpose == EdgeEstimator::Purpose::Weight)
speedMpS = 1.0;
static double constexpr kSmallDistanceM = 1; // we have altitude threshold is 0.5m
if (distance > kSmallDistanceM && !IsTransit(road.GetHighwayType()))
{
@ -167,6 +173,26 @@ double GetCarClimbPenalty(EdgeEstimator::Purpose, double, geometry::Altitude)
}
// EdgeEstimator -----------------------------------------------------------------------------------
string const EdgeEstimator::kRoutingStrategySettings = "router_strategy";
// static
EdgeEstimator::Strategy EdgeEstimator::LoadRoutingStrategyFromSettings()
{
int mode = 0;
if (!settings::Get(kRoutingStrategySettings, mode))
mode = 0;
return (EdgeEstimator::Strategy) mode;
}
// static
void EdgeEstimator::SaveRoutingStrategyToSettings(Strategy strategy)
{
settings::Set(kRoutingStrategySettings,
strings::to_string(static_cast<int>(strategy)));
}
EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
DataSource * /*dataSourcePtr*/, std::shared_ptr<NumMwmIds> /*numMwmIds*/)
: m_maxWeightSpeedMpS(KmphToMps(maxWeightSpeedKMpH))
@ -180,6 +206,9 @@ EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroa
if (m_offroadSpeedKMpH.m_eta != kNotUsed)
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_eta), ());
m_avoidRoutingOptions = RoutingOptions();
m_strategy = EdgeEstimator::Strategy::Fastest;
}
double EdgeEstimator::CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const
@ -260,6 +289,26 @@ double EdgeEstimator::CalcOffroad(ms::LatLon const & from, ms::LatLon const & to
return TimeBetweenSec(from, to, KmphToMps(offroadSpeedKMpH));
}
RoutingOptions EdgeEstimator::GetAvoidRoutingOptions() const
{
return m_avoidRoutingOptions;
}
void EdgeEstimator::SetAvoidRoutingOptions(RoutingOptions::RoadType options)
{
m_avoidRoutingOptions.SetOptions(options);
}
EdgeEstimator::Strategy EdgeEstimator::GetStrategy() const
{
return m_strategy;
}
void EdgeEstimator::SetStrategy(EdgeEstimator::Strategy strategy)
{
m_strategy = strategy;
}
// PedestrianEstimator -----------------------------------------------------------------------------
class PedestrianEstimator final : public EdgeEstimator
{
@ -270,7 +319,20 @@ public:
}
// EdgeEstimator overrides:
double GetUTurnPenalty(Purpose /* purpose */) const override { return 0.0 /* seconds */; }
double GetUTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
return 60 * 60;
return 0.0;
}
double GetTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
return 60 * 60;
return 0.0;
}
double GetFerryLandingPenalty(Purpose purpose) const override
{
switch (purpose)
@ -283,11 +345,16 @@ public:
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
{
return CalcClimbSegment(purpose, segment, road,
double result = CalcClimbSegment(purpose, GetStrategy(), segment, road,
[purpose](double speedMpS, double tangent, geometry::Altitude altitude)
{
return speedMpS / GetPedestrianClimbPenalty(purpose, tangent, altitude);
});
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
result += (24 * 60 * 60);
return result;
}
};
@ -301,7 +368,20 @@ public:
}
// EdgeEstimator overrides:
double GetUTurnPenalty(Purpose /* purpose */) const override { return 20.0 /* seconds */; }
double GetUTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
return 60 * 60;
return 20.0;
}
double GetTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
return 60 * 60;
return 0.0;
}
double GetFerryLandingPenalty(Purpose purpose) const override
{
switch (purpose)
@ -314,7 +394,7 @@ public:
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override
{
return CalcClimbSegment(purpose, segment, road,
double result = CalcClimbSegment(purpose, GetStrategy(), segment, road,
[purpose, this](double speedMpS, double tangent, geometry::Altitude altitude)
{
auto const factor = GetBicycleClimbPenalty(purpose, tangent, altitude);
@ -347,6 +427,12 @@ public:
return std::min(speedMpS, GetMaxWeightSpeedMpS());
});
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
result += (24 * 60 * 60);
return result;
}
};
@ -364,14 +450,24 @@ public:
// EdgeEstimator overrides:
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override;
double GetUTurnPenalty(Purpose /* purpose */) const override
double GetUTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight && GetStrategy() == EdgeEstimator::Strategy::FewerTurns)
return 60 * 60;
// Adds 2 minutes penalty for U-turn. The value is quite arbitrary
// and needs to be properly selected after a number of real-world
// experiments.
return 2 * 60; // seconds
}
double GetTurnPenalty(Purpose purpose) const override
{
if (purpose == EdgeEstimator::Purpose::Weight)
return 60 * 60;
return 0;
}
double GetFerryLandingPenalty(Purpose purpose) const override
{
switch (purpose)
@ -390,6 +486,9 @@ double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry con
{
double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road);
if (purpose == EdgeEstimator::Purpose::Weight && !road.SuitableForOptions(EdgeEstimator::GetAvoidRoutingOptions()))
result += (24 * 60 * 60);
if (m_trafficStash)
{
SpeedGroup const speedGroup = m_trafficStash->GetSpeedGroup(segment);

View file

@ -1,5 +1,6 @@
#pragma once
#include "routing/routing_options.hpp"
#include "routing/segment.hpp"
#include "routing/vehicle_mask.hpp"
@ -27,10 +28,22 @@ public:
ETA
};
static std::string const kRoutingStrategySettings;
enum class Strategy
{
Fastest,
Shortest,
FewerTurns
};
EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
DataSource * dataSourcePtr = nullptr, std::shared_ptr<NumMwmIds> numMwmIds = nullptr);
virtual ~EdgeEstimator() = default;
static Strategy LoadRoutingStrategyFromSettings();
static void SaveRoutingStrategyToSettings(Strategy strategy);
double CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const;
// Estimates time in seconds it takes to go from point |from| to point |to| along a leap (fake)
// edge |from|-|to| using real features.
@ -45,9 +58,16 @@ public:
// Estimates time in seconds it takes to go from point |from| to point |to| along direct fake edge.
double CalcOffroad(ms::LatLon const & from, ms::LatLon const & to, Purpose purpose) const;
RoutingOptions GetAvoidRoutingOptions() const;
void SetAvoidRoutingOptions(RoutingOptions::RoadType options);
Strategy GetStrategy() const;
void SetStrategy(Strategy strategy);
virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road,
Purpose purpose) const = 0;
virtual double GetUTurnPenalty(Purpose purpose) const = 0;
virtual double GetTurnPenalty(Purpose purpose) const = 0;
virtual double GetFerryLandingPenalty(Purpose purpose) const = 0;
static std::shared_ptr<EdgeEstimator> Create(VehicleType vehicleType, double maxWeighSpeedKMpH,
@ -65,6 +85,8 @@ public:
private:
double const m_maxWeightSpeedMpS;
SpeedKMpH const m_offroadSpeedKMpH;
RoutingOptions m_avoidRoutingOptions;
Strategy m_strategy;
//DataSource * m_dataSourcePtr;
//std::shared_ptr<NumMwmIds> m_numMwmIds;

View file

@ -12,6 +12,7 @@
#include "base/timer.hpp"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iterator>
#include <limits>
@ -254,8 +255,8 @@ void IndexGraph::GetNeighboringEdges(astar::VertexData<Segment, RouteWeight> con
if (!road.IsValid())
return;
if (useRoutingOptions && !road.SuitableForOptions(m_avoidRoutingOptions))
return;
// if (useRoutingOptions && !road.SuitableForOptions(m_avoidRoutingOptions))
// return;
bool const bidirectional = !road.IsOneWay();
auto const & from = fromVertexData.m_vertex;
@ -282,8 +283,8 @@ void IndexGraph::GetSegmentCandidateForRoadPoint(RoadPoint const & rp, NumMwmId
if (!road.IsValid())
return;
if (!road.SuitableForOptions(m_avoidRoutingOptions))
return;
// if (!road.SuitableForOptions(m_avoidRoutingOptions))
// return;
bool const bidirectional = !road.IsOneWay();
auto const pointId = rp.GetPointId();
@ -514,6 +515,9 @@ RouteWeight IndexGraph::GetPenalties(EdgeEstimator::Purpose purpose, Segment con
if (IsUTurn(u, v))
weightPenalty += m_estimator->GetUTurnPenalty(purpose);
if (IsTurn(u, v))
weightPenalty += m_estimator->GetTurnPenalty(purpose);
if (IsBoarding(fromPenaltyData.m_isFerry, toPenaltyData.m_isFerry))
weightPenalty += m_estimator->GetFerryLandingPenalty(purpose);
@ -549,6 +553,57 @@ bool IndexGraph::IsUTurnAndRestricted(Segment const & parent, Segment const & ch
return uTurn.m_atTheEnd && turnPoint == n - 1;
}
bool IndexGraph::IsTurn(Segment const & u, Segment const & v) const
{
// Boundary check for segmentIdx
if (u.GetSegmentIdx() == 0 && !(u.IsForward()))
{
return false;
}
if (v.GetSegmentIdx() == 0 && !(v.IsForward()))
{
return false;
}
auto geoU = GetRoadGeometry(u.GetFeatureId());
auto startPointU = geoU.GetPoint(u.GetSegmentIdx());
auto endPointU = geoU.GetPoint(u.IsForward() ? u.GetSegmentIdx() + 1: u.GetSegmentIdx() - 1);
auto geoV = GetRoadGeometry(v.GetFeatureId());
auto startPointV = geoV.GetPoint(v.GetSegmentIdx());
auto endPointV = geoV.GetPoint(v.IsForward() ? v.GetSegmentIdx() + 1: v.GetSegmentIdx() - 1);
if (!(endPointU == startPointV))
{
return false;
}
double vectorU[2] = {endPointU.m_lat - startPointU.m_lat, endPointU.m_lon - startPointU.m_lon};
double vectorV[2] = {endPointV.m_lat - startPointV.m_lat, endPointV.m_lon - startPointV.m_lon};
//dot product
double dot = vectorU[0] * vectorV[0] + vectorU[1] * vectorV[1];
//determinant
double det = vectorU[0] * vectorV[1] - vectorU[1] * vectorV[0];
//calculate the anlge
double angle = atan2(det, dot);
//convert to degree value
angle = angle * 180 / 3.141592;
if (abs(angle) >= 15)
{
return true;
}
else
{
return false;
}
}
RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool isOutgoing,
Segment const & from, Segment const & to,
std::optional<RouteWeight const> const & prevWeight) const
@ -556,7 +611,18 @@ RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool
auto const & segment = isOutgoing ? to : from;
auto const & road = GetRoadGeometry(segment.GetFeatureId());
// m_estimator->SetAvoidRoutingOptions(this->m_avoidRoutingOptions.GetOptions());
auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(segment, road, purpose));
if (purpose == EdgeEstimator::Purpose::Weight)
{
if(m_estimator->GetStrategy() == EdgeEstimator::Strategy::Shortest)
{
return weight;
}
}
auto const penalties = GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight);
return weight + penalties;

View file

@ -133,6 +133,8 @@ public:
bool IsUTurnAndRestricted(Segment const & parent, Segment const & child, bool isOutgoing) const;
bool IsTurn(Segment const & u, Segment const & v) const;
/// @param[in] isOutgoing true, when movig from -> to, false otherwise.
/// @param[in] prevWeight used for fetching access:conditional.
/// I suppose :) its time when user will be at the end of |from| (|to| if \a isOutgoing == false) segment.

View file

@ -326,6 +326,10 @@ bool IndexRouter::FindClosestProjectionToRoad(m2::PointD const & point,
return true;
}
void IndexRouter::SetEstimatorOptions(RoutingOptions::RoadType options) {m_estimator ->SetAvoidRoutingOptions(options);}
void IndexRouter::SetEstimatorStrategy(EdgeEstimator::Strategy strategy) {m_estimator ->SetStrategy(strategy);}
void IndexRouter::SetGuides(GuidesTracks && guides) { m_guides = GuidesConnections(guides); }
RouterResultCode IndexRouter::CalculateRoute(Checkpoints const & checkpoints,

View file

@ -14,6 +14,7 @@
#include "routing/regions_decl.hpp"
#include "routing/router.hpp"
#include "routing/routing_callbacks.hpp"
#include "routing/routing_options.hpp"
#include "routing/segment.hpp"
#include "routing/segmented_route.hpp"
@ -77,6 +78,10 @@ public:
std::string GetName() const override { return m_name; }
void ClearState() override;
void SetEstimatorOptions(RoutingOptions::RoadType options) override;
void SetEstimatorStrategy(EdgeEstimator::Strategy strategy) override;
void SetGuides(GuidesTracks && guides) override;
RouterResultCode CalculateRoute(Checkpoints const & checkpoints,
m2::PointD const & startDirection, bool adjustToPrevRoute,

View file

@ -4,6 +4,7 @@
#include "routing/checkpoints.hpp"
#include "routing/regions_decl.hpp"
#include "routing/router_delegate.hpp"
#include "routing/segment.hpp"
#include "base/thread.hpp"

View file

@ -2,11 +2,10 @@
#include "traffic/speed_groups.hpp"
#include "geometry/mercator.hpp"
#include "platform/location.hpp"
#include "geometry/angles.hpp"
#include "geometry/mercator.hpp"
#include "geometry/point2d.hpp"
#include <algorithm>
@ -25,14 +24,9 @@ double constexpr kSteetNameLinkMeters = 400.0;
std::string DebugPrint(RouteSegment::RoadNameInfo const & rni)
{
stringstream out;
out << "RoadNameInfo "
<< "{ m_name = " << rni.m_name
<< ", m_ref = " << rni.m_ref
<< ", m_junction_ref = " << rni.m_junction_ref
<< ", m_destination_ref = " << rni.m_destination_ref
<< ", m_destination = " << rni.m_destination
<< ", m_isLink = " << rni.m_isLink
<< " }";
out << "RoadNameInfo " << "{ m_name = " << rni.m_name << ", m_ref = " << rni.m_ref
<< ", m_junction_ref = " << rni.m_junction_ref << ", m_destination_ref = " << rni.m_destination_ref
<< ", m_destination = " << rni.m_destination << ", m_isLink = " << rni.m_isLink << " }";
return out.str();
}
@ -41,9 +35,7 @@ std::string DebugPrint(RouteSegment::SpeedCamera const & rhs)
return "SpeedCamera{ " + std::to_string(rhs.m_coef) + ", " + std::to_string(int(rhs.m_maxSpeedKmPH)) + " }";
}
Route::Route(string const & router, vector<m2::PointD> const & points, uint64_t routeId,
string const & name)
Route::Route(string const & router, vector<m2::PointD> const & points, uint64_t routeId, string const & name)
: m_router(router)
, m_routingSettings(GetRoutingSettings(VehicleType::Car))
, m_name(name)
@ -87,8 +79,7 @@ double Route::GetMercatorDistanceFromBegin() const
CHECK_LESS(curIter.m_ind, m_routeSegments.size(), ());
double const distMerc =
curIter.m_ind == 0 ? 0.0 : m_routeSegments[curIter.m_ind - 1].GetDistFromBeginningMerc();
double const distMerc = curIter.m_ind == 0 ? 0.0 : m_routeSegments[curIter.m_ind - 1].GetDistFromBeginningMerc();
return distMerc + m_poly.GetDistFromCurPointToRoutePointMerc();
}
@ -97,10 +88,7 @@ double Route::GetTotalTimeSec() const
return m_routeSegments.empty() ? 0 : m_routeSegments.back().GetTimeFromBeginningSec();
}
double Route::GetCurrentTimeToEndSec() const
{
return GetCurrentTimeToSegmentSec(m_routeSegments.size() - 1);
}
double Route::GetCurrentTimeToEndSec() const { return GetCurrentTimeToSegmentSec(m_routeSegments.size() - 1); }
double Route::GetCurrentTimeToNearestTurnSec() const
{
@ -136,7 +124,8 @@ double Route::GetCurrentTimeFromBeginSec() const
auto const & curIter = m_poly.GetCurrentIter();
CHECK_LESS(curIter.m_ind, m_routeSegments.size(), ());
double const toLastPointSec = (curIter.m_ind == 0) ? 0.0 : m_routeSegments[curIter.m_ind - 1].GetTimeFromBeginningSec();
double const toLastPointSec =
(curIter.m_ind == 0) ? 0.0 : m_routeSegments[curIter.m_ind - 1].GetTimeFromBeginningSec();
double const toNextPointSec = m_routeSegments[curIter.m_ind].GetTimeFromBeginningSec();
double const curSegLenMeters = GetSegLenMeters(curIter.m_ind);
@ -288,8 +277,7 @@ void Route::GetNearestTurn(double & distanceToTurnMeters, TurnItem & turn) const
GetClosestTurnAfterIdx(m_poly.GetCurrentIter().m_ind, turn);
CHECK_LESS(m_poly.GetCurrentIter().m_ind, turn.m_index, ());
distanceToTurnMeters = m_poly.GetDistanceM(m_poly.GetCurrentIter(),
m_poly.GetIterToIndex(turn.m_index));
distanceToTurnMeters = m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(turn.m_index));
}
optional<turns::TurnItem> Route::GetCurrentIteratorTurn() const
@ -326,8 +314,7 @@ bool Route::GetNextTurn(double & distanceToTurnMeters, TurnItem & nextTurn) cons
CHECK_LESS(curTurn.m_index, m_routeSegments.size(), ());
GetClosestTurnAfterIdx(curTurn.m_index, nextTurn);
CHECK_LESS(curTurn.m_index, nextTurn.m_index, ());
distanceToTurnMeters = m_poly.GetDistanceM(m_poly.GetCurrentIter(),
m_poly.GetIterToIndex(nextTurn.m_index));
distanceToTurnMeters = m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(nextTurn.m_index));
return true;
}
@ -345,10 +332,7 @@ bool Route::GetNextTurns(vector<TurnItemDist> & turns) const
return true;
}
void Route::GetCurrentDirectionPoint(m2::PointD & pt) const
{
m_poly.GetCurrentDirectionPoint(pt, kOnEndToleranceM);
}
void Route::GetCurrentDirectionPoint(m2::PointD & pt) const { m_poly.GetCurrentDirectionPoint(pt, kOnEndToleranceM); }
void Route::SetRouteSegments(vector<RouteSegment> && routeSegments)
{
@ -357,8 +341,7 @@ void Route::SetRouteSegments(vector<RouteSegment> && routeSegments)
m_haveAltitudes = true;
for (size_t i = 0; i < m_routeSegments.size(); ++i)
{
if (m_haveAltitudes &&
m_routeSegments[i].GetJunction().GetAltitude() == geometry::kInvalidAltitude)
if (m_haveAltitudes && m_routeSegments[i].GetJunction().GetAltitude() == geometry::kInvalidAltitude)
{
m_haveAltitudes = false;
}
@ -372,9 +355,8 @@ void Route::SetRouteSegments(vector<RouteSegment> && routeSegments)
bool Route::MoveIterator(location::GpsInfo const & info)
{
m2::RectD const rect = mercator::MetersToXY(
info.m_longitude, info.m_latitude,
max(m_routingSettings.m_matchingThresholdM, info.m_horizontalAccuracy));
m2::RectD const rect = mercator::MetersToXY(info.m_longitude, info.m_latitude,
max(m_routingSettings.m_matchingThresholdM, info.m_horizontalAccuracy));
return m_poly.UpdateMatchingProjection(rect);
}
@ -395,13 +377,11 @@ double Route::GetPolySegAngle(size_t ind) const
do
{
p2 = m_poly.GetPolyline().GetPoint(i);
}
while (m2::AlmostEqualULPs(p1, p2) && ++i < polySz);
} while (m2::AlmostEqualULPs(p1, p2) && ++i < polySz);
return (i == polySz) ? 0 : base::RadToDeg(ang::AngleTo(p1, p2));
}
bool Route::MatchLocationToRoute(location::GpsInfo & location,
location::RouteMatchingInfo & routeMatchingInfo) const
bool Route::MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const
{
if (!IsValid())
return false;
@ -463,9 +443,8 @@ bool Route::IsSubroutePassed(size_t subrouteIdx) const
CHECK_LESS(segmentIdx, m_routeSegments.size(), ());
double const lengthMeters = m_routeSegments[segmentIdx].GetDistFromBeginningMeters();
double const passedDistanceMeters = m_poly.GetDistanceFromStartMeters();
double const finishToleranceM = segmentIdx == m_routeSegments.size() - 1
? m_routingSettings.m_finishToleranceM
: kOnEndToleranceM;
double const finishToleranceM =
segmentIdx == m_routeSegments.size() - 1 ? m_routingSettings.m_finishToleranceM : kOnEndToleranceM;
return lengthMeters - passedDistanceMeters < finishToleranceM;
}
@ -514,10 +493,7 @@ void Route::SetMwmsPartlyProhibitedForSpeedCams(vector<platform::CountryFile> &&
m_speedCamPartlyProhibitedMwms = std::move(mwms);
}
bool Route::CrossMwmsPartlyProhibitedForSpeedCams() const
{
return !m_speedCamPartlyProhibitedMwms.empty();
}
bool Route::CrossMwmsPartlyProhibitedForSpeedCams() const { return !m_speedCamPartlyProhibitedMwms.empty(); }
vector<platform::CountryFile> const & Route::GetMwmsPartlyProhibitedForSpeedCams() const
{
@ -551,6 +527,13 @@ std::string Route::DebugPrintTurns() const
return res;
}
std::shared_ptr<const Route> Routes::GetRoute(EdgeEstimator::Strategy strategy) { return *m_routes.Find(strategy); }
void Routes::SetRoute(EdgeEstimator::Strategy strategy, std::shared_ptr<Route> route)
{
m_routes.Insert(strategy, route);
}
bool IsNormalTurn(TurnItem const & turn)
{
CHECK_NOT_EQUAL(turn.m_turn, CarDirection::Count, ());
@ -559,8 +542,5 @@ bool IsNormalTurn(TurnItem const & turn)
return !turn.IsTurnNone();
}
string DebugPrint(Route const & r)
{
return DebugPrint(r.m_poly.GetPolyline());
}
} // namespace routing
string DebugPrint(Route const & r) { return DebugPrint(r.m_poly.GetPolyline()); }
} // namespace routing

View file

@ -1,17 +1,17 @@
#pragma once
#include "routing/base/followed_polyline.hpp"
#include "routing/edge_estimator.hpp"
#include "routing/routing_options.hpp"
#include "routing/routing_settings.hpp"
#include "routing/segment.hpp"
#include "routing/transit_info.hpp"
#include "routing/turns.hpp"
#include "routing/base/followed_polyline.hpp"
#include "traffic/speed_groups.hpp"
#include "routing_common/maxspeed_conversion.hpp"
#include "traffic/speed_groups.hpp"
#include "platform/country_file.hpp"
#include "geometry/point_with_altitude.hpp"
@ -19,6 +19,7 @@
#include "base/assert.hpp"
#include "base/math.hpp"
#include "base/small_map.hpp"
#include <limits>
#include <memory>
@ -29,9 +30,9 @@
namespace location
{
class GpsInfo;
class RouteMatchingInfo;
}
class GpsInfo;
class RouteMatchingInfo;
} // namespace location
namespace routing
{
@ -46,12 +47,9 @@ public:
struct SpeedCamera
{
SpeedCamera() = default;
SpeedCamera(double coef, uint8_t maxSpeedKmPH): m_coef(coef), m_maxSpeedKmPH(maxSpeedKmPH) {}
SpeedCamera(double coef, uint8_t maxSpeedKmPH) : m_coef(coef), m_maxSpeedKmPH(maxSpeedKmPH) {}
bool EqualCoef(SpeedCamera const & rhs) const
{
return base::AlmostEqualAbs(m_coef, rhs.m_coef, 1.0E-5);
}
bool EqualCoef(SpeedCamera const & rhs) const { return base::AlmostEqualAbs(m_coef, rhs.m_coef, 1.0E-5); }
bool operator<(SpeedCamera const & rhs) const
{
@ -78,9 +76,9 @@ public:
std::string m_destination_ref; // Number of next road, e.g. "CA 85", Sometimes "CA 85 South". Usually match |m_ref|
// of next main road.
// This is for 1st segment of link after junction. Exit |junction_ref| to |m_destination_ref| for |m_destination|.
std::string m_junction_ref; // Number of junction e.g. "398B".
std::string m_destination; // E.g. "Cupertino".
std::string m_ref; // Number of street/road e.g. "CA 85".
std::string m_junction_ref; // Number of junction e.g. "398B".
std::string m_destination; // E.g. "Cupertino".
std::string m_ref; // Number of street/road e.g. "CA 85".
bool m_isLink = false;
RoadNameInfo() = default;
@ -125,13 +123,9 @@ public:
friend std::string DebugPrint(RoadNameInfo const & rni);
};
RouteSegment(Segment const & segment, turns::TurnItem const & turn,
geometry::PointWithAltitude const & junction, RoadNameInfo const & roadNameInfo)
: m_segment(segment)
, m_turn(turn)
, m_junction(junction)
, m_roadNameInfo(roadNameInfo)
, m_transitInfo(nullptr)
RouteSegment(Segment const & segment, turns::TurnItem const & turn, geometry::PointWithAltitude const & junction,
RoadNameInfo const & roadNameInfo)
: m_segment(segment), m_turn(turn), m_junction(junction), m_roadNameInfo(roadNameInfo), m_transitInfo(nullptr)
{
}
@ -152,10 +146,7 @@ public:
m_timeFromBeginningS = timeFromBeginningS;
}
void SetTransitInfo(std::unique_ptr<TransitInfo> transitInfo)
{
m_transitInfo.Set(std::move(transitInfo));
}
void SetTransitInfo(std::unique_ptr<TransitInfo> transitInfo) { m_transitInfo.Set(std::move(transitInfo)); }
Segment const & GetSegment() const { return m_segment; }
Segment & GetSegment() { return m_segment; }
@ -231,13 +222,9 @@ public:
public:
SubrouteAttrs() = default;
SubrouteAttrs(geometry::PointWithAltitude const & start,
geometry::PointWithAltitude const & finish, size_t beginSegmentIdx,
size_t endSegmentIdx)
: m_start(start)
, m_finish(finish)
, m_beginSegmentIdx(beginSegmentIdx)
, m_endSegmentIdx(endSegmentIdx)
SubrouteAttrs(geometry::PointWithAltitude const & start, geometry::PointWithAltitude const & finish,
size_t beginSegmentIdx, size_t endSegmentIdx)
: m_start(start), m_finish(finish), m_beginSegmentIdx(beginSegmentIdx), m_endSegmentIdx(endSegmentIdx)
{
CHECK_LESS_OR_EQUAL(beginSegmentIdx, endSegmentIdx, ());
}
@ -272,8 +259,7 @@ public:
/// \brief For every subroute some attributes are kept in the following structure.
struct SubrouteSettings final
{
SubrouteSettings(RoutingSettings const & routingSettings, std::string const & router,
SubrouteUid id)
SubrouteSettings(RoutingSettings const & routingSettings, std::string const & router, SubrouteUid id)
: m_routingSettings(routingSettings), m_router(router), m_id(id)
{
}
@ -292,17 +278,15 @@ public:
template <class TIter>
Route(std::string const & router, TIter beg, TIter end, uint64_t routeId)
: m_router(router)
, m_routingSettings(GetRoutingSettings(VehicleType::Car))
, m_poly(beg, end)
, m_routeId(routeId)
: m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)), m_poly(beg, end), m_routeId(routeId)
{
}
Route(std::string const & router, std::vector<m2::PointD> const & points, uint64_t routeId,
std::string const & name = std::string());
template <class TIter> void SetGeometry(TIter beg, TIter end)
template <class TIter>
void SetGeometry(TIter beg, TIter end)
{
if (beg == end)
{
@ -327,6 +311,8 @@ public:
std::vector<RouteSegment> const & GetRouteSegments() const { return m_routeSegments; }
RoutingSettings const & GetCurrentRoutingSettings() const { return m_routingSettings; }
std::optional<EdgeEstimator::Strategy> GetStrategy() const { return m_strategy; }
void SetCurrentSubrouteIdx(size_t currentSubrouteIdx) { m_currentSubrouteIdx = currentSubrouteIdx; }
template <class V>
@ -410,8 +396,7 @@ public:
/// \brief Finds projection of |location| to the nearest route and sets |routeMatchingInfo|.
/// fields accordingly.
bool MatchLocationToRoute(location::GpsInfo & location,
location::RouteMatchingInfo & routeMatchingInfo) const;
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const;
/// Add country name if we have no country filename to make route.
void AddAbsentCountry(std::string const & name);
@ -419,10 +404,9 @@ public:
/// Get absent file list of a routing files for shortest path finding.
std::set<std::string> const & GetAbsentCountries() const { return m_absentCountries; }
inline void SetRoutingSettings(RoutingSettings const & routingSettings)
{
m_routingSettings = routingSettings;
}
inline void SetRoutingSettings(RoutingSettings const & routingSettings) { m_routingSettings = routingSettings; }
inline void SetStrategy(EdgeEstimator::Strategy strategy) { m_strategy = strategy; }
// Subroute interface.
/// \returns Number of subroutes.
@ -486,6 +470,7 @@ private:
double GetCurrentTimeFromBeginSec() const;
std::string m_router;
std::optional<EdgeEstimator::Strategy> m_strategy;
RoutingSettings m_routingSettings;
std::string m_name;
@ -507,7 +492,27 @@ private:
std::vector<platform::CountryFile> m_speedCamPartlyProhibitedMwms;
};
class Routes
{
public:
// should this just be a regular const ref?
std::shared_ptr<const Route> GetRoute(EdgeEstimator::Strategy strategy);
void SetRoute(EdgeEstimator::Strategy strategy, std::shared_ptr<Route> route);
private:
base::SmallMapBase<EdgeEstimator::Strategy, std::shared_ptr<Route>> m_routes;
};
// NOTE: Should strategy just be included into Route, and avoid having this extra struct
// or is this separation fine? If it is, then perhaps the name could be simplified to avoid such
// verbosity. Or maybe use inheritance?
// struct RouteWithStrategy
// {
// std::shared_ptr<Route> m_route;
// EdgeEstimator::Strategy m_strategy;
// };
/// \returns true if |turn| is not equal to turns::CarDirection::None or
/// |turns::PedestrianDirection::None|.
bool IsNormalTurn(turns::TurnItem const & turn);
} // namespace routing
} // namespace routing

View file

@ -1,9 +1,11 @@
#pragma once
#include "routing/checkpoints.hpp"
#include "routing/edge_estimator.hpp"
#include "routing/road_graph.hpp"
#include "routing/router_delegate.hpp"
#include "routing/routing_callbacks.hpp"
#include "routing/routing_options.hpp"
#include "kml/type_utils.hpp"
@ -62,6 +64,10 @@ public:
/// Clear all temporary buffers.
virtual void ClearState() {}
virtual void SetEstimatorOptions(RoutingOptions::RoadType options) {}
virtual void SetEstimatorStrategy(EdgeEstimator::Strategy strategy) {}
virtual void SetGuides(GuidesTracks && guides) = 0;
/// Override this function with routing implementation.

View file

@ -1,7 +1,5 @@
#pragma once
#include "routing/turns.hpp"
#include "geometry/latlon.hpp"
#include "geometry/point2d.hpp"
@ -9,7 +7,6 @@
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
@ -45,16 +42,16 @@ enum class RouterResultCode
enum class SessionState
{
NoValidRoute, // No valid route: no route after application launching or the route was removed.
RouteBuilding, // We requested a route and wait when it will be built. User may be following
// the previous route.
RouteNotStarted, // Route is built but the user isn't on it.
OnRoute, // User follows the route.
RouteNeedRebuild, // User left the route.
RouteFinished, // Destination point is reached but the session isn't closed.
RouteNoFollowing, // Route is built but following mode has been disabled.
RouteRebuilding, // We requested a route rebuild and wait when it will be rebuilt.
// User may following the previous route.
NoValidRoute, // No valid route: no route after application launching or the route was removed.
RouteBuilding, // We requested a route and wait when it will be built. User may be following
// the previous route.
RouteNotStarted, // Route is built but the user isn't on it.
OnRoute, // User follows the route.
RouteNeedRebuild, // User left the route.
RouteFinished, // Destination point is reached but the session isn't closed.
RouteNoFollowing, // Route is built but following mode has been disabled.
RouteRebuilding, // We requested a route rebuild and wait when it will be rebuilt.
// User may following the previous route.
};
/*
@ -113,10 +110,7 @@ inline std::string ToString(RouterResultCode code)
return result;
}
inline std::string DebugPrint(RouterResultCode code)
{
return ToString(code);
}
inline std::string DebugPrint(RouterResultCode code) { return ToString(code); }
// This define should be set to see the spread of A* waves on the map.
// #define SHOW_ROUTE_DEBUG_MARKS

View file

@ -50,6 +50,11 @@ bool RoutingOptions::Has(RoutingOptions::Road type) const
return (m_options & static_cast<RoadType>(type)) != 0;
}
void RoutingOptions::SetOptions(RoadType options)
{
m_options = options;
}
// RoutingOptionsClassifier ---------------------------------------------------------------------------
RoutingOptionsClassifier::RoutingOptionsClassifier()

View file

@ -37,6 +37,7 @@ public:
bool Has(Road type) const;
RoadType GetOptions() const { return m_options; }
void SetOptions(RoadType options);
private:
RoadType m_options = 0;

View file

@ -1,18 +1,15 @@
#include "routing/routing_session.hpp"
#include "routing/routing_helpers.hpp"
#include "routing/speed_camera.hpp"
#include "indexer/road_shields_parser.hpp"
#include "platform/distance.hpp"
#include "platform/location.hpp"
#include "platform/measurement_utils.hpp"
#include "platform/platform.hpp"
#include "platform/distance.hpp"
#include "geometry/angles.hpp"
#include "geometry/mercator.hpp"
#include "indexer/road_shields_parser.hpp"
#include <utility>
namespace
@ -45,7 +42,7 @@ void FormatDistance(double dist, std::string & value, std::string & suffix)
RoutingSession::RoutingSession()
: m_router(nullptr)
, m_route(std::make_shared<Route>(std::string{} /* router */, 0 /* route id */))
, m_active_route(std::make_shared<Route>(std::string{} /* router */, 0 /* route id */))
, m_state(SessionState::NoValidRoute)
, m_isFollowing(false)
, m_speedCameraManager(m_turnNotificationsMgr)
@ -55,7 +52,7 @@ RoutingSession::RoutingSession()
{
// To call |m_changeSessionStateCallback| on |m_state| initialization.
SetState(SessionState::NoValidRoute);
m_speedCameraManager.SetRoute(m_route);
m_speedCameraManager.SetRoute(m_active_route);
}
void RoutingSession::Init(PointCheckCallback const & pointCheckCallback)
@ -73,35 +70,34 @@ void RoutingSession::BuildRoute(Checkpoints const & checkpoints, uint32_t timeou
m_router->ClearState();
m_isFollowing = false;
m_routingRebuildCount = -1; // -1 for the first rebuild.
m_routingRebuildCount = -1; // -1 for the first rebuild.
RebuildRoute(checkpoints.GetStart(), m_buildReadyCallback, m_needMoreMapsCallback,
m_removeRouteCallback, timeoutSec, SessionState::RouteBuilding, false /* adjust */);
RebuildRoute(checkpoints.GetStart(), m_buildReadyCallback, m_needMoreMapsCallback, m_removeRouteCallback, timeoutSec,
SessionState::RouteBuilding, false /* adjust */);
}
void RoutingSession::RebuildRoute(m2::PointD const & startPoint,
ReadyCallback const & readyCallback,
void RoutingSession::RebuildRoute(m2::PointD const & startPoint, ReadyCallback const & readyCallback,
NeedMoreMapsCallback const & needMoreMapsCallback,
RemoveRouteCallback const & removeRouteCallback,
uint32_t timeoutSec, SessionState routeRebuildingState,
bool adjustToPrevRoute)
RemoveRouteCallback const & removeRouteCallback, uint32_t timeoutSec,
SessionState routeRebuildingState, bool adjustToPrevRoute)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
CHECK(m_router, ());
SetState(routeRebuildingState);
++m_routingRebuildCount;
auto const & direction = m_routingSettings.m_useDirectionForRouteBuilding
? m_positionAccumulator.GetDirection()
: m2::PointD::Zero();
auto const & direction =
m_routingSettings.m_useDirectionForRouteBuilding ? m_positionAccumulator.GetDirection() : m2::PointD::Zero();
Checkpoints checkpoints(m_checkpoints);
checkpoints.SetPointFrom(startPoint);
// NOTE: purposefully clunky way to enumerate strategies; this will need to be revisited later
// Use old-style callback construction, because lambda constructs buggy function on Android
// (callback param isn't captured by value).
m_router->CalculateRoute(checkpoints, direction, adjustToPrevRoute,
DoReadyCallback(*this, readyCallback), needMoreMapsCallback,
removeRouteCallback, m_progressCallback, timeoutSec);
m_router->CalculateRoute(
checkpoints, direction, adjustToPrevRoute, {EdgeEstimator::Strategy::Fastest, EdgeEstimator::Strategy::Shortest},
DoReadyCallback(*this, readyCallback), needMoreMapsCallback, removeRouteCallback, m_progressCallback, timeoutSec);
}
m2::PointD RoutingSession::GetStartPoint() const
@ -118,9 +114,9 @@ m2::PointD RoutingSession::GetEndPoint() const
void RoutingSession::DoReadyCallback::operator()(std::shared_ptr<Route> const & route, RouterResultCode e)
{
ASSERT(m_rs.m_route, ());
ASSERT(m_rs.m_active_route, ());
m_rs.AssignRoute(route, e);
m_callback(*m_rs.m_route, e);
m_callback(*m_rs.m_active_route, e);
}
void RoutingSession::RemoveRoute()
@ -131,9 +127,9 @@ void RoutingSession::RemoveRoute()
m_moveAwayCounter = 0;
m_turnNotificationsMgr.Reset();
m_route = std::make_shared<Route>(std::string{} /* router */, 0 /* route id */);
m_active_route = std::make_shared<Route>(std::string{} /* router */, 0 /* route id */);
m_speedCameraManager.Reset();
m_speedCameraManager.SetRoute(m_route);
m_speedCameraManager.SetRoute(m_active_route);
}
void RoutingSession::RebuildRouteOnTrafficUpdate()
@ -152,9 +148,7 @@ void RoutingSession::RebuildRouteOnTrafficUpdate()
case SessionState::RouteBuilding:
case SessionState::RouteNotStarted:
case SessionState::RouteNoFollowing:
case SessionState::RouteRebuilding:
startPoint = m_checkpoints.GetPointFrom();
break;
case SessionState::RouteRebuilding: startPoint = m_checkpoints.GetPointFrom(); break;
case SessionState::OnRoute:
case SessionState::RouteNeedRebuild: break;
@ -165,8 +159,8 @@ void RoutingSession::RebuildRouteOnTrafficUpdate()
}
RebuildRoute(startPoint, m_rebuildReadyCallback, nullptr /* needMoreMapsCallback */,
nullptr /* removeRouteCallback */, RouterDelegate::kNoTimeout,
SessionState::RouteRebuilding, false /* adjustToPrevRoute */);
nullptr /* removeRouteCallback */, RouterDelegate::kNoTimeout, SessionState::RouteRebuilding,
false /* adjustToPrevRoute */);
}
bool RoutingSession::IsActive() const
@ -265,17 +259,17 @@ SessionState RoutingSession::OnLocationPositionChanged(GpsInfo const & info)
return m_state;
}
CHECK(m_route, (m_state));
CHECK(m_active_route, (m_state));
// Note. The route may not be valid here. It happens in case when while the first route
// build is cancelled because of traffic jam were downloaded. After that route rebuilding
// happens. While the rebuilding may be called OnLocationPositionChanged(...)
if (!m_route->IsValid())
if (!m_active_route->IsValid())
return m_state;
m_turnNotificationsMgr.SetSpeedMetersPerSecond(info.m_speedMpS);
auto const formerIter = m_route->GetCurrentIteratorTurn();
if (m_route->MoveIterator(info))
auto const formerIter = m_active_route->GetCurrentIteratorTurn();
if (m_active_route->MoveIterator(info))
{
m_moveAwayCounter = 0;
m_lastDistance = 0.0;
@ -284,7 +278,7 @@ SessionState RoutingSession::OnLocationPositionChanged(GpsInfo const & info)
if (m_checkpoints.IsFinished())
{
m_passedDistanceOnRouteMeters += m_route->GetTotalDistanceMeters();
m_passedDistanceOnRouteMeters += m_active_route->GetTotalDistanceMeters();
SetState(SessionState::RouteFinished);
}
else
@ -296,11 +290,10 @@ SessionState RoutingSession::OnLocationPositionChanged(GpsInfo const & info)
if (m_userCurrentPositionValid)
m_lastGoodPosition = m_userCurrentPosition;
auto const curIter = m_route->GetCurrentIteratorTurn();
auto const curIter = m_active_route->GetCurrentIteratorTurn();
// If we are moving to the next segment after passing the turn
// it means the turn is changed. So the |m_onNewTurn| should be called.
if (formerIter && curIter && IsNormalTurn(*formerIter) &&
formerIter->m_index < curIter->m_index && m_onNewTurn)
if (formerIter && curIter && IsNormalTurn(*formerIter) && formerIter->m_index < curIter->m_index && m_onNewTurn)
{
m_onNewTurn();
}
@ -312,9 +305,9 @@ SessionState RoutingSession::OnLocationPositionChanged(GpsInfo const & info)
{
// Distance from the last known projection on route
// (check if we are moving far from the last known projection).
auto const & lastGoodPoint = m_route->GetFollowedPolyline().GetCurrentIter().m_pt;
double const dist = mercator::DistanceOnEarth(lastGoodPoint,
mercator::FromLatLon(info.m_latitude, info.m_longitude));
auto const & lastGoodPoint = m_active_route->GetFollowedPolyline().GetCurrentIter().m_pt;
double const dist =
mercator::DistanceOnEarth(lastGoodPoint, mercator::FromLatLon(info.m_latitude, info.m_longitude));
if (base::AlmostEqualAbs(dist, m_lastDistance, kRunawayDistanceSensitivityMeters))
return m_state;
@ -327,7 +320,7 @@ SessionState RoutingSession::OnLocationPositionChanged(GpsInfo const & info)
if (m_moveAwayCounter > kOnRouteMissedCount)
{
m_passedDistanceOnRouteMeters += m_route->GetCurrentDistanceFromBeginMeters();
m_passedDistanceOnRouteMeters += m_active_route->GetCurrentDistanceFromBeginMeters();
SetState(SessionState::RouteNeedRebuild);
}
}
@ -374,9 +367,9 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
ASSERT(m_active_route, ());
if (!m_route->IsValid())
if (!m_active_route->IsValid())
{
// nothing should be displayed on the screen about turns if these lines are executed
info = FollowingInfo();
@ -386,22 +379,21 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
if (!IsNavigable())
{
info = FollowingInfo();
info.m_distToTarget = platform::Distance::CreateFormatted(m_route->GetTotalDistanceMeters());
info.m_time = static_cast<int>(std::max(kMinimumETASec, m_route->GetCurrentTimeToEndSec()));
info.m_distToTarget = platform::Distance::CreateFormatted(m_active_route->GetTotalDistanceMeters());
info.m_time = static_cast<int>(std::max(kMinimumETASec, m_active_route->GetCurrentTimeToEndSec()));
return;
}
info.m_distToTarget =
platform::Distance::CreateFormatted(m_route->GetCurrentDistanceToEndMeters());
info.m_distToTarget = platform::Distance::CreateFormatted(m_active_route->GetCurrentDistanceToEndMeters());
double distanceToTurnMeters = 0.;
turns::TurnItem turn;
m_route->GetNearestTurn(distanceToTurnMeters, turn);
m_active_route->GetNearestTurn(distanceToTurnMeters, turn);
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
info.m_turn = turn.m_turn;
SpeedInUnits speedLimit;
m_route->GetCurrentSpeedLimit(speedLimit);
m_active_route->GetCurrentSpeedLimit(speedLimit);
if (speedLimit.IsNumeric())
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
@ -416,20 +408,20 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
info.m_nextTurn = routing::turns::CarDirection::None;
info.m_exitNum = turn.m_exitNum;
info.m_time = static_cast<int>(std::max(kMinimumETASec, m_route->GetCurrentTimeToEndSec()));
info.m_time = static_cast<int>(std::max(kMinimumETASec, m_active_route->GetCurrentTimeToEndSec()));
RouteSegment::RoadNameInfo currentRoadNameInfo, nextRoadNameInfo, nextNextRoadNameInfo;
m_route->GetCurrentStreetName(currentRoadNameInfo);
m_active_route->GetCurrentStreetName(currentRoadNameInfo);
GetFullRoadName(currentRoadNameInfo, info.m_currentStreetName);
m_route->GetNextTurnStreetName(nextRoadNameInfo);
m_active_route->GetNextTurnStreetName(nextRoadNameInfo);
GetFullRoadName(nextRoadNameInfo, info.m_nextStreetName);
m_route->GetNextNextTurnStreetName(nextNextRoadNameInfo);
m_active_route->GetNextNextTurnStreetName(nextNextRoadNameInfo);
GetFullRoadName(nextNextRoadNameInfo, info.m_nextNextStreetName);
info.m_completionPercent = GetCompletionPercent();
// Lane information
info.m_lanes.clear();
if (distanceToTurnMeters < kShowLanesMinDistInMeters || m_route->GetCurrentTimeToNearestTurnSec() < 60.0)
if (distanceToTurnMeters < kShowLanesMinDistInMeters || m_active_route->GetCurrentTimeToNearestTurnSec() < 60.0)
{
// There are two nested loops below. Outer one is for lanes and inner one (ctor of
// SingleLaneInfo) is
@ -441,23 +433,21 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
}
// Pedestrian info.
info.m_pedestrianTurn = (distanceToTurnMeters < kShowPedestrianTurnInMeters)
? turn.m_pedestrianTurn
: turns::PedestrianDirection::None;
info.m_pedestrianTurn =
(distanceToTurnMeters < kShowPedestrianTurnInMeters) ? turn.m_pedestrianTurn : turns::PedestrianDirection::None;
}
double RoutingSession::GetCompletionPercent() const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
ASSERT(m_active_route, ());
double const denominator = m_passedDistanceOnRouteMeters + m_route->GetTotalDistanceMeters();
if (!m_route->IsValid() || denominator == 0.0)
double const denominator = m_passedDistanceOnRouteMeters + m_active_route->GetTotalDistanceMeters();
if (!m_active_route->IsValid() || denominator == 0.0)
return 0;
double const percent =
100.0 * (m_passedDistanceOnRouteMeters + m_route->GetCurrentDistanceFromBeginMeters()) /
denominator;
100.0 * (m_passedDistanceOnRouteMeters + m_active_route->GetCurrentDistanceFromBeginMeters()) / denominator;
if (percent - m_lastCompletionPercent > kCompletionPercentAccuracy)
{
m_lastCompletionPercent = percent;
@ -468,9 +458,9 @@ double RoutingSession::GetCompletionPercent() const
void RoutingSession::PassCheckpoints()
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
while (!m_checkpoints.IsFinished() && m_route->IsSubroutePassed(m_checkpoints.GetPassedIdx()))
while (!m_checkpoints.IsFinished() && m_active_route->IsSubroutePassed(m_checkpoints.GetPassedIdx()))
{
m_route->PassNextSubroute();
m_active_route->PassNextSubroute();
m_checkpoints.PassNextPoint();
LOG(LINFO, ("Pass checkpoint, ", m_checkpoints));
m_checkpointCallback(m_checkpoints.GetPassedIdx());
@ -482,24 +472,24 @@ void RoutingSession::GenerateNotifications(std::vector<std::string> & notificati
CHECK_THREAD_CHECKER(m_threadChecker, ());
notifications.clear();
ASSERT(m_route, ());
ASSERT(m_active_route, ());
// Voice turn notifications.
if (!m_routingSettings.m_soundDirection)
return;
if (!m_route->IsValid() || !IsNavigable())
if (!m_active_route->IsValid() || !IsNavigable())
return;
// Generate turns notifications.
std::vector<turns::TurnItemDist> turns;
if (m_route->GetNextTurns(turns))
if (m_active_route->GetNextTurns(turns))
{
RouteSegment::RoadNameInfo nextStreetInfo;
// only populate nextStreetInfo if TtsStreetNames is enabled
if (announceStreets)
m_route->GetNextTurnStreetName(nextStreetInfo);
m_active_route->GetNextTurnStreetName(nextStreetInfo);
m_turnNotificationsMgr.GenerateTurnNotifications(turns, notifications, nextStreetInfo);
}
@ -515,7 +505,7 @@ void RoutingSession::AssignRoute(std::shared_ptr<Route> const & route, RouterRes
{
// Route building was not success. If the former route is valid let's continue moving along it.
// If not, let's set corresponding state.
if (m_route->IsValid())
if (m_active_route->IsValid())
SetState(SessionState::OnRoute);
else
SetState(SessionState::NoValidRoute);
@ -528,13 +518,15 @@ void RoutingSession::AssignRoute(std::shared_ptr<Route> const & route, RouterRes
m_checkpoints.SetPointFrom(route->GetPoly().Front());
route->SetRoutingSettings(m_routingSettings);
m_route = route;
m_active_route = route;
auto strategy = route->GetStrategy();
// if (strategy)
// m_routes->SetRoute(strategy.value(), route);
m_speedCameraManager.Reset();
m_speedCameraManager.SetRoute(m_route);
m_speedCameraManager.SetRoute(m_active_route);
}
void RoutingSession::SetRouter(std::unique_ptr<IRouter> && router,
std::unique_ptr<AbsentRegionsFinder> && finder)
void RoutingSession::SetRouter(std::unique_ptr<IRouter> && router, std::unique_ptr<AbsentRegionsFinder> && finder)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_router != nullptr, ());
@ -545,7 +537,7 @@ void RoutingSession::SetRouter(std::unique_ptr<IRouter> && router,
void RoutingSession::MatchLocationToRoadGraph(location::GpsInfo & location)
{
auto const locationMerc = mercator::FromLatLon(location.m_latitude, location.m_longitude);
double const radius = m_route->GetCurrentRoutingSettings().m_matchingThresholdM;
double const radius = m_active_route->GetCurrentRoutingSettings().m_matchingThresholdM;
m2::PointD const direction = m_positionAccumulator.GetDirection();
@ -570,12 +562,11 @@ void RoutingSession::MatchLocationToRoadGraph(location::GpsInfo & location)
if (m_proj.m_edge.GetFeatureId() == proj.m_edge.GetFeatureId())
{
if (m_route->GetCurrentRoutingSettings().m_matchRoute)
if (m_active_route->GetCurrentRoutingSettings().m_matchRoute)
{
if (!base::AlmostEqualAbs(m_proj.m_point, proj.m_point, kEps))
{
location.m_bearing =
location::AngleToBearing(base::RadToDeg(ang::AngleTo(m_proj.m_point, proj.m_point)));
location.m_bearing = location::AngleToBearing(base::RadToDeg(ang::AngleTo(m_proj.m_point, proj.m_point)));
}
}
@ -590,24 +581,22 @@ void RoutingSession::MatchLocationToRoadGraph(location::GpsInfo & location)
m_proj = proj;
}
bool RoutingSession::MatchLocationToRoute(location::GpsInfo & location,
location::RouteMatchingInfo & routeMatchingInfo)
bool RoutingSession::MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
if (!IsOnRoute())
return true;
ASSERT(m_route, ());
ASSERT(m_active_route, ());
bool const matchedToRoute = m_route->MatchLocationToRoute(location, routeMatchingInfo);
bool const matchedToRoute = m_active_route->MatchLocationToRoute(location, routeMatchingInfo);
if (matchedToRoute)
m_projectedToRoadGraph = false;
return matchedToRoute;
}
traffic::SpeedGroup RoutingSession::MatchTraffic(
location::RouteMatchingInfo const & routeMatchingInfo) const
traffic::SpeedGroup RoutingSession::MatchTraffic(location::RouteMatchingInfo const & routeMatchingInfo) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
if (!routeMatchingInfo.IsMatched())
@ -615,7 +604,7 @@ traffic::SpeedGroup RoutingSession::MatchTraffic(
size_t const index = routeMatchingInfo.GetIndexInRoute();
return m_route->GetTraffic(index);
return m_active_route->GetTraffic(index);
}
bool RoutingSession::DisableFollowMode()
@ -685,8 +674,7 @@ void RoutingSession::SetCheckpointCallback(CheckpointCallback const & checkpoint
m_checkpointCallback = checkpointCallback;
}
void RoutingSession::SetChangeSessionStateCallback(
ChangeSessionStateCallback const & changeSessionStateCallback)
void RoutingSession::SetChangeSessionStateCallback(ChangeSessionStateCallback const & changeSessionStateCallback)
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
m_changeSessionStateCallback = changeSessionStateCallback;
@ -753,16 +741,16 @@ std::string RoutingSession::GetTurnNotificationsLocale() const
void RoutingSession::RouteCall(RouteCallback const & callback) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
CHECK(m_route, ());
callback(*m_route);
CHECK(m_active_route, ());
callback(*m_active_route);
}
void RoutingSession::EmitCloseRoutingEvent() const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
ASSERT(m_active_route, ());
if (!m_route->IsValid())
if (!m_active_route->IsValid())
{
ASSERT(false, ());
return;
@ -772,31 +760,31 @@ void RoutingSession::EmitCloseRoutingEvent() const
bool RoutingSession::HasRouteAltitude() const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
return m_route->HaveAltitudes();
ASSERT(m_active_route, ());
return m_active_route->HaveAltitudes();
}
bool RoutingSession::IsRouteId(uint64_t routeId) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
return m_route->IsRouteId(routeId);
return m_active_route->IsRouteId(routeId);
}
bool RoutingSession::IsRouteValid() const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
return m_route && m_route->IsValid();
return m_active_route && m_active_route->IsValid();
}
bool RoutingSession::GetRouteJunctionPoints(std::vector<m2::PointD> & routeJunctionPoints) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
ASSERT(m_active_route, ());
if (!m_route->IsValid())
if (!m_active_route->IsValid())
return false;
auto const & segments = m_route->GetRouteSegments();
auto const & segments = m_active_route->GetRouteSegments();
routeJunctionPoints.reserve(segments.size());
for (size_t i = 0; i < segments.size(); ++i)
@ -813,17 +801,17 @@ bool RoutingSession::GetRouteAltitudesAndDistancesM(std::vector<double> & routeS
geometry::Altitudes & routeAltitudesM) const
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
ASSERT(m_route, ());
ASSERT(m_active_route, ());
if (!m_route->IsValid() || !m_route->HaveAltitudes())
if (!m_active_route->IsValid() || !m_active_route->HaveAltitudes())
return false;
auto const & distances = m_route->GetSegDistanceMeters();
auto const & distances = m_active_route->GetSegDistanceMeters();
routeSegDistanceM.reserve(distances.size() + 1);
routeSegDistanceM.push_back(0);
routeSegDistanceM.insert(routeSegDistanceM.end(), distances.begin(), distances.end());
m_route->GetAltitudes(routeAltitudesM);
m_active_route->GetAltitudes(routeAltitudesM);
ASSERT_EQUAL(routeSegDistanceM.size(), routeAltitudesM.size(), ());
return true;
@ -848,19 +836,23 @@ void RoutingSession::OnTrafficInfoAdded(TrafficInfo && info)
// Note. |coloring| should not be used after this call on gui thread.
auto const mwmId = info.GetMwmId();
GetPlatform().RunTask(Platform::Thread::Gui, [this, mwmId, coloring]() {
Set(mwmId, coloring);
RebuildRouteOnTrafficUpdate();
});
GetPlatform().RunTask(Platform::Thread::Gui,
[this, mwmId, coloring]()
{
Set(mwmId, coloring);
RebuildRouteOnTrafficUpdate();
});
}
void RoutingSession::OnTrafficInfoRemoved(MwmSet::MwmId const & mwmId)
{
GetPlatform().RunTask(Platform::Thread::Gui, [this, mwmId]() {
CHECK_THREAD_CHECKER(m_threadChecker, ());
Remove(mwmId);
RebuildRouteOnTrafficUpdate();
});
GetPlatform().RunTask(Platform::Thread::Gui,
[this, mwmId]()
{
CHECK_THREAD_CHECKER(m_threadChecker, ());
Remove(mwmId);
RebuildRouteOnTrafficUpdate();
});
}
void RoutingSession::CopyTraffic(traffic::AllMwmTrafficInfo & trafficColoring) const

View file

@ -6,10 +6,7 @@
#include "routing/route.hpp"
#include "routing/router.hpp"
#include "routing/routing_callbacks.hpp"
#include "routing/routing_exceptions.hpp"
#include "routing/speed_camera.hpp"
#include "routing/speed_camera_manager.hpp"
#include "routing/turns.hpp"
#include "routing/turns_notification_manager.hpp"
#include "traffic/speed_groups.hpp"
@ -21,16 +18,11 @@
#include "geometry/point2d.hpp"
#include "geometry/point_with_altitude.hpp"
#include "geometry/polyline2d.hpp"
#include "base/thread_checker.hpp"
#include <cstdint>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <queue>
#include <string>
namespace location
@ -52,16 +44,14 @@ public:
void Init(PointCheckCallback const & pointCheckCallback);
void SetRouter(std::unique_ptr<IRouter> && router,
std::unique_ptr<AbsentRegionsFinder> && finder);
void SetRouter(std::unique_ptr<IRouter> && router, std::unique_ptr<AbsentRegionsFinder> && finder);
/// @param[in] checkpoints in mercator
/// @param[in] timeoutSec timeout in seconds, if zero then there is no timeout
void BuildRoute(Checkpoints const & checkpoints, uint32_t timeoutSec);
void RebuildRoute(m2::PointD const & startPoint, ReadyCallback const & readyCallback,
NeedMoreMapsCallback const & needMoreMapsCallback,
RemoveRouteCallback const & removeRouteCallback, uint32_t timeoutSec,
SessionState routeRebuildingState, bool adjustToPrevRoute);
NeedMoreMapsCallback const & needMoreMapsCallback, RemoveRouteCallback const & removeRouteCallback,
uint32_t timeoutSec, SessionState routeRebuildingState, bool adjustToPrevRoute);
m2::PointD GetStartPoint() const;
m2::PointD GetEndPoint() const;
@ -101,8 +91,7 @@ public:
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
void GetRouteFollowingInfo(FollowingInfo & info) const;
bool MatchLocationToRoute(location::GpsInfo & location,
location::RouteMatchingInfo & routeMatchingInfo);
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
void MatchLocationToRoadGraph(location::GpsInfo & location);
// Get traffic speed for the current route position.
// Returns SpeedGroup::Unknown if any trouble happens: position doesn't match with route or something else.
@ -125,8 +114,7 @@ public:
bool EnableFollowMode();
void SetRoutingSettings(RoutingSettings const & routingSettings);
void SetRoutingCallbacks(ReadyCallback const & buildReadyCallback,
ReadyCallback const & rebuildReadyCallback,
void SetRoutingCallbacks(ReadyCallback const & buildReadyCallback, ReadyCallback const & rebuildReadyCallback,
NeedMoreMapsCallback const & needMoreMapsCallback,
RemoveRouteCallback const & removeRouteCallback);
void SetProgressCallback(ProgressCallback const & progressCallback);
@ -169,7 +157,7 @@ public:
SpeedCameraManager & GetSpeedCamManager() { return m_speedCameraManager; }
SpeedCameraManager const & GetSpeedCamManager() const { return m_speedCameraManager; }
std::shared_ptr<Route> GetRouteForTests() const { return m_route; }
std::shared_ptr<Route> GetRouteForTests() const { return m_active_route; }
void SetGuidesForTests(GuidesTracks guides) { m_router->SetGuidesTracks(std::move(guides)); }
double GetCompletionPercent() const;
@ -180,9 +168,7 @@ private:
RoutingSession & m_rs;
ReadyCallback m_callback;
DoReadyCallback(RoutingSession & rs, ReadyCallback const & cb)
: m_rs(rs), m_callback(cb)
{}
DoReadyCallback(RoutingSession & rs, ReadyCallback const & cb) : m_rs(rs), m_callback(cb) {}
void operator()(std::shared_ptr<Route> const & route, RouterResultCode e);
};
@ -196,7 +182,8 @@ private:
private:
std::unique_ptr<AsyncRouter> m_router;
std::shared_ptr<Route> m_route;
std::unique_ptr<Routes> m_routes;
std::shared_ptr<Route> m_active_route;
SessionState m_state;
bool m_isFollowing;
Checkpoints m_checkpoints;
@ -233,7 +220,7 @@ private:
// Passed distance on route including reroutes
double m_passedDistanceOnRouteMeters = 0.0;
// Rerouting count
int m_routingRebuildCount = -1; // -1 for the first rebuild called in BuildRoute().
int m_routingRebuildCount = -1; // -1 for the first rebuild called in BuildRoute().
mutable double m_lastCompletionPercent = 0.0;
DECLARE_THREAD_CHECKER(m_threadChecker);

View file

@ -146,6 +146,7 @@ double WeightedEdgeEstimator::CalcSegmentWeight(Segment const & segment,
}
double WeightedEdgeEstimator::GetUTurnPenalty(Purpose purpose) const { return 0.0; }
double WeightedEdgeEstimator::GetTurnPenalty(Purpose purpose) const { return 0.0; }
double WeightedEdgeEstimator::GetFerryLandingPenalty(Purpose purpose) const { return 0.0; }
// TestIndexGraphTopology --------------------------------------------------------------------------

View file

@ -181,6 +181,7 @@ public:
EdgeEstimator::Purpose purpose) const override;
double GetUTurnPenalty(Purpose purpose) const override;
double GetTurnPenalty(Purpose purpose) const override;
double GetFerryLandingPenalty(Purpose purpose) const override;
private: