|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Class for loading trip amount definitions and route generation 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 <cassert> 00031 #include <string> 00032 #include <algorithm> 00033 #include <utils/options/OptionsCont.h> 00034 #include <utils/common/UtilExceptions.h> 00035 #include <utils/common/StringTokenizer.h> 00036 #include <utils/common/MsgHandler.h> 00037 #include <utils/common/ToString.h> 00038 #include <utils/common/RandHelper.h> 00039 #include <utils/common/StringUtils.h> 00040 #include "RORouteDef.h" 00041 #include "RONet.h" 00042 #include "RORouteDef_OrigDest.h" 00043 #include "RORDGenerator_ODAmounts.h" 00044 #include "ROVehicle.h" 00045 #include "RORouteDef_Complete.h" 00046 #include "ROAbstractRouteDefLoader.h" 00047 #include <utils/xml/SUMOVehicleParserHelper.h> 00048 00049 #ifdef CHECK_MEMORY_LEAKS 00050 #include <foreign/nvwa/debug_new.h> 00051 #endif // CHECK_MEMORY_LEAKS 00052 00053 00054 // =========================================================================== 00055 // method definitions 00056 // =========================================================================== 00057 /* ------------------------------------------------------------------------- 00058 * RORDGenerator_ODAmounts::FlowDef - methods 00059 * ----------------------------------------------------------------------- */ 00060 RORDGenerator_ODAmounts::FlowDef::FlowDef(ROVehicle* vehicle, 00061 SUMOVTypeParameter* type, 00062 RORouteDef* route, 00063 SUMOTime intBegin, 00064 SUMOTime intEnd, 00065 unsigned int vehicles2insert, 00066 bool randomize) 00067 : myVehicle(vehicle), myVehicleType(type), myRoute(route), 00068 myIntervalBegin(intBegin), myIntervalEnd(intEnd), 00069 myVehicle2InsertNumber(vehicles2insert), myInserted(0), myRandom(randomize) { 00070 assert(myIntervalBegin<myIntervalEnd); 00071 if (myRandom) { 00072 SUMOTime period = myIntervalEnd - myIntervalBegin; 00073 myDepartures.reserve(myVehicle2InsertNumber); 00074 for (size_t i=0; i<myVehicle2InsertNumber; ++i) { 00075 SUMOTime departure = myIntervalBegin + ((int)(RandHelper::rand(period) / DELTA_T)) * DELTA_T; 00076 myDepartures.push_back(departure); 00077 } 00078 sort(myDepartures.begin(), myDepartures.end()); 00079 reverse(myDepartures.begin(), myDepartures.end()); 00080 } 00081 } 00082 00083 00084 RORDGenerator_ODAmounts::FlowDef::~FlowDef() { 00085 delete myVehicle; 00086 } 00087 00088 00089 bool 00090 RORDGenerator_ODAmounts::FlowDef::applicableForTime(SUMOTime t) const { 00091 return myIntervalBegin<=t&&myIntervalEnd>t; 00092 } 00093 00094 00095 void 00096 RORDGenerator_ODAmounts::FlowDef::addRoutes(RONet& net, SUMOTime t) { 00097 assert(myIntervalBegin<=t&&myIntervalEnd>=t); 00098 if (!myRandom) { 00099 unsigned int absPerEachStep = myVehicle2InsertNumber / ((myIntervalEnd-myIntervalBegin) / DELTA_T); 00100 for (unsigned int i=0; i<absPerEachStep; i++) { 00101 addSingleRoute(net, t); 00102 } 00103 // fraction 00104 SUMOReal toInsert = (SUMOReal) myVehicle2InsertNumber / (SUMOReal)(myIntervalEnd-myIntervalBegin) * (SUMOReal)(t-myIntervalBegin+(SUMOReal)DELTA_T/2.); 00105 if (toInsert>myInserted) { 00106 addSingleRoute(net, t); 00107 } 00108 } else { 00109 while (myDepartures.size() > 0 && myDepartures.back() < t+DELTA_T) { 00110 addSingleRoute(net, myDepartures.back()); 00111 myDepartures.pop_back(); 00112 } 00113 } 00114 } 00115 00116 00117 void 00118 RORDGenerator_ODAmounts::FlowDef::addSingleRoute(RONet& net, SUMOTime t) { 00119 std::string id = myVehicle->getID() + "_" + toString<unsigned int>(myInserted); 00120 RORouteDef* rd = myRoute->copy(id); 00121 net.addRouteDef(rd); 00122 ROVehicle* veh = myVehicle->copy(id, t, rd); 00123 net.addVehicle(id, veh); 00124 ++myInserted; 00125 } 00126 00127 00128 SUMOTime 00129 RORDGenerator_ODAmounts::FlowDef::getIntervalEnd() const { 00130 return myIntervalEnd; 00131 } 00132 00133 00134 /* ------------------------------------------------------------------------- 00135 * RORDGenerator_ODAmounts - methods 00136 * ----------------------------------------------------------------------- */ 00137 RORDGenerator_ODAmounts::RORDGenerator_ODAmounts(RONet& net, 00138 SUMOTime begin, 00139 SUMOTime end, 00140 bool emptyDestinationsAllowed, 00141 bool randomize, 00142 const std::string& fileName) throw(ProcessError) 00143 : RORDLoader_TripDefs(net, begin, end, emptyDestinationsAllowed, false, fileName), 00144 myRandom(randomize), 00145 myHaveWarnedAboutDeprecatedNumber(false) { 00146 // read the complete file on initialisation 00147 myParser->parseReset(myToken); 00148 myParser->parse(getFileName().c_str()); 00149 myDepartureTime = myBegin; 00150 } 00151 00152 00153 RORDGenerator_ODAmounts::~RORDGenerator_ODAmounts() throw() { 00154 for (FlowDefV::const_iterator i=myFlows.begin(); i!=myFlows.end(); i++) { 00155 delete(*i); 00156 } 00157 } 00158 00159 00160 bool 00161 RORDGenerator_ODAmounts::readRoutesAtLeastUntil(SUMOTime until, bool skipping) throw(ProcessError) { 00162 UNUSED_PARAMETER(skipping); 00163 // skip routes before begin 00164 if (until<myBegin) { 00165 myDepartureTime = until; 00166 return true; 00167 } 00168 // build route definitions for the given timestep 00169 buildRoutes(until); 00170 return true; 00171 } 00172 00173 00174 void 00175 RORDGenerator_ODAmounts::buildRoutes(SUMOTime until) throw() { 00176 SUMOTime t; 00177 for (t=myDepartureTime; t<until+1; t+=DELTA_T) { 00178 buildForTimeStep(t); 00179 } 00180 myDepartureTime = t; 00181 } 00182 00183 00184 void 00185 RORDGenerator_ODAmounts::buildForTimeStep(SUMOTime time) throw() { 00186 if (time<myBegin||time>=myEnd) { 00187 return; 00188 } 00189 myEnded = true; 00190 for (FlowDefV::const_iterator i=myFlows.begin(); i!=myFlows.end(); i++) { 00191 FlowDef* fd = *i; 00192 // skip flow definitions not valid for the current time 00193 if (fd->applicableForTime(time)) { 00194 fd->addRoutes(myNet, time); 00195 } 00196 // check whether any further exists 00197 if (fd->getIntervalEnd()>time) { 00198 myEnded = false; 00199 } 00200 } 00201 } 00202 00203 00204 void 00205 RORDGenerator_ODAmounts::myStartElement(int element, 00206 const SUMOSAXAttributes& attrs) throw(ProcessError) { 00207 RORDLoader_TripDefs::myStartElement(element, attrs); 00208 if (element == SUMO_TAG_FLOW) { 00209 parseFlowAmountDef(attrs); 00210 } else if (element == SUMO_TAG_INTERVAL) { 00211 parseInterval(attrs); 00212 } 00213 } 00214 00215 00216 void 00217 RORDGenerator_ODAmounts::parseFlowAmountDef(const SUMOSAXAttributes& attrs) throw(ProcessError) { 00218 // get the vehicle id, the edges, the speed and position and 00219 // the departure time and other information 00220 std::string id = getVehicleID(attrs); 00221 if (myKnownIDs.find(id)!=myKnownIDs.end()) { 00222 throw ProcessError("The id '" + id + "' appears twice within the flow descriptions.'"); 00223 } 00224 myKnownIDs.insert(id); // !!! a local storage is not save 00225 myBeginEdge = getEdge(attrs, "origin", SUMO_ATTR_FROM, id, false); 00226 myEndEdge = getEdge(attrs, "destination", 00227 SUMO_ATTR_TO, id, myEmptyDestinationsAllowed); 00228 try { 00229 myParameter = SUMOVehicleParserHelper::parseVehicleAttributes(attrs, true, true); 00230 } catch (ProcessError& e) { 00231 throw ProcessError(StringUtils::replace(e.what(), "''", id.c_str())); 00232 } 00233 myParameter->id = id; 00234 bool ok = true; 00235 myIntervalBegin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, id.c_str(), ok, myUpperIntervalBegin); 00236 myIntervalEnd = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, id.c_str(), ok, myUpperIntervalEnd); 00237 if (attrs.hasAttribute(SUMO_ATTR_NUMBER)) { 00238 myVehicle2InsertNumber = attrs.getIntReporting(SUMO_ATTR_NUMBER, id.c_str(), ok); 00239 } else if (attrs.hasAttribute(SUMO_ATTR_NO__DEPRECATED)) { 00240 if (!myHaveWarnedAboutDeprecatedNumber) { 00241 myHaveWarnedAboutDeprecatedNumber = true; 00242 WRITE_WARNING("'" + toString(SUMO_ATTR_NO__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_ATTR_NUMBER) + "' instead."); 00243 } 00244 myVehicle2InsertNumber = attrs.getIntReporting(SUMO_ATTR_NO__DEPRECATED, id.c_str(), ok); 00245 } else { 00246 throw ProcessError("Flow '" + id + "' has no vehicle number."); 00247 } 00248 if (!ok) { 00249 throw ProcessError(); 00250 } 00251 if (myIntervalEnd<=myIntervalBegin) { 00252 throw ProcessError("The interval must be larger than 0.\n The current values are: begin=" + toString<unsigned int>(myIntervalBegin) + " end=" + toString<unsigned int>(myIntervalEnd)); 00253 } 00254 } 00255 00256 00257 void 00258 RORDGenerator_ODAmounts::parseInterval(const SUMOSAXAttributes& attrs) { 00259 bool ok = true; 00260 myUpperIntervalBegin = attrs.getOptSUMOTimeReporting(SUMO_ATTR_BEGIN, 0, ok, -1); // !!!really optional ? 00261 myUpperIntervalEnd = attrs.getOptSUMOTimeReporting(SUMO_ATTR_END, 0, ok, -1); // !!!really optional ? 00262 } 00263 00264 00265 void 00266 RORDGenerator_ODAmounts::myEndElement(int element) throw(ProcessError) { 00267 RORDLoader_TripDefs::myEndElement(element); 00268 if (element == SUMO_TAG_FLOW) { 00269 myEndFlowAmountDef(); 00270 } else if (element == SUMO_TAG_INTERVAL) { 00271 myEndInterval(); 00272 } 00273 } 00274 00275 00276 void 00277 RORDGenerator_ODAmounts::myEndInterval() { 00278 myUpperIntervalBegin = 0; // !!! was -1 00279 myUpperIntervalEnd = 0; // !!! was: -1 00280 } 00281 00282 00283 void 00284 RORDGenerator_ODAmounts::myEndFlowAmountDef() { 00285 if (!MsgHandler::getErrorInstance()->wasInformed()) { 00286 00287 if (myIntervalEnd<myBegin) { 00288 return; 00289 } 00290 // add the vehicle type, the vehicle and the route to the net 00291 RGBColor* col = myParameter->wasSet(VEHPARS_COLOR_SET) ? new RGBColor(myParameter->color) : 0; 00292 RORouteDef* route = new RORouteDef_OrigDest(myParameter->id, col, myBeginEdge, myEndEdge); 00293 SUMOVTypeParameter* type = myNet.getVehicleTypeSecure(myParameter->vtypeid); 00294 // check whether any errors occured 00295 if (MsgHandler::getErrorInstance()->wasInformed()) { 00296 return; 00297 } 00298 // build the vehicle 00299 if (myNet.addRouteDef(route)) { 00300 myNextRouteRead = true; 00301 ROVehicle* vehicle = new ROVehicle(*myParameter, route, type); 00302 // add to the container 00303 FlowDef* fd = new FlowDef(vehicle, type, route, myIntervalBegin, myIntervalEnd, myVehicle2InsertNumber, myRandom); 00304 myFlows.push_back(fd); 00305 } else { 00306 WRITE_ERROR("The vehicle '" + myParameter->id + "' occurs at least twice."); 00307 delete route; 00308 } 00309 delete myParameter; 00310 myParameter = 0; 00311 } 00312 } 00313 00314 00315 /****************************************************************************/ 00316