SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // An O/D (origin/destination) matrix 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 "ODMatrix.h" 00034 #include <utils/options/OptionsCont.h> 00035 #include <utils/common/StdDefs.h> 00036 #include <utils/common/MsgHandler.h> 00037 #include <utils/common/ToString.h> 00038 #include <iostream> 00039 #include <algorithm> 00040 #include <list> 00041 #include <iterator> 00042 #include <utils/common/RandHelper.h> 00043 #include <utils/iodevices/OutputDevice.h> 00044 00045 #ifdef CHECK_MEMORY_LEAKS 00046 #include <foreign/nvwa/debug_new.h> 00047 #endif // CHECK_MEMORY_LEAKS 00048 00049 00050 // =========================================================================== 00051 // method definitions 00052 // =========================================================================== 00053 ODMatrix::ODMatrix(const ODDistrictCont& dc) 00054 : myDistricts(dc), myNoLoaded(0), myNoWritten(0), myNoDiscarded(0) {} 00055 00056 00057 ODMatrix::~ODMatrix() { 00058 for (CellVector::iterator i = myContainer.begin(); i != myContainer.end(); ++i) { 00059 delete *i; 00060 } 00061 myContainer.clear(); 00062 } 00063 00064 00065 void 00066 ODMatrix::add(SUMOReal vehicleNumber, SUMOTime begin, 00067 SUMOTime end, const std::string& origin, const std::string& destination, 00068 const std::string& vehicleType) { 00069 myNoLoaded += vehicleNumber; 00070 if (myDistricts.get(origin) == 0 && myDistricts.get(destination) == 0) { 00071 WRITE_WARNING("Missing origin '" + origin + "' and destination '" + destination + "' (" + toString(vehicleNumber) + " vehicles)."); 00072 } else if (myDistricts.get(origin) == 0 && vehicleNumber > 0) { 00073 WRITE_ERROR("Missing origin '" + origin + "' (" + toString(vehicleNumber) + " vehicles)."); 00074 myNoDiscarded += vehicleNumber; 00075 } else if (myDistricts.get(destination) == 0 && vehicleNumber > 0) { 00076 WRITE_ERROR("Missing destination '" + destination + "' (" + toString(vehicleNumber) + " vehicles)."); 00077 myNoDiscarded += vehicleNumber; 00078 } else { 00079 if (myDistricts.get(origin)->sourceNumber() == 0) { 00080 WRITE_ERROR("District '" + origin + "' has no source."); 00081 myNoDiscarded += vehicleNumber; 00082 } else if (myDistricts.get(destination)->sinkNumber() == 0) { 00083 WRITE_ERROR("District '" + destination + "' has no sink."); 00084 myNoDiscarded += vehicleNumber; 00085 } else { 00086 ODCell* cell = new ODCell(); 00087 cell->begin = begin; 00088 cell->end = end; 00089 cell->origin = origin; 00090 cell->destination = destination; 00091 cell->vehicleType = vehicleType; 00092 cell->vehicleNumber = vehicleNumber; 00093 myContainer.push_back(cell); 00094 } 00095 } 00096 } 00097 00098 00099 SUMOReal 00100 ODMatrix::computeDeparts(ODCell* cell, 00101 size_t& vehName, std::vector<ODVehicle> &into, 00102 bool uniform, const std::string& prefix) { 00103 int vehicles2insert = (int) cell->vehicleNumber; 00104 // compute whether the fraction forces an additional vehicle insertion 00105 SUMOReal mrand = RandHelper::rand(); 00106 SUMOReal mprob = (SUMOReal) cell->vehicleNumber - (SUMOReal) vehicles2insert; 00107 if (mrand < mprob) { 00108 vehicles2insert++; 00109 } 00110 00111 SUMOReal offset = (SUMOReal)(cell->end - cell->begin) / (SUMOReal) vehicles2insert / (SUMOReal) 2.; 00112 for (int i = 0; i < vehicles2insert; ++i) { 00113 ODVehicle veh; 00114 veh.id = prefix + toString(vehName++); 00115 00116 if (uniform) { 00117 veh.depart = (unsigned int)(offset + cell->begin + ((SUMOReal)(cell->end - cell->begin) * (SUMOReal) i / (SUMOReal) vehicles2insert)); 00118 } else { 00119 veh.depart = (unsigned int) RandHelper::rand((int) cell->begin, (int) cell->end); 00120 } 00121 00122 veh.from = myDistricts.getRandomSourceFromDistrict(cell->origin); 00123 veh.to = myDistricts.getRandomSinkFromDistrict(cell->destination); 00124 veh.cell = cell; 00125 into.push_back(veh); 00126 } 00127 return cell->vehicleNumber - vehicles2insert; 00128 } 00129 00130 00131 void 00132 ODMatrix::write(SUMOTime begin, SUMOTime end, 00133 OutputDevice& dev, bool uniform, bool noVtype, 00134 const std::string& prefix, bool stepLog) { 00135 if (myContainer.size() == 0) { 00136 return; 00137 } 00138 OptionsCont& oc = OptionsCont::getOptions(); 00139 std::map<std::pair<std::string, std::string>, SUMOReal> fractionLeft; 00140 size_t vehName = 0; 00141 sort(myContainer.begin(), myContainer.end(), cell_by_begin_sorter()); 00142 // recheck begin time 00143 ODCell* first = *myContainer.begin(); 00144 begin = MAX2(begin, first->begin); 00145 CellVector::iterator next = myContainer.begin(); 00146 std::vector<ODVehicle> vehicles; 00147 // go through the time steps 00148 for (SUMOTime t = begin; t != end; t++) { 00149 if (stepLog) { 00150 std::cout << "Parsing time " + toString(t) << '\r'; 00151 } 00152 // recheck whether a new cell got valid 00153 bool changed = false; 00154 while (next != myContainer.end() && (*next)->begin <= t && (*next)->end > t) { 00155 std::pair<std::string, std::string> odID = std::make_pair((*next)->origin, (*next)->destination); 00156 // check whether the current cell must be extended by the last fraction 00157 if (fractionLeft.find(odID) != fractionLeft.end()) { 00158 (*next)->vehicleNumber += fractionLeft[odID]; 00159 fractionLeft[odID] = 0; 00160 } 00161 // get the new departures (into tmp) 00162 std::vector<ODVehicle> tmp; 00163 SUMOReal fraction = computeDeparts(*next, vehName, tmp, uniform, prefix); 00164 // copy new departures if any 00165 if (tmp.size() != 0) { 00166 copy(tmp.begin(), tmp.end(), back_inserter(vehicles)); 00167 changed = true; 00168 } 00169 // save the fraction 00170 if (fraction != 0) { 00171 if (fractionLeft.find(odID) == fractionLeft.end()) { 00172 fractionLeft[odID] = fraction; 00173 } else { 00174 fractionLeft[odID] += fraction; 00175 } 00176 } 00177 // 00178 ++next; 00179 } 00180 if (changed) { 00181 sort(vehicles.begin(), vehicles.end(), descending_departure_comperator()); 00182 } 00183 std::vector<ODVehicle>::reverse_iterator i = vehicles.rbegin(); 00184 for (; i != vehicles.rend() && (*i).depart == t; ++i) { 00185 myNoWritten++; 00186 dev.openTag("trip") << " id=\"" << (*i).id << "\" depart=\"" << t << ".00\" " 00187 << "from=\"" << (*i).from << "\" " 00188 << "to=\"" << (*i).to << "\""; 00189 if (!noVtype && (*i).cell->vehicleType.length() != 0) { 00190 dev << " type=\"" << (*i).cell->vehicleType << "\""; 00191 } 00192 dev << " fromTaz=\"" << (*i).cell->origin << "\""; 00193 dev << " toTaz=\"" << (*i).cell->destination << "\""; 00194 if (oc.isSet("departlane") && oc.getString("departlane") != "default") { 00195 dev << " departLane=\"" << oc.getString("departlane") << "\""; 00196 } 00197 if (oc.isSet("departpos")) { 00198 dev << " departPos=\"" << oc.getString("departpos") << "\""; 00199 } 00200 if (oc.isSet("departspeed") && oc.getString("departspeed") != "default") { 00201 dev << " departSpeed=\"" << oc.getString("departspeed") << "\""; 00202 } 00203 if (oc.isSet("arrivallane")) { 00204 dev << " arrivalLane=\"" << oc.getString("arrivallane") << "\""; 00205 } 00206 if (oc.isSet("arrivalpos")) { 00207 dev << " arrivalPos=\"" << oc.getString("arrivalpos") << "\""; 00208 } 00209 if (oc.isSet("arrivalspeed")) { 00210 dev << " arrivalSpeed=\"" << oc.getString("arrivalspeed") << "\""; 00211 } 00212 dev.closeTag(true); 00213 } 00214 while (vehicles.size() != 0 && (*vehicles.rbegin()).depart == t) { 00215 vehicles.pop_back(); 00216 } 00217 } 00218 } 00219 00220 00221 SUMOReal 00222 ODMatrix::getNoLoaded() const { 00223 return myNoLoaded; 00224 } 00225 00226 00227 SUMOReal 00228 ODMatrix::getNoWritten() const { 00229 return myNoWritten; 00230 } 00231 00232 00233 SUMOReal 00234 ODMatrix::getNoDiscarded() const { 00235 return myNoDiscarded; 00236 } 00237 00238 00239 void 00240 ODMatrix::applyCurve(const Distribution_Points& ps, ODCell* cell, CellVector& newCells) { 00241 for (size_t i = 0; i < ps.getAreaNo(); ++i) { 00242 ODCell* ncell = new ODCell(); 00243 ncell->begin = (SUMOTime) ps.getAreaBegin(i); 00244 ncell->end = (SUMOTime) ps.getAreaEnd(i); 00245 ncell->origin = cell->origin; 00246 ncell->destination = cell->destination; 00247 ncell->vehicleType = cell->vehicleType; 00248 ncell->vehicleNumber = cell->vehicleNumber * ps.getAreaPerc(i); 00249 newCells.push_back(ncell); 00250 } 00251 } 00252 00253 00254 void 00255 ODMatrix::applyCurve(const Distribution_Points& ps) { 00256 CellVector oldCells = myContainer; 00257 myContainer.clear(); 00258 for (CellVector::iterator i = oldCells.begin(); i != oldCells.end(); ++i) { 00259 CellVector newCells; 00260 applyCurve(ps, *i, newCells); 00261 copy(newCells.begin(), newCells.end(), back_inserter(myContainer)); 00262 delete *i; 00263 } 00264 } 00265 00266 00267 00268 /****************************************************************************/ 00269