Program Listing for File RoutingCost.h

Return to documentation for file (include/lanelet2_routing/RoutingCost.h)

#pragma once

#include <lanelet2_core/Exceptions.h>
#include <lanelet2_core/Forward.h>
#include <lanelet2_core/primitives/LaneletOrArea.h>
#include <lanelet2_traffic_rules/TrafficRules.h>

#include "lanelet2_routing/Forward.h"

namespace lanelet {
namespace routing {

class RoutingCost {  // NOLINT
 public:
  virtual ~RoutingCost() = default;

  virtual double getCostSucceeding(const traffic_rules::TrafficRules& trafficRules, const ConstLaneletOrArea& from,
                                   const ConstLaneletOrArea& to) const = 0;

  virtual double getCostLaneChange(const traffic_rules::TrafficRules& trafficRules, const ConstLanelets& from,
                                   const ConstLanelets& to) const = 0;
};

class RoutingCostDistance : public RoutingCost {
 public:
  explicit RoutingCostDistance(double laneChangeCost, double minLaneChangeLength = 0.)
      : laneChangeCost_{laneChangeCost}, minChangeLength_{minLaneChangeLength} {
    if (laneChangeCost_ < 0.0) {
      throw InvalidInputError("Lane change cost must be positive, but it is " + std::to_string(laneChangeCost_));
    }
  }
  inline double getCostSucceeding(const traffic_rules::TrafficRules& /*trafficRules*/, const ConstLaneletOrArea& from,
                                  const ConstLaneletOrArea& to) const override {
    auto getLength = [this](auto& lltOrArea) -> double { return this->length(lltOrArea); };
    return (from.applyVisitor(getLength) + to.applyVisitor(getLength)) / 2;
  }
  inline double getCostLaneChange(const traffic_rules::TrafficRules& /*trafficRules*/, const ConstLanelets& from,
                                  const ConstLanelets& /*to*/) const noexcept override {
    if (minChangeLength_ <= 0.) {
      return laneChangeCost_;
    }
    auto totalLength = std::accumulate(from.begin(), from.end(), 0.,
                                       [this](double acc, auto& llt) { return acc + this->length(llt); });
    return totalLength >= minChangeLength_ ? laneChangeCost_ : std::numeric_limits<double>::infinity();
  }

 private:
  static double length(const ConstLanelet& ll) noexcept;
  static double length(const ConstArea& ar) noexcept;
  const double laneChangeCost_, minChangeLength_;  // NOLINT
};

class RoutingCostTravelTime : public RoutingCost {
 public:
  RoutingCostTravelTime() = delete;

  explicit RoutingCostTravelTime(double laneChangeCost, double minLaneChangeTime = 0.)
      : laneChangeCost_{laneChangeCost}, minChangeTime_{minLaneChangeTime} {
    if (laneChangeCost_ < 0.0) {
      throw InvalidInputError("Lane change cost must be positive, but it is " + std::to_string(laneChangeCost_));
    }
  }

  inline double getCostLaneChange(const traffic_rules::TrafficRules& trafficRules, const ConstLanelets& from,
                                  const ConstLanelets& /*to*/) const noexcept override {
    if (minChangeTime_ <= 0.) {
      return laneChangeCost_;
    }
    auto changeTime = std::accumulate(from.begin(), from.end(), 0., [this, &trafficRules](double acc, auto& llt) {
      return acc + this->travelTime(trafficRules, llt);
    });
    return changeTime >= minChangeTime_ ? laneChangeCost_ : std::numeric_limits<double>::infinity();
  }
  inline double getCostSucceeding(const traffic_rules::TrafficRules& trafficRules, const ConstLaneletOrArea& from,
                                  const ConstLaneletOrArea& to) const override {
    auto getTravelTime = [&trafficRules, this](auto& lltOrArea) -> double {
      return this->travelTime(trafficRules, lltOrArea);
    };
    return (from.applyVisitor(getTravelTime) + to.applyVisitor(getTravelTime)) / 2;
  }

 private:
  static double travelTime(const traffic_rules::TrafficRules& trafficRules, const ConstLanelet& ll);
  static double travelTime(const traffic_rules::TrafficRules& trafficRules, const ConstArea& ar);
  const Velocity maxSpeed_;                      // NOLINT
  const double laneChangeCost_, minChangeTime_;  // NOLINT
};

inline RoutingCostPtrs defaultRoutingCosts() {
  return RoutingCostPtrs{std::make_shared<RoutingCostDistance>(10.), std::make_shared<RoutingCostTravelTime>(5.)};
}
}  // namespace routing
}  // namespace lanelet