SUMO - Simulation of Urban MObility

NLJunctionControlBuilder.cpp

Go to the documentation of this file.
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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines