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