Welcome to mirror list, hosted at ThFree Co, Russian Federation.

vehicle_model.hpp « routing_common - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c37e102e4ac5e7fea7f226904db0de1d46315811 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
#pragma once

#include "routing_common/maxspeed_conversion.hpp"

#include "base/stl_helpers.hpp"

#include <array>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <limits>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

class Classificator;
class FeatureType;

namespace feature { class TypesHolder; }

namespace routing
{
double constexpr kNotUsed = std::numeric_limits<double>::max();

struct InOutCityFactor;
struct InOutCitySpeedKMpH;

// Each value is equal to the corresponding type index from types.txt.
// The ascending order is strict.
enum class HighwayType : uint32_t
{
  HighwayResidential = 1,
  HighwayService = 2,
  HighwayUnclassified = 4,
  HighwayFootway = 6,
  HighwayTrack = 7,
  HighwayTertiary = 8,
  HighwaySecondary = 12,
  HighwayPath = 15,
  HighwayPrimary = 26,
  HighwayRoad = 30,
  HighwayCycleway = 36,
  HighwayMotorwayLink = 43,
  HighwayLivingStreet = 54,
  HighwayMotorway = 57,
  HighwaySteps = 58,
  HighwayTrunk = 65,
  HighwayPedestrian = 69,
  HighwayTrunkLink = 90,
  HighwayPrimaryLink = 95,
  ManMadePier = 119,
  HighwayBridleway = 167,
  HighwaySecondaryLink = 176,
  RouteFerry = 259,
  HighwayTertiaryLink = 272,
  RouteFerryMotorcar = 988,
  RouteFerryMotorVehicle = 993,
  RailwayRailMotorVehicle = 994,
  RouteShuttleTrain = 1054,
};

using HighwayBasedFactors = std::unordered_map<HighwayType, InOutCityFactor, base::EnumClassHash>;
using HighwayBasedSpeeds = std::unordered_map<HighwayType, InOutCitySpeedKMpH, base::EnumClassHash>;

/// \brief Params for calculation of an approximate speed on a feature.
struct SpeedParams
{
  SpeedParams(bool forward, bool inCity, Maxspeed maxspeed)
    : m_forward(forward), m_inCity(inCity), m_maxspeed(std::move(maxspeed))
  {
  }

  bool m_forward;
  // |m_inCity| == true if a corresponding feature lies inside a city of a town.
  bool m_inCity;
  Maxspeed m_maxspeed;
};

/// \brief Speeds which are used for edge weight and ETA estimations.
struct SpeedKMpH
{
  constexpr SpeedKMpH() = default;
  constexpr SpeedKMpH(double weight) noexcept : m_weight(weight), m_eta(weight) {}
  constexpr SpeedKMpH(double weight, double eta) noexcept : m_weight(weight), m_eta(eta) {}

  bool operator==(SpeedKMpH const & rhs) const
  {
    return m_weight == rhs.m_weight && m_eta == rhs.m_eta;
  }
  bool operator!=(SpeedKMpH const & rhs) const { return !(*this == rhs); }

  bool IsValid() const { return m_weight > 0 && m_eta > 0; }

  double m_weight = 0.0;  // KMpH
  double m_eta = 0.0;     // KMpH
};

/// \brief Factors which modify weight and ETA speed on feature in case of bad pavement (reduce)
/// or good highway class (increase).
/// Both should be greater then 0.
struct SpeedFactor
{
  constexpr SpeedFactor() = default;
  constexpr SpeedFactor(double factor) noexcept : m_weight(factor), m_eta(factor) {}
  constexpr SpeedFactor(double weight, double eta) noexcept : m_weight(weight), m_eta(eta) {}

  bool IsValid() const { return m_weight > 0.0 && m_eta > 0.0; }

  bool operator==(SpeedFactor const & rhs) const
  {
    return m_weight == rhs.m_weight && m_eta == rhs.m_eta;
  }
  bool operator!=(SpeedFactor const & rhs) const { return !(*this == rhs); }

  double m_weight = 1.0;
  double m_eta = 1.0;
};

inline SpeedKMpH operator*(SpeedFactor const & factor, SpeedKMpH const & speed)
{
  return {speed.m_weight * factor.m_weight, speed.m_eta * factor.m_eta};
}

inline SpeedKMpH operator*(SpeedKMpH const & speed, SpeedFactor const & factor)
{
  return {speed.m_weight * factor.m_weight, speed.m_eta * factor.m_eta};
}

struct InOutCitySpeedKMpH
{
  constexpr InOutCitySpeedKMpH() = default;
  constexpr explicit InOutCitySpeedKMpH(SpeedKMpH const & speed) noexcept
    : m_inCity(speed), m_outCity(speed)
  {
  }
  constexpr InOutCitySpeedKMpH(SpeedKMpH const & inCity, SpeedKMpH const & outCity) noexcept
    : m_inCity(inCity), m_outCity(outCity)
  {
  }

  bool operator==(InOutCitySpeedKMpH const & rhs) const
  {
    return m_inCity == rhs.m_inCity && m_outCity == rhs.m_outCity;
  }

  SpeedKMpH const & GetSpeed(bool isCity) const { return isCity ? m_inCity : m_outCity; }
  bool IsValid() const { return m_inCity.IsValid() && m_outCity.IsValid(); }

  SpeedKMpH m_inCity;
  SpeedKMpH m_outCity;
};

struct InOutCityFactor
{
  constexpr explicit InOutCityFactor(SpeedFactor const & factor) noexcept
    : m_inCity(factor), m_outCity(factor)
  {
  }
  constexpr InOutCityFactor(SpeedFactor const & inCity, SpeedFactor const & outCity) noexcept
    : m_inCity(inCity), m_outCity(outCity)
  {
  }

  bool operator==(InOutCityFactor const & rhs) const
  {
    return m_inCity == rhs.m_inCity && m_outCity == rhs.m_outCity;
  }

  SpeedFactor const & GetFactor(bool isCity) const { return isCity ? m_inCity : m_outCity; }
  bool IsValid() const { return m_inCity.IsValid() && m_outCity.IsValid(); }

  SpeedFactor m_inCity;
  SpeedFactor m_outCity;
};

struct HighwayBasedInfo
{
  HighwayBasedInfo(HighwayBasedSpeeds const & speeds, HighwayBasedFactors const & factors)
    : m_speeds(speeds)
    , m_factors(factors)
  {
  }

  HighwayBasedSpeeds const & m_speeds;
  HighwayBasedFactors const & m_factors;
};

class VehicleModelInterface
{
public:
  enum class RoadAvailability
  {
    NotAvailable,
    Available,
    Unknown,
  };

  virtual ~VehicleModelInterface() = default;

  /// @return Allowed weight and ETA speed in KMpH.
  /// 0 means that it's forbidden to move on this feature or it's not a road at all.
  /// Weight and ETA should be less than max model speed's values respectively.
  /// @param inCity is true if |f| lies in a city of town.
  virtual SpeedKMpH GetSpeed(FeatureType & f, SpeedParams const & speedParams) const = 0;

  virtual HighwayType GetHighwayType(FeatureType & f) const = 0;

  /// @return Maximum model weight speed.
  /// All speeds which the model returns must be less than or equal to this speed.
  virtual double GetMaxWeightSpeed() const = 0;

  /// @return Offroad speed in KMpH for vehicle. This speed should be used for non-feature routing
  /// e.g. to connect start point to nearest feature.
  virtual SpeedKMpH const & GetOffroadSpeed() const = 0;

  virtual bool IsOneWay(FeatureType & f) const = 0;

  /// @returns true iff feature |f| can be used for routing with corresponding vehicle model.
  virtual bool IsRoad(FeatureType & f) const = 0;

  /// @returns true iff feature |f| can be used for through passage with corresponding vehicle model.
  /// e.g. in Russia roads tagged "highway = service" are not allowed for through passage;
  /// however, road with this tag can be be used if it is close enough to the start or destination
  /// point of the route.
  /// Roads with additional types e.g. "path = ferry", "vehicle_type = yes" considered as allowed
  /// to pass through.
  virtual bool IsPassThroughAllowed(FeatureType & f) const = 0;
};

class VehicleModelFactoryInterface
{
public:
  virtual ~VehicleModelFactoryInterface() = default;
  /// @return Default vehicle model which corresponds for all countrines,
  /// but it may be non optimal for some countries
  virtual std::shared_ptr<VehicleModelInterface> GetVehicleModel() const = 0;

  /// @return The most optimal vehicle model for specified country
  virtual std::shared_ptr<VehicleModelInterface> GetVehicleModelForCountry(
      std::string const & country) const = 0;
};

class VehicleModel : public VehicleModelInterface
{
public:
  struct FeatureTypeLimits final
  {
    FeatureTypeLimits(std::vector<std::string> const & types, bool isPassThroughAllowed)
      : m_types(types), m_isPassThroughAllowed(isPassThroughAllowed)
    {
    }

    std::vector<std::string> m_types;
    bool m_isPassThroughAllowed;  // Pass through this road type is allowed.
  };

  // Structure for keeping surface tags: psurface|paved_good, psurface|paved_bad,
  // psurface|unpaved_good and psurface|unpaved_bad.
  struct FeatureTypeSurface
  {
    std::vector<std::string> m_types;  // 2-arity road type
    SpeedFactor m_factor;
  };

  struct AdditionalRoadTags final
  {
    AdditionalRoadTags() = default;

    AdditionalRoadTags(std::initializer_list<char const *> const & hwtag,
                       InOutCitySpeedKMpH const & speed)
      : m_hwtag(hwtag.begin(), hwtag.end()), m_speed(speed)
    {
    }

    std::vector<std::string> m_hwtag;
    InOutCitySpeedKMpH m_speed;
  };

  using LimitsInitList = std::initializer_list<FeatureTypeLimits>;
  using SurfaceInitList = std::initializer_list<FeatureTypeSurface>;

  VehicleModel(Classificator const & c, LimitsInitList const & featureTypeLimits,
               SurfaceInitList const & featureTypeSurface, HighwayBasedInfo const & info);

  /// VehicleModelInterface overrides:
  SpeedKMpH GetSpeed(FeatureType & f, SpeedParams const & speedParams) const override;
  HighwayType GetHighwayType(FeatureType & f) const override;
  double GetMaxWeightSpeed() const override;
  bool IsOneWay(FeatureType & f) const override;
  bool IsRoad(FeatureType & f) const override;
  bool IsPassThroughAllowed(FeatureType & f) const override;

public:
  /// @returns true if |m_highwayTypes| or |m_addRoadTypes| contains |type| and false otherwise.
  bool IsRoadType(uint32_t type) const;

  template <class TList>
  bool HasRoadType(TList const & types) const
  {
    for (uint32_t t : types)
    {
      if (IsRoadType(t))
        return true;
    }
    return false;
  }

  bool EqualsForTests(VehicleModel const & rhs) const
  {
    return (m_roadTypes == rhs.m_roadTypes) && (m_addRoadTypes == rhs.m_addRoadTypes) &&
           (m_onewayType == rhs.m_onewayType);
  }

protected:
  /// @returns a special restriction which is set to the feature.
  virtual RoadAvailability GetRoadAvailability(feature::TypesHolder const & types) const;

  /// Used in derived class constructors only. Not for public use.
  void SetAdditionalRoadTypes(Classificator const & c,
                              std::vector<AdditionalRoadTags> const & additionalTags);

  /// \returns true if |types| is a oneway feature.
  /// \note According to OSM, tag "oneway" could have value "-1". That means it's a oneway feature
  /// with reversed geometry. In that case at map generation the geometry of such features
  /// is reversed (the order of points is changed) so in vehicle model all oneway feature
  /// may be considered as features with forward geometry.
  bool HasOneWayType(feature::TypesHolder const & types) const;

  bool HasPassThroughType(feature::TypesHolder const & types) const;

  SpeedKMpH GetTypeSpeed(feature::TypesHolder const & types, SpeedParams const & speedParams) const;

  SpeedKMpH GetSpeedWihtoutMaxspeed(FeatureType & f, SpeedParams const & speedParams) const;

  /// \brief maximum within all the speed limits set in a model (car model, bicycle model and so on).
  /// It shouldn't be mixed with maxspeed value tag which defines maximum legal speed on a feature.
  InOutCitySpeedKMpH m_maxModelSpeed;

private:
  struct AdditionalRoadType final
  {
    AdditionalRoadType(Classificator const & c, AdditionalRoadTags const & tag);

    bool operator==(AdditionalRoadType const & rhs) const { return m_type == rhs.m_type; }

    uint32_t const m_type;
    InOutCitySpeedKMpH const m_speed;
  };

  class RoadType final
  {
  public:
    RoadType(HighwayType hwtype, bool isPassThroughAllowed)
      : m_highwayType(hwtype), m_isPassThroughAllowed(isPassThroughAllowed)
    {
    }

    bool IsPassThroughAllowed() const { return m_isPassThroughAllowed; };
    HighwayType GetHighwayType() const { return m_highwayType; }
    bool operator==(RoadType const & rhs) const
    {
      return m_highwayType == rhs.m_highwayType &&
             m_isPassThroughAllowed == rhs.m_isPassThroughAllowed;
    }

  private:
    HighwayType const m_highwayType;
    bool const m_isPassThroughAllowed;
  };

  struct TypeFactor
  {
    uint32_t m_type = 0;
    SpeedFactor m_factor;
  };

  std::optional<HighwayType> GetHighwayType(uint32_t type) const;
  void GetSurfaceFactor(uint32_t type, SpeedFactor & factor) const;
  void GetAdditionalRoadSpeed(uint32_t type, bool isCityRoad,
                              std::optional<SpeedKMpH> & speed) const;

  SpeedKMpH GetSpeedOnFeatureWithoutMaxspeed(HighwayType const & type,
                                             SpeedParams const & speedParams) const;
  SpeedKMpH GetSpeedOnFeatureWithMaxspeed(HighwayType const & type,
                                          SpeedParams const & speedParams) const;

  std::vector<AdditionalRoadType>::const_iterator FindAdditionalRoadType(uint32_t type) const;

  std::unordered_map<uint32_t, RoadType> m_roadTypes;
  // Mapping surface types (psurface|paved_good, psurface|paved_bad, psurface|unpaved_good,
  // psurface|unpaved_bad) to surface speed factors.
  // Note. It's an array (not map or unordered_map) because of perfomance reasons.
  std::array<TypeFactor, 4> m_surfaceFactors;

  std::vector<AdditionalRoadType> m_addRoadTypes;
  uint32_t m_onewayType;

  HighwayBasedInfo const m_highwayBasedInfo;
};

class VehicleModelFactory : public VehicleModelFactoryInterface
{
public:
  // Callback which takes territory name (mwm graph node name) and returns its parent
  // territory name. Used to properly find local restrictions in GetVehicleModelForCountry.
  // For territories which do not have parent (countries) or have multiple parents
  // (disputed territories) it should return empty name.
  // For example "Munich" -> "Bavaria"; "Bavaria" -> "Germany"; "Germany" -> ""
  using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;

  std::shared_ptr<VehicleModelInterface> GetVehicleModel() const override;

  std::shared_ptr<VehicleModelInterface> GetVehicleModelForCountry(
      std::string const & country) const override;

protected:
  explicit VehicleModelFactory(CountryParentNameGetterFn const & countryParentNameGetterFn);
  std::string GetParent(std::string const & country) const;

  std::unordered_map<std::string, std::shared_ptr<VehicleModelInterface>> m_models;
  CountryParentNameGetterFn m_countryParentNameGetterFn;
};

HighwayBasedFactors GetOneFactorsForBicycleAndPedestrianModel();

std::string DebugPrint(VehicleModelInterface::RoadAvailability const l);
std::string DebugPrint(SpeedKMpH const & speed);
std::string DebugPrint(SpeedFactor const & speedFactor);
std::string DebugPrint(InOutCitySpeedKMpH const & speed);
std::string DebugPrint(InOutCityFactor const & speedFactor);
std::string DebugPrint(HighwayType type);
}  // namespace routing