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 : }