|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // Builder of microsim-junctions and tls 00011 /****************************************************************************/ 00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00014 /****************************************************************************/ 00015 // 00016 // This file is part of SUMO. 00017 // SUMO is free software: you can redistribute it and/or modify 00018 // it under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation, either version 3 of the License, or 00020 // (at your option) any later version. 00021 // 00022 /****************************************************************************/ 00023 00024 00025 // =========================================================================== 00026 // included modules 00027 // =========================================================================== 00028 #ifdef _MSC_VER 00029 #include <windows_config.h> 00030 #else 00031 #include <config.h> 00032 #endif 00033 00034 #include <map> 00035 #include <string> 00036 #include <vector> 00037 #include <list> 00038 #include <algorithm> 00039 #include <microsim/MSJunctionLogic.h> 00040 #include <microsim/MSNoLogicJunction.h> 00041 #include <microsim/MSRightOfWayJunction.h> 00042 #include <microsim/MSInternalJunction.h> 00043 #include <microsim/MSJunctionControl.h> 00044 #include <microsim/traffic_lights/MSTrafficLightLogic.h> 00045 #include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h> 00046 #include <microsim/MSEventControl.h> 00047 #include <microsim/MSGlobals.h> 00048 #include <microsim/traffic_lights/MSAgentbasedTrafficLightLogic.h> 00049 #include <microsim/traffic_lights/MSOffTrafficLightLogic.h> 00050 #include <microsim/traffic_lights/MSTLLogicControl.h> 00051 #include <utils/xml/SUMOXMLDefinitions.h> 00052 #include <utils/common/UtilExceptions.h> 00053 #include <utils/common/ToString.h> 00054 #include <netbuild/NBNode.h> 00055 #include "NLBuilder.h" 00056 #include "NLJunctionControlBuilder.h" 00057 00058 #ifdef CHECK_MEMORY_LEAKS 00059 #include <foreign/nvwa/debug_new.h> 00060 #endif // CHECK_MEMORY_LEAKS 00061 00062 00063 // =========================================================================== 00064 // static members 00065 // =========================================================================== 00066 const int NLJunctionControlBuilder::NO_REQUEST_SIZE = -1; 00067 00068 // =========================================================================== 00069 // method definitions 00070 // =========================================================================== 00071 NLJunctionControlBuilder::NLJunctionControlBuilder(MSNet& net, NLDetectorBuilder& db) 00072 : myNet(net), myDetectorBuilder(db), myOffset(0), myJunctions(0) { 00073 myLogicControl = new MSTLLogicControl(); 00074 myJunctions = new MSJunctionControl(); 00075 } 00076 00077 00078 NLJunctionControlBuilder::~NLJunctionControlBuilder() { 00079 delete myLogicControl; 00080 delete myJunctions; 00081 } 00082 00083 00084 void 00085 NLJunctionControlBuilder::openJunction(const std::string& id, 00086 const std::string& key, 00087 const std::string& type, 00088 SUMOReal x, SUMOReal y, 00089 const PositionVector& shape, 00090 const std::vector<MSLane*> &incomingLanes, 00091 const std::vector<MSLane*> &internalLanes) throw(InvalidArgument) { 00092 #ifdef HAVE_INTERNAL_LANES 00093 myActiveInternalLanes = internalLanes; 00094 #endif 00095 myActiveIncomingLanes = incomingLanes; 00096 myActiveID = id; 00097 myActiveKey = key; 00098 if (!SUMOXMLDefinitions::NodeTypes.hasString(type)) { 00099 throw InvalidArgument("An unknown or invalid junction type '" + type + "' occured in junction '" + id + "'."); 00100 } 00101 00102 myType = SUMOXMLDefinitions::NodeTypes.get(type); 00103 myPosition.set(x, y); 00104 myShape = shape; 00105 } 00106 00107 00108 void 00109 NLJunctionControlBuilder::closeJunction() throw(InvalidArgument, ProcessError) { 00110 if (myJunctions == 0) { 00111 throw ProcessError("Information about the number of nodes was missing."); 00112 } 00113 MSJunction* junction = 0; 00114 switch (myType) { 00115 case NODETYPE_NOJUNCTION: 00116 case NODETYPE_DEAD_END: 00117 case NODETYPE_DEAD_END_DEPRECATED: 00118 case NODETYPE_DISTRICT: 00119 junction = buildNoLogicJunction(); 00120 break; 00121 case NODETYPE_TRAFFIC_LIGHT: 00122 case NODETYPE_RIGHT_BEFORE_LEFT: 00123 case NODETYPE_PRIORITY_JUNCTION: 00124 junction = buildLogicJunction(); 00125 break; 00126 case NODETYPE_INTERNAL: 00127 #ifdef HAVE_INTERNAL_LANES 00128 if (MSGlobals::gUsingInternalLanes) { 00129 junction = buildInternalJunction(); 00130 } 00131 #endif 00132 break; 00133 default: 00134 throw InvalidArgument("False junction logic type."); 00135 } 00136 if (junction != 0) { 00137 if (!myJunctions->add(myActiveID, junction)) { 00138 throw InvalidArgument("Another junction with the id '" + myActiveID + "' exists."); 00139 } 00140 } 00141 } 00142 00143 00144 MSJunctionControl* 00145 NLJunctionControlBuilder::build() const { 00146 MSJunctionControl* js = myJunctions; 00147 myJunctions = 0; 00148 return js; 00149 } 00150 00151 00152 MSJunction* 00153 NLJunctionControlBuilder::buildNoLogicJunction() { 00154 return new MSNoLogicJunction(myActiveID, myPosition, myShape, myActiveIncomingLanes 00155 #ifdef HAVE_INTERNAL_LANES 00156 , myActiveInternalLanes 00157 #endif 00158 ); 00159 } 00160 00161 00162 MSJunction* 00163 NLJunctionControlBuilder::buildLogicJunction() throw(InvalidArgument) { 00164 MSJunctionLogic* jtype = getJunctionLogicSecure(); 00165 // build the junction 00166 return new MSRightOfWayJunction(myActiveID, myPosition, myShape, myActiveIncomingLanes, 00167 #ifdef HAVE_INTERNAL_LANES 00168 myActiveInternalLanes, 00169 #endif 00170 jtype); 00171 } 00172 00173 00174 #ifdef HAVE_INTERNAL_LANES 00175 MSJunction* 00176 NLJunctionControlBuilder::buildInternalJunction() { 00177 // build the junction 00178 return new MSInternalJunction(myActiveID, myPosition, myShape, myActiveIncomingLanes, 00179 myActiveInternalLanes); 00180 } 00181 #endif 00182 00183 00184 MSJunctionLogic* 00185 NLJunctionControlBuilder::getJunctionLogicSecure() throw(InvalidArgument) { 00186 // get and check the junction logic 00187 if (myLogics.find(myActiveID) == myLogics.end()) { 00188 throw InvalidArgument("Missing junction logic '" + myActiveID + "'."); 00189 } 00190 return myLogics[myActiveID]; 00191 } 00192 00193 00194 MSTLLogicControl::TLSLogicVariants& 00195 NLJunctionControlBuilder::getTLLogic(const std::string& id) const throw(InvalidArgument) { 00196 return getTLLogicControlToUse().get(id); 00197 } 00198 00199 00200 void 00201 NLJunctionControlBuilder::closeTrafficLightLogic() throw(InvalidArgument, ProcessError) { 00202 if (myActiveProgram == "off") { 00203 if (myAbsDuration > 0) { 00204 throw InvalidArgument("The off program for TLS '" + myActiveKey + "' has phases."); 00205 } 00206 if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, 00207 new MSOffTrafficLightLogic(getTLLogicControlToUse(), myActiveKey))) { 00208 throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists."); 00209 } 00210 return; 00211 } 00212 if (myAbsDuration == 0) { 00213 throw InvalidArgument("TLS program '" + myActiveProgram + "' for TLS '" + myActiveKey + "' has a duration of 0."); 00214 } 00215 // compute the initial step and first switch time of the tls-logic 00216 unsigned int step = 0; 00217 SUMOTime firstEventOffset = 0; 00218 SUMOTime offset = (myNet.getCurrentTimeStep() + myOffset % myAbsDuration) % myAbsDuration; 00219 MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin(); 00220 while (offset >= (*i)->duration) { 00221 step++; 00222 offset -= (*i)->duration; 00223 ++i; 00224 } 00225 firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep(); 00226 00227 // 00228 if (myActiveProgram == "") { 00229 myActiveProgram = "default"; 00230 } 00231 MSTrafficLightLogic* tlLogic = 0; 00232 // build the tls-logic in dependance to its type 00233 switch (myLogicType) { 00234 case TLTYPE_ACTUATED: 00235 tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(), 00236 myActiveKey, myActiveProgram, 00237 myActivePhases, step, firstEventOffset, myAdditionalParameter); 00238 break; 00239 case TLTYPE_AGENT: 00240 tlLogic = new MSAgentbasedTrafficLightLogic(getTLLogicControlToUse(), 00241 myActiveKey, myActiveProgram, 00242 myActivePhases, step, firstEventOffset, myAdditionalParameter); 00243 break; 00244 case TLTYPE_STATIC: 00245 tlLogic = 00246 new MSSimpleTrafficLightLogic(getTLLogicControlToUse(), 00247 myActiveKey, myActiveProgram, 00248 myActivePhases, step, firstEventOffset); 00249 tlLogic->setParameter(myAdditionalParameter); 00250 } 00251 TLInitInfo ii; 00252 ii.logic = tlLogic; 00253 ii.params = myAdditionalParameter; 00254 myJunctions2PostLoadInit.push_back(ii); 00255 myActivePhases.clear(); 00256 if (tlLogic != 0) { 00257 try { 00258 if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) { 00259 throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists."); 00260 } 00261 tlLogic->setParameter(myAdditionalParameter); 00262 tlLogic->init(myDetectorBuilder); 00263 } catch (InvalidArgument&) { 00264 delete tlLogic; 00265 throw; 00266 } 00267 } 00268 } 00269 00270 00271 void 00272 NLJunctionControlBuilder::initJunctionLogic(const std::string& id) { 00273 myActiveKey = id; 00274 myActiveProgram = ""; 00275 myActiveLogic.clear(); 00276 myActiveFoes.clear(); 00277 myActiveConts.reset(); 00278 myRequestSize = NO_REQUEST_SIZE; // seems not to be used 00279 myRequestItemNumber = 0; 00280 myCurrentHasError = false; 00281 } 00282 00283 00284 void 00285 NLJunctionControlBuilder::addLogicItem(int request, 00286 const std::string& response, 00287 const std::string& foes, 00288 bool cont) throw(InvalidArgument) { 00289 if (myCurrentHasError) { 00290 // had an error 00291 return; 00292 } 00293 if (request > 63) { 00294 // bad request 00295 myCurrentHasError = true; 00296 throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network."); 00297 } 00298 if (myRequestSize == NO_REQUEST_SIZE) { 00299 // initialize 00300 myRequestSize = (int)response.size(); 00301 } 00302 if (response.size() != myRequestSize) { 00303 myCurrentHasError = true; 00304 throw InvalidArgument("Invalid response size " + toString(response.size()) + 00305 " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")"); 00306 } 00307 if (foes.size() != myRequestSize) { 00308 myCurrentHasError = true; 00309 throw InvalidArgument("Invalid foes size " + toString(foes.size()) + 00310 " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")"); 00311 } 00312 // assert that the logicitems come ordered by their request index 00313 assert(myActiveLogic.size() == (size_t) request); 00314 assert(myActiveFoes.size() == (size_t) request); 00315 // add the read response for the given request index 00316 myActiveLogic.push_back(std::bitset<64>(response)); 00317 // add the read junction-internal foes for the given request index 00318 myActiveFoes.push_back(std::bitset<64>(foes)); 00319 // add whether the vehicle may drive a little bit further 00320 myActiveConts.set(request, cont); 00321 // increse number of set information 00322 myRequestItemNumber++; 00323 } 00324 00325 00326 void 00327 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID, 00328 TrafficLightType type, SUMOTime offset) { 00329 myActiveKey = id; 00330 myActiveProgram = programID; 00331 myActivePhases.clear(); 00332 myAbsDuration = 0; 00333 myRequestSize = NO_REQUEST_SIZE; 00334 myLogicType = type; 00335 myOffset = offset; 00336 myAdditionalParameter.clear(); 00337 } 00338 00339 00340 void 00341 NLJunctionControlBuilder::addPhase(SUMOTime duration, const std::string& state, 00342 int minDuration, int maxDuration) { 00343 // build and add the phase definition to the list 00344 myActivePhases.push_back(new MSPhaseDefinition(duration, minDuration, maxDuration, state)); 00345 // add phase duration to the absolute duration 00346 myAbsDuration += duration; 00347 } 00348 00349 00350 void 00351 NLJunctionControlBuilder::closeJunctionLogic() throw(InvalidArgument) { 00352 if (myRequestSize == NO_REQUEST_SIZE) { 00353 // We have a legacy network. junction element did not contain logicitems; read the logic later 00354 return; 00355 } 00356 if (myCurrentHasError) { 00357 // had an error before... 00358 return; 00359 } 00360 if (myRequestItemNumber != myRequestSize) { 00361 throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious."); 00362 } 00363 if (myLogics.count(myActiveKey) > 0) { 00364 throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice."); 00365 } 00366 MSJunctionLogic* logic = new MSBitsetLogic(myRequestSize, 00367 new MSBitsetLogic::Logic(myActiveLogic), 00368 new MSBitsetLogic::Foes(myActiveFoes), 00369 myActiveConts); 00370 myLogics[myActiveKey] = logic; 00371 } 00372 00373 00374 MSTLLogicControl* 00375 NLJunctionControlBuilder::buildTLLogics() const { 00376 if (!myLogicControl->closeNetworkReading()) { 00377 throw ProcessError("Traffic lights could not be built."); 00378 } 00379 MSTLLogicControl* ret = myLogicControl; 00380 myLogicControl = 0; 00381 return ret; 00382 } 00383 00384 00385 void 00386 NLJunctionControlBuilder::addParam(const std::string& key, 00387 const std::string& value) { 00388 myAdditionalParameter[key] = value; 00389 } 00390 00391 00392 MSTLLogicControl& 00393 NLJunctionControlBuilder::getTLLogicControlToUse() const { 00394 if (myLogicControl != 0) { 00395 return *myLogicControl; 00396 } 00397 return myNet.getTLSControl(); 00398 } 00399 00400 00401 const std::string& 00402 NLJunctionControlBuilder::getActiveKey() const { 00403 return myActiveKey; 00404 } 00405 00406 00407 const std::string& 00408 NLJunctionControlBuilder::getActiveSubKey() const { 00409 return myActiveProgram; 00410 } 00411 00412 00413 /****************************************************************************/