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