SUMO - Simulation of Urban MObility

NLJunctionControlBuilder.cpp

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