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 // a positive offset delays all phases by x (advance by absDuration - x) while a negative offset advances all phases by x seconds 00217 // @note The implementation of % for negative values is implementation defined in ISO1998 00218 SUMOTime offset; // the time to run the traffic light in advance 00219 if (myOffset >= 0) { 00220 offset = (myNet.getCurrentTimeStep() + myAbsDuration - (myOffset % myAbsDuration)) % myAbsDuration; 00221 } else { 00222 offset = (myNet.getCurrentTimeStep() + ((-myOffset) % myAbsDuration)) % myAbsDuration; 00223 } 00224 unsigned int step = 0; 00225 SUMOTime firstEventOffset = 0; 00226 MSSimpleTrafficLightLogic::Phases::const_iterator i = myActivePhases.begin(); 00227 while (offset >= (*i)->duration) { 00228 step++; 00229 offset -= (*i)->duration; 00230 ++i; 00231 } 00232 firstEventOffset = (*i)->duration - offset + myNet.getCurrentTimeStep(); 00233 00234 // 00235 if (myActiveProgram == "") { 00236 myActiveProgram = "default"; 00237 } 00238 MSTrafficLightLogic* tlLogic = 0; 00239 // build the tls-logic in dependance to its type 00240 switch (myLogicType) { 00241 case TLTYPE_ACTUATED: 00242 tlLogic = new MSActuatedTrafficLightLogic(getTLLogicControlToUse(), 00243 myActiveKey, myActiveProgram, 00244 myActivePhases, step, firstEventOffset, myAdditionalParameter); 00245 break; 00246 case TLTYPE_AGENT: 00247 tlLogic = new MSAgentbasedTrafficLightLogic(getTLLogicControlToUse(), 00248 myActiveKey, myActiveProgram, 00249 myActivePhases, step, firstEventOffset, myAdditionalParameter); 00250 break; 00251 case TLTYPE_STATIC: 00252 tlLogic = 00253 new MSSimpleTrafficLightLogic(getTLLogicControlToUse(), 00254 myActiveKey, myActiveProgram, 00255 myActivePhases, step, firstEventOffset); 00256 tlLogic->setParameter(myAdditionalParameter); 00257 } 00258 TLInitInfo ii; 00259 ii.logic = tlLogic; 00260 ii.params = myAdditionalParameter; 00261 myJunctions2PostLoadInit.push_back(ii); 00262 myActivePhases.clear(); 00263 if (tlLogic != 0) { 00264 try { 00265 if (!getTLLogicControlToUse().add(myActiveKey, myActiveProgram, tlLogic)) { 00266 throw InvalidArgument("Another logic with id '" + myActiveKey + "' and subid '" + myActiveProgram + "' exists."); 00267 } 00268 tlLogic->setParameter(myAdditionalParameter); 00269 tlLogic->init(myDetectorBuilder); 00270 } catch (InvalidArgument&) { 00271 delete tlLogic; 00272 throw; 00273 } 00274 } 00275 } 00276 00277 00278 void 00279 NLJunctionControlBuilder::initJunctionLogic(const std::string& id) { 00280 myActiveKey = id; 00281 myActiveProgram = ""; 00282 myActiveLogic.clear(); 00283 myActiveFoes.clear(); 00284 myActiveConts.reset(); 00285 myRequestSize = NO_REQUEST_SIZE; // seems not to be used 00286 myRequestItemNumber = 0; 00287 myCurrentHasError = false; 00288 } 00289 00290 00291 void 00292 NLJunctionControlBuilder::addLogicItem(int request, 00293 const std::string& response, 00294 const std::string& foes, 00295 bool cont) throw(InvalidArgument) { 00296 if (myCurrentHasError) { 00297 // had an error 00298 return; 00299 } 00300 if (request > 63) { 00301 // bad request 00302 myCurrentHasError = true; 00303 throw InvalidArgument("Junction logic '" + myActiveKey + "' is larger than allowed; recheck the network."); 00304 } 00305 if (myRequestSize == NO_REQUEST_SIZE) { 00306 // initialize 00307 myRequestSize = (int)response.size(); 00308 } 00309 if (response.size() != myRequestSize) { 00310 myCurrentHasError = true; 00311 throw InvalidArgument("Invalid response size " + toString(response.size()) + 00312 " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")"); 00313 } 00314 if (foes.size() != myRequestSize) { 00315 myCurrentHasError = true; 00316 throw InvalidArgument("Invalid foes size " + toString(foes.size()) + 00317 " in Junction logic '" + myActiveKey + "' (expected " + toString(myRequestSize) + ")"); 00318 } 00319 // assert that the logicitems come ordered by their request index 00320 assert(myActiveLogic.size() == (size_t) request); 00321 assert(myActiveFoes.size() == (size_t) request); 00322 // add the read response for the given request index 00323 myActiveLogic.push_back(std::bitset<64>(response)); 00324 // add the read junction-internal foes for the given request index 00325 myActiveFoes.push_back(std::bitset<64>(foes)); 00326 // add whether the vehicle may drive a little bit further 00327 myActiveConts.set(request, cont); 00328 // increse number of set information 00329 myRequestItemNumber++; 00330 } 00331 00332 00333 void 00334 NLJunctionControlBuilder::initTrafficLightLogic(const std::string& id, const std::string& programID, 00335 TrafficLightType type, SUMOTime offset) { 00336 myActiveKey = id; 00337 myActiveProgram = programID; 00338 myActivePhases.clear(); 00339 myAbsDuration = 0; 00340 myRequestSize = NO_REQUEST_SIZE; 00341 myLogicType = type; 00342 myOffset = offset; 00343 myAdditionalParameter.clear(); 00344 } 00345 00346 00347 void 00348 NLJunctionControlBuilder::addPhase(SUMOTime duration, const std::string& state, 00349 int minDuration, int maxDuration) { 00350 // build and add the phase definition to the list 00351 myActivePhases.push_back(new MSPhaseDefinition(duration, minDuration, maxDuration, state)); 00352 // add phase duration to the absolute duration 00353 myAbsDuration += duration; 00354 } 00355 00356 00357 void 00358 NLJunctionControlBuilder::closeJunctionLogic() throw(InvalidArgument) { 00359 if (myRequestSize == NO_REQUEST_SIZE) { 00360 // We have a legacy network. junction element did not contain logicitems; read the logic later 00361 return; 00362 } 00363 if (myCurrentHasError) { 00364 // had an error before... 00365 return; 00366 } 00367 if (myRequestItemNumber != myRequestSize) { 00368 throw InvalidArgument("The description for the junction logic '" + myActiveKey + "' is malicious."); 00369 } 00370 if (myLogics.count(myActiveKey) > 0) { 00371 throw InvalidArgument("Junction logic '" + myActiveKey + "' was defined twice."); 00372 } 00373 MSJunctionLogic* logic = new MSBitsetLogic(myRequestSize, 00374 new MSBitsetLogic::Logic(myActiveLogic), 00375 new MSBitsetLogic::Foes(myActiveFoes), 00376 myActiveConts); 00377 myLogics[myActiveKey] = logic; 00378 } 00379 00380 00381 MSTLLogicControl* 00382 NLJunctionControlBuilder::buildTLLogics() const { 00383 if (!myLogicControl->closeNetworkReading()) { 00384 throw ProcessError("Traffic lights could not be built."); 00385 } 00386 MSTLLogicControl* ret = myLogicControl; 00387 myLogicControl = 0; 00388 return ret; 00389 } 00390 00391 00392 void 00393 NLJunctionControlBuilder::addParam(const std::string& key, 00394 const std::string& value) { 00395 myAdditionalParameter[key] = value; 00396 } 00397 00398 00399 MSTLLogicControl& 00400 NLJunctionControlBuilder::getTLLogicControlToUse() const { 00401 if (myLogicControl != 0) { 00402 return *myLogicControl; 00403 } 00404 return myNet.getTLSControl(); 00405 } 00406 00407 00408 const std::string& 00409 NLJunctionControlBuilder::getActiveKey() const { 00410 return myActiveKey; 00411 } 00412 00413 00414 const std::string& 00415 NLJunctionControlBuilder::getActiveSubKey() const { 00416 return myActiveProgram; 00417 } 00418 00419 00420 /****************************************************************************/