LCOV - code coverage report
Current view: top level - app/src/Dynamic/Env - Lane.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 88 2.3 %
Date: 2023-08-17 16:45:52 Functions: 1 16 6.2 %

          Line data    Source code
       1             : #include "Dynamic/Env/Lane.hpp"
       2             : 
       3             : #include <optional>
       4             : 
       5             : #include "Dynamic/Env/Edge.hpp"
       6             : #include "Dynamic/Env/Env.hpp"
       7             : #include "Dynamic/Env/Event/EventPopQueue.hpp"
       8             : #include "Dynamic/Env/Event/EventUpdateVehicle.hpp"
       9             : 
      10             : using namespace std;
      11             : using namespace Dynamic;
      12             : using namespace Dynamic::Env;
      13             : 
      14             : const double Lane::QUEUE_PERIOD = 1.0 / JUNCTION_CAPACITY;
      15             : const double Lane::QUEUE_SPEED  = JUNCTION_CAPACITY * Vehicle::LENGTH;
      16             : const Length Lane::K_JAM        = 1.0 / Dynamic::Env::Vehicle::LENGTH;
      17             : 
      18           1 : Lane::Lane(Edge &edge_, Index index_):
      19           2 :     edge(edge_), index(index_) {}
      20             : 
      21           0 : bool Lane::operator==(const Lane &other) const {
      22           0 :     return edge == other.edge && index == other.index;
      23             : }
      24             : 
      25           0 : bool Lane::operator!=(const Lane &other) const {
      26           0 :     return !(*this == other);
      27             : }
      28             : 
      29           0 : bool Lane::operator<(const Lane &other) const {
      30           0 :     if(edge != other.edge)
      31           0 :         return edge < other.edge;
      32             :     else
      33           0 :         return index < other.index;
      34             : }
      35             : 
      36           0 : list<reference_wrapper<Connection>> Lane::getOutgoingConnections() const {
      37           0 :     list<reference_wrapper<Connection>> ret;
      38           0 :     for(auto &[toEdgeID, connections]: outgoingConnections)
      39           0 :         for(auto &[toLaneIndex, connection]: connections)
      40           0 :             ret.push_back(connection);
      41           0 :     return ret;
      42             : }
      43             : 
      44           0 : list<reference_wrapper<Connection>> Lane::getOutgoingConnections(
      45             :     const Edge &nextEdge
      46             : ) const {
      47           0 :     if(!outgoingConnections.count(nextEdge.id))
      48           0 :         return list<reference_wrapper<Connection>>();
      49           0 :     list<reference_wrapper<Connection>> ret;
      50           0 :     for(auto &[targetLaneIndex, connection]: outgoingConnections.at(nextEdge.id))
      51           0 :         ret.push_back(connection);
      52           0 :     return ret;
      53             : }
      54             : 
      55           0 : Connection &Lane::getOutgoingConnection(const Lane &nextLane) const {
      56           0 :     return outgoingConnections.at(nextLane.edge.id).at(nextLane.index);
      57             : }
      58             : 
      59           0 : list<reference_wrapper<Connection>> Lane::getIncomingConnections() const {
      60           0 :     list<reference_wrapper<Connection>> ret;
      61           0 :     for(auto &[fromEdgeID, connections]: incomingConnections)
      62           0 :         for(auto &[fromLaneIndex, connection]: connections)
      63           0 :             ret.push_back(connection);
      64           0 :     return ret;
      65             : }
      66             : 
      67           0 : Speed Lane::calculateSpeed() const {
      68           0 :     size_t N = moving.size() + stopped.size();
      69             : 
      70           0 :     if(N <= 1)
      71           0 :         return edge.calculateSpeed();
      72             : 
      73           0 :     Length K = (double)(N) / edge.length;
      74             : 
      75           0 :     Speed v = edge.calculateSpeed() * (1.0 - K / K_JAM);
      76             : 
      77             :     // v = max(v, 3.5);
      78           0 :     v = max(v, QUEUE_SPEED);
      79             : 
      80           0 :     return v;
      81             : }
      82             : 
      83           0 : Length Lane::queueLength() const {
      84           0 :     return Vehicle::LENGTH * (Length)stopped.size();
      85             : }
      86             : 
      87           0 : Length Lane::queuePosition() const {
      88           0 :     return edge.length - queueLength();
      89             : }
      90             : 
      91           0 : size_t Lane::queueCapacity() const {
      92           0 :     return (size_t)ceil(edge.length / Vehicle::LENGTH);
      93             : }
      94             : 
      95           0 : bool Lane::isFull() const {
      96           0 :     return queueLength() >= edge.length;
      97             : }
      98             : 
      99           0 : void Lane::processNextWaitingVehicle(Env &env) {
     100           0 :     if(isFull()) return;
     101             : 
     102           0 :     if(!uninstantiated.empty()) {
     103           0 :         Dynamic::Vehicle instantiatedVehicle = uninstantiated.front();
     104           0 :         uninstantiated.pop();
     105             : 
     106           0 :         EventSpawnVehicle event(
     107             :             env.getTime(),
     108             :             instantiatedVehicle
     109           0 :         );
     110           0 :         event.process(env);
     111             : 
     112           0 :         return;
     113             :     }
     114             : 
     115           0 :     set<reference_wrapper<Connection>, less<Connection>> inConnections;
     116           0 :     for(Connection &connection: getIncomingConnections()) {
     117           0 :         const auto &incomingQueue = connection.fromLane.stopped;
     118             : 
     119           0 :         if(incomingQueue.empty()) continue;
     120             : 
     121           0 :         const Action &a = *incomingQueue.front().second;
     122             : 
     123           0 :         if(a.connection.toLane != *this) continue;
     124             : 
     125           0 :         inConnections.insert(connection);
     126             :     }
     127             : 
     128           0 :     optional<reference_wrapper<Connection>> connection = nullopt;
     129             : 
     130           0 :     while(!inConnections.empty() && !connection.has_value()) {
     131           0 :         connection = *inConnections.begin();
     132             : 
     133           0 :         for(
     134           0 :             auto it = ++inConnections.begin();
     135           0 :             it != inConnections.end();
     136           0 :             ++it
     137             :         ) {
     138           0 :             Connection &otherConnection = it->get();
     139           0 :             if(connection.value().get().yieldsTo(otherConnection)) {
     140           0 :                 inConnections.erase(connection.value());
     141           0 :                 connection = nullopt;
     142             :                 break;
     143             :             }
     144             :         }
     145             :     }
     146             : 
     147           0 :     if(!connection.has_value())
     148           0 :         return;
     149             : 
     150           0 :     Lane &incomingLane = connection.value().get().fromLane;
     151             : 
     152           0 :     auto [vehicle, action] = incomingLane.stopped.front();
     153             : 
     154           0 :     assert(action->connection.toLane == *this);
     155             : 
     156             :     /*
     157             :      * We don't need to check if connection.canPass(), because
     158             :      * EventPopQueue already checks connection.canPass() before
     159             :      * popping the queue.
     160             :      */
     161           0 :     EventPopQueue event(
     162             :         env.getTime(),
     163             :         incomingLane
     164           0 :     );
     165           0 :     event.process(env);
     166             : }
     167             : 
     168           0 : string Lane::idAsString() const {
     169           0 :     return to_string(edge.id) + "_" + to_string(index);
     170             : }
     171             : 
     172             : Lane Lane::INVALID = {Edge::INVALID, 0};
     173             : 
     174           0 : size_t std::hash<Lane>::operator()(const Lane &lane) const {
     175           0 :     size_t h = hash<Edge::ID>()(lane.edge.id) << 4;
     176           0 :     h ^= lane.index;
     177           0 :     return h;
     178             : }

Generated by: LCOV version 1.14