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     // 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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines