|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // Parser and container for routes during their loading 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 <string> 00035 #include <map> 00036 #include <vector> 00037 #include <microsim/MSRoute.h> 00038 #include <microsim/MSEdge.h> 00039 #include <microsim/MSVehicleType.h> 00040 #include <microsim/MSVehicle.h> 00041 #include <microsim/MSEdge.h> 00042 #include <microsim/MSInsertionControl.h> 00043 #include <microsim/MSVehicleControl.h> 00044 #include <microsim/MSLane.h> 00045 #include "MSRouteHandler.h" 00046 #include "MSPersonControl.h" 00047 #include <utils/xml/SUMOSAXHandler.h> 00048 #include <utils/xml/SUMOXMLDefinitions.h> 00049 #include <utils/common/MsgHandler.h> 00050 #include <utils/common/StringTokenizer.h> 00051 #include <utils/common/UtilExceptions.h> 00052 #include <utils/options/OptionsCont.h> 00053 #include "MSNet.h" 00054 00055 #include <microsim/trigger/MSBusStop.h> 00056 #include <microsim/MSGlobals.h> 00057 #include <utils/xml/SUMOVehicleParserHelper.h> 00058 00059 #ifdef CHECK_MEMORY_LEAKS 00060 #include <foreign/nvwa/debug_new.h> 00061 #endif // CHECK_MEMORY_LEAKS 00062 00063 00064 // =========================================================================== 00065 // method definitions 00066 // =========================================================================== 00067 MSRouteHandler::MSRouteHandler(const std::string& file, 00068 bool addVehiclesDirectly) : 00069 SUMOSAXHandler(file), 00070 myVehicleParameter(0), 00071 myLastDepart(0), 00072 myActivePlan(0), 00073 myAddVehiclesDirectly(addVehiclesDirectly), 00074 myCurrentVTypeDistribution(0), 00075 myCurrentRouteDistribution(0), 00076 myCurrentVType(0), 00077 myScale(-1.), 00078 myHaveWarnedAboutDeprecatedFriendlyPos(false), 00079 myHaveWarnedAboutDeprecatedBusStop(false), 00080 myHaveWarnedAboutDeprecatedVType(false), 00081 myHaveWarnedAboutDeprecatedVTypeDistribution(false), 00082 myHaveWarnedAboutDeprecatedVTypes(false), 00083 myHaveWarnedAboutDeprecatedRefID(false) { 00084 OptionsCont& oc = OptionsCont::getOptions(); 00085 if (oc.isSet("incremental-dua-step")) { 00086 myScale = oc.getInt("incremental-dua-step") / static_cast<SUMOReal>(oc.getInt("incremental-dua-base")); 00087 } 00088 if (oc.isSet("scale")) { 00089 myScale = oc.getFloat("scale"); 00090 } 00091 myActiveRoute.reserve(100); 00092 } 00093 00094 00095 MSRouteHandler::~MSRouteHandler() { 00096 } 00097 00098 00099 SUMOTime 00100 MSRouteHandler::getLastDepart() const { 00101 return myLastDepart; 00102 } 00103 00104 00105 bool 00106 MSRouteHandler::checkLastDepart() { 00107 if (myVehicleParameter->departProcedure == DEPART_GIVEN) { 00108 if (!myAddVehiclesDirectly && myVehicleParameter->depart < myLastDepart) { 00109 WRITE_WARNING("Route file should be sorted by departure time, ignoring '" + myVehicleParameter->id + "'!"); 00110 return false; 00111 } 00112 myLastDepart = myVehicleParameter->depart; 00113 } 00114 return true; 00115 } 00116 00117 00118 void 00119 MSRouteHandler::myStartElement(int element, 00120 const SUMOSAXAttributes& attrs) { 00121 switch (element) { 00122 case SUMO_TAG_VEHICLE: 00123 delete myVehicleParameter; 00124 myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(attrs); 00125 break; 00126 case SUMO_TAG_PERSON: 00127 delete myVehicleParameter; 00128 myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(attrs); 00129 myActivePlan = new MSPerson::MSPersonPlan(); 00130 break; 00131 case SUMO_TAG_RIDE: { 00132 const std::string pid = myVehicleParameter->id; 00133 bool ok = true; 00134 MSEdge* from = 0; 00135 if (attrs.hasAttribute(SUMO_ATTR_FROM)) { 00136 const std::string fromID = attrs.getStringReporting(SUMO_ATTR_FROM, pid.c_str(), ok); 00137 from = MSEdge::dictionary(fromID); 00138 if (from == 0) { 00139 throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known."); 00140 } 00141 if (!myActivePlan->empty() && &myActivePlan->back()->getDestination() != from) { 00142 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00143 } 00144 if (myActivePlan->empty()) { 00145 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(*from, -1, myVehicleParameter->depart)); 00146 } 00147 } 00148 const std::string toID = attrs.getStringReporting(SUMO_ATTR_TO, pid.c_str(), ok); 00149 MSEdge* to = MSEdge::dictionary(toID); 00150 if (to == 0) { 00151 throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known."); 00152 } 00153 const std::string desc = attrs.getStringReporting(SUMO_ATTR_LINES, pid.c_str(), ok); 00154 StringTokenizer st(desc); 00155 myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(*to, st.getVector())); 00156 break; 00157 } 00158 case SUMO_TAG_WALK: { 00159 myActiveRoute.clear(); 00160 bool ok = true; 00161 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, myActiveRouteID); 00162 if (myActiveRoute.empty()) { 00163 throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'."); 00164 } 00165 if (!myActivePlan->empty() && &myActivePlan->back()->getDestination() != myActiveRoute.front()) { 00166 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00167 } 00168 if (myActivePlan->empty()) { 00169 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(*myActiveRoute.front(), -1, myVehicleParameter->depart)); 00170 } 00171 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1); 00172 const SUMOReal speed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, 0, ok, -1); 00173 myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myActiveRoute, duration, speed)); 00174 myActiveRoute.clear(); 00175 break; 00176 } 00177 case SUMO_TAG_FLOW: 00178 delete myVehicleParameter; 00179 myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes(attrs); 00180 if (attrs.hasAttribute(SUMO_ATTR_FROM) && attrs.hasAttribute(SUMO_ATTR_TO)) { 00181 myActiveRouteID = "!" + myVehicleParameter->id; 00182 bool ok = true; 00183 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), 00184 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00185 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok), 00186 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00187 closeRoute(); 00188 } 00189 break; 00190 case SUMO_TAG_VTYPE__DEPRECATED: 00191 if (!myHaveWarnedAboutDeprecatedVType) { 00192 myHaveWarnedAboutDeprecatedVType = true; 00193 WRITE_WARNING("'" + toString(SUMO_TAG_VTYPE__DEPRECATED) + "' is deprecated; please use '" + toString(SUMO_TAG_VTYPE) + "'."); 00194 } 00195 case SUMO_TAG_VTYPE: 00196 myCurrentVType = SUMOVehicleParserHelper::beginVTypeParsing(attrs); 00197 break; 00198 case SUMO_TAG_VTYPE_DISTRIBUTION__DEPRECATED: 00199 if (!myHaveWarnedAboutDeprecatedVTypeDistribution) { 00200 myHaveWarnedAboutDeprecatedVTypeDistribution = true; 00201 WRITE_WARNING("'" + toString(SUMO_TAG_VTYPE_DISTRIBUTION__DEPRECATED) + "' is deprecated; please use '" + toString(SUMO_TAG_VTYPE_DISTRIBUTION) + "'."); 00202 } 00203 case SUMO_TAG_VTYPE_DISTRIBUTION: 00204 openVehicleTypeDistribution(attrs); 00205 break; 00206 case SUMO_TAG_ROUTE: 00207 openRoute(attrs); 00208 break; 00209 case SUMO_TAG_ROUTE_DISTRIBUTION: 00210 openRouteDistribution(attrs); 00211 break; 00212 case SUMO_TAG_STOP: 00213 addStop(attrs); 00214 break; 00215 case SUMO_TAG_TRIP__DEPRECATED: 00216 case SUMO_TAG_TRIP: { 00217 bool ok = true; 00218 myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(attrs); 00219 myVehicleParameter->setParameter |= VEHPARS_FORCE_REROUTE; 00220 myActiveRouteID = "!" + myVehicleParameter->id; 00221 if (attrs.hasAttribute(SUMO_ATTR_FROM) || !myVehicleParameter->wasSet(VEHPARS_TAZ_SET)) { 00222 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), 00223 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00224 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok), 00225 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00226 } else { 00227 const MSEdge* fromTaz = MSEdge::dictionary(myVehicleParameter->fromTaz + "-source"); 00228 if (fromTaz == 0) { 00229 WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' not known for '" + myVehicleParameter->id + "'!"); 00230 } else if (fromTaz->getNoFollowing() == 0) { 00231 WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' has no outgoing edges for '" + myVehicleParameter->id + "'!"); 00232 } else { 00233 myActiveRoute.push_back(fromTaz->getFollower(0)); 00234 } 00235 } 00236 closeRoute(); 00237 closeVehicle(); 00238 } 00239 break; 00240 default: 00241 break; 00242 } 00243 // parse embedded vtype information 00244 if (myCurrentVType != 0 && element != SUMO_TAG_VTYPE && element != SUMO_TAG_VTYPE__DEPRECATED) { 00245 SUMOVehicleParserHelper::parseVTypeEmbedded(*myCurrentVType, element, attrs); 00246 return; 00247 } 00248 } 00249 00250 00251 void 00252 MSRouteHandler::openVehicleTypeDistribution(const SUMOSAXAttributes& attrs) { 00253 bool ok = true; 00254 myCurrentVTypeDistributionID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00255 if (ok) { 00256 myCurrentVTypeDistribution = new RandomDistributor<MSVehicleType*>(); 00257 if (attrs.hasAttribute(SUMO_ATTR_VTYPES) || attrs.hasAttribute(SUMO_ATTR_VTYPES__DEPRECATED)) { 00258 std::string vTypes; 00259 if (!myHaveWarnedAboutDeprecatedVTypes && attrs.hasAttribute(SUMO_ATTR_VTYPES__DEPRECATED)) { 00260 myHaveWarnedAboutDeprecatedVTypes = true; 00261 WRITE_WARNING("'" + toString(SUMO_ATTR_VTYPES__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_ATTR_VTYPES) + "' instead."); 00262 vTypes = attrs.getStringReporting(SUMO_ATTR_VTYPES__DEPRECATED, myCurrentVTypeDistributionID.c_str(), ok); 00263 } else { 00264 vTypes = attrs.getStringReporting(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok); 00265 } 00266 StringTokenizer st(vTypes); 00267 while (st.hasNext()) { 00268 std::string vtypeID = st.next(); 00269 MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(vtypeID); 00270 if (type == 0) { 00271 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'."); 00272 } 00273 myCurrentVTypeDistribution->add(type->getDefaultProbability(), type); 00274 } 00275 } 00276 } 00277 } 00278 00279 00280 void 00281 MSRouteHandler::closeVehicleTypeDistribution() { 00282 if (myCurrentVTypeDistribution != 0) { 00283 if (myCurrentVTypeDistribution->getOverallProb() == 0) { 00284 delete myCurrentVTypeDistribution; 00285 WRITE_ERROR("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty."); 00286 } else if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) { 00287 delete myCurrentVTypeDistribution; 00288 WRITE_ERROR("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists."); 00289 } 00290 myCurrentVTypeDistribution = 0; 00291 } 00292 } 00293 00294 00295 void 00296 MSRouteHandler::openRoute(const SUMOSAXAttributes& attrs) { 00297 // check whether the id is really necessary 00298 std::string rid; 00299 if (myCurrentRouteDistribution != 0) { 00300 myActiveRouteID = myCurrentRouteDistributionID + "#" + toString(myCurrentRouteDistribution->getProbs().size()); // !!! document this 00301 rid = "distribution '" + myCurrentRouteDistributionID + "'"; 00302 } else if (myVehicleParameter != 0) { 00303 // ok, a vehicle is wrapping the route, 00304 // we may use this vehicle's id as default 00305 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this 00306 if (attrs.hasAttribute(SUMO_ATTR_ID)) { 00307 WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "')."); 00308 } 00309 } else { 00310 bool ok = true; 00311 myActiveRouteID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok, false); 00312 if (!ok) { 00313 return; 00314 } 00315 rid = "'" + myActiveRouteID + "'"; 00316 } 00317 if (myVehicleParameter != 0) { // have to do this here for nested route distributions 00318 rid = "for vehicle '" + myVehicleParameter->id + "'"; 00319 } 00320 bool ok = true; 00321 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) { 00322 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid); 00323 } 00324 myActiveRouteRefID = attrs.getOptStringReporting(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, ""); 00325 if (attrs.hasAttribute(SUMO_ATTR_REFID__DEPRECATED)) { 00326 myActiveRouteRefID = attrs.getOptStringReporting(SUMO_ATTR_REFID__DEPRECATED, myActiveRouteID.c_str(), ok, ""); 00327 if (!myHaveWarnedAboutDeprecatedRefID) { 00328 myHaveWarnedAboutDeprecatedRefID = true; 00329 WRITE_WARNING("'" + toString(SUMO_ATTR_REFID__DEPRECATED) + "' is deprecated, please use '" + toString(SUMO_ATTR_REFID) + "' instead."); 00330 } 00331 } 00332 if (myActiveRouteRefID != "" && MSRoute::dictionary(myActiveRouteRefID) == 0) { 00333 WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + "."); 00334 } 00335 myActiveRouteProbability = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, myActiveRouteID.c_str(), ok, DEFAULT_VEH_PROB); 00336 myActiveRouteColor = attrs.hasAttribute(SUMO_ATTR_COLOR) ? RGBColor::parseColorReporting(attrs.getString(SUMO_ATTR_COLOR), attrs.getObjectType(), myActiveRouteID.c_str(), true, ok) : RGBColor::getDefaultColor(); 00337 } 00338 00339 00340 void 00341 MSRouteHandler::myEndElement(int element) { 00342 switch (element) { 00343 case SUMO_TAG_ROUTE: 00344 closeRoute(); 00345 break; 00346 case SUMO_TAG_PERSON: 00347 closePerson(); 00348 delete myVehicleParameter; 00349 myVehicleParameter = 0; 00350 break; 00351 case SUMO_TAG_VEHICLE: 00352 if (myVehicleParameter->repetitionNumber > 0) { 00353 myVehicleParameter->repetitionNumber++; // for backwards compatibility 00354 // it is a flow, thus no break here 00355 } else { 00356 closeVehicle(); 00357 delete myVehicleParameter; 00358 myVehicleParameter = 0; 00359 break; 00360 } 00361 case SUMO_TAG_FLOW: 00362 closeFlow(); 00363 break; 00364 case SUMO_TAG_VTYPE_DISTRIBUTION__DEPRECATED: 00365 case SUMO_TAG_VTYPE_DISTRIBUTION: 00366 closeVehicleTypeDistribution(); 00367 break; 00368 case SUMO_TAG_ROUTE_DISTRIBUTION: 00369 closeRouteDistribution(); 00370 break; 00371 case SUMO_TAG_VTYPE__DEPRECATED: 00372 case SUMO_TAG_VTYPE: { 00373 SUMOVehicleParserHelper::closeVTypeParsing(*myCurrentVType); 00374 MSVehicleType* vehType = MSVehicleType::build(*myCurrentVType); 00375 delete myCurrentVType; 00376 myCurrentVType = 0; 00377 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) { 00378 std::string id = vehType->getID(); 00379 delete vehType; 00380 #ifdef HAVE_MESOSIM 00381 if (!MSGlobals::gStateLoaded) { 00382 #endif 00383 throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists."); 00384 #ifdef HAVE_MESOSIM 00385 } 00386 #endif 00387 } else { 00388 if (myCurrentVTypeDistribution != 0) { 00389 myCurrentVTypeDistribution->add(vehType->getDefaultProbability(), vehType); 00390 } 00391 } 00392 } 00393 break; 00394 default: 00395 break; 00396 } 00397 } 00398 00399 00400 void 00401 MSRouteHandler::closeRoute() { 00402 if (myActiveRoute.size() == 0) { 00403 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != 0) { 00404 myCurrentRouteDistribution->add(myActiveRouteProbability, MSRoute::dictionary(myActiveRouteRefID)); 00405 myActiveRouteID = ""; 00406 myActiveRouteRefID = ""; 00407 return; 00408 } 00409 if (myVehicleParameter != 0) { 00410 throw ProcessError("Vehicle's '" + myVehicleParameter->id + "' route has no edges."); 00411 } else { 00412 throw ProcessError("Route '" + myActiveRouteID + "' has no edges."); 00413 } 00414 } 00415 MSRoute* route = new MSRoute(myActiveRouteID, myActiveRoute, 00416 myVehicleParameter == 0 || myVehicleParameter->repetitionNumber >= 1, 00417 myActiveRouteColor, myActiveRouteStops); 00418 myActiveRoute.clear(); 00419 if (!MSRoute::dictionary(myActiveRouteID, route)) { 00420 delete route; 00421 #ifdef HAVE_MESOSIM 00422 if (!MSGlobals::gStateLoaded) { 00423 #endif 00424 if (myVehicleParameter != 0) { 00425 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == 0) { 00426 throw ProcessError("Another route for vehicle '" + myVehicleParameter->id + "' exists."); 00427 } else { 00428 throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists."); 00429 } 00430 } else { 00431 throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists."); 00432 } 00433 #ifdef HAVE_MESOSIM 00434 } 00435 #endif 00436 } else { 00437 if (myCurrentRouteDistribution != 0) { 00438 myCurrentRouteDistribution->add(myActiveRouteProbability, route); 00439 } 00440 } 00441 myActiveRouteID = ""; 00442 myActiveRouteStops.clear(); 00443 } 00444 00445 00446 void 00447 MSRouteHandler::openRouteDistribution(const SUMOSAXAttributes& attrs) { 00448 // check whether the id is really necessary 00449 bool ok = true; 00450 if (myVehicleParameter != 0) { 00451 // ok, a vehicle is wrapping the route, 00452 // we may use this vehicle's id as default 00453 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this 00454 } else { 00455 myCurrentRouteDistributionID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00456 if (!ok) { 00457 return; 00458 } 00459 } 00460 myCurrentRouteDistribution = new RandomDistributor<const MSRoute*>(); 00461 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) { 00462 bool ok = true; 00463 StringTokenizer st(attrs.getStringReporting(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok)); 00464 while (st.hasNext()) { 00465 std::string routeID = st.next(); 00466 const MSRoute* route = MSRoute::dictionary(routeID); 00467 if (route == 0) { 00468 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'."); 00469 } 00470 myCurrentRouteDistribution->add(1., route, false); 00471 } 00472 } 00473 } 00474 00475 00476 void 00477 MSRouteHandler::closeRouteDistribution() { 00478 if (myCurrentRouteDistribution != 0) { 00479 if (myCurrentRouteDistribution->getOverallProb() == 0) { 00480 delete myCurrentRouteDistribution; 00481 WRITE_ERROR("Route distribution '" + myCurrentRouteDistributionID + "' is empty."); 00482 } else if (!MSRoute::dictionary(myCurrentRouteDistributionID, myCurrentRouteDistribution)) { 00483 delete myCurrentRouteDistribution; 00484 WRITE_ERROR("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists."); 00485 } 00486 myCurrentRouteDistribution = 0; 00487 } 00488 } 00489 00490 00491 void 00492 MSRouteHandler::closeVehicle() { 00493 // get nested route 00494 const MSRoute* route = MSRoute::dictionary("!" + myVehicleParameter->id); 00495 MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl(); 00496 if (myVehicleParameter->departProcedure == DEPART_GIVEN) { 00497 // let's check whether this vehicle had to depart before the simulation starts 00498 if (!checkLastDepart() || myVehicleParameter->depart < string2time(OptionsCont::getOptions().getString("begin"))) { 00499 if (route != 0) { 00500 route->addReference(); 00501 route->release(); 00502 } 00503 return; 00504 } 00505 } 00506 // get the vehicle's type 00507 MSVehicleType* vtype = 0; 00508 if (myVehicleParameter->vtypeid != "") { 00509 vtype = vehControl.getVType(myVehicleParameter->vtypeid); 00510 if (vtype == 0) { 00511 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00512 } 00513 } else { 00514 // there should be one (at least the default one) 00515 vtype = vehControl.getVType(); 00516 } 00517 if (route == 0) { 00518 // if there is no nested route, try via the (hopefully) given route-id 00519 route = MSRoute::dictionary(myVehicleParameter->routeid); 00520 } 00521 if (route == 0) { 00522 // nothing found? -> error 00523 if (myVehicleParameter->routeid != "") { 00524 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00525 } else { 00526 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route."); 00527 } 00528 } 00529 myActiveRouteID = ""; 00530 00531 // try to build the vehicle 00532 SUMOVehicle* vehicle = 0; 00533 if (vehControl.getVehicle(myVehicleParameter->id) == 0) { 00534 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype); 00535 // maybe we do not want this vehicle to be inserted due to scaling 00536 if (myScale < 0 || vehControl.isInQuota(myScale)) { 00537 // add the vehicle to the vehicle control 00538 vehControl.addVehicle(myVehicleParameter->id, vehicle); 00539 if (myVehicleParameter->departProcedure == DEPART_TRIGGERED) { 00540 vehControl.addWaiting(*route->begin(), vehicle); 00541 vehControl.registerOneWaitingForPerson(); 00542 } 00543 myVehicleParameter = 0; 00544 } else { 00545 vehControl.deleteVehicle(vehicle); 00546 myVehicleParameter = 0; 00547 vehicle = 0; 00548 } 00549 } else { 00550 // strange: another vehicle with the same id already exists 00551 #ifdef HAVE_MESOSIM 00552 if (!MSGlobals::gStateLoaded) { 00553 #endif 00554 // and was not loaded while loading a simulation state 00555 // -> error 00556 throw ProcessError("Another vehicle with the id '" + myVehicleParameter->id + "' exists."); 00557 #ifdef HAVE_MESOSIM 00558 } else { 00559 // ok, it seems to be loaded previously while loading a simulation state 00560 vehicle = 0; 00561 } 00562 #endif 00563 } 00564 // check whether the vehicle shall be added directly to the network or 00565 // shall stay in the internal buffer 00566 if (vehicle != 0) { 00567 if (vehicle->getParameter().departProcedure == DEPART_GIVEN) { 00568 MSNet::getInstance()->getInsertionControl().add(vehicle); 00569 } 00570 } 00571 } 00572 00573 00574 void 00575 MSRouteHandler::closePerson() { 00576 if (myActivePlan->size() == 0) { 00577 throw ProcessError("Person '" + myVehicleParameter->id + "' has no plan."); 00578 } 00579 MSPerson* person = new MSPerson(myVehicleParameter, myActivePlan); 00580 if (checkLastDepart() && MSNet::getInstance()->getPersonControl().add(myVehicleParameter->id, person)) { 00581 MSNet::getInstance()->getPersonControl().setArrival(myVehicleParameter->depart, person); 00582 } else { 00583 delete person; 00584 } 00585 myVehicleParameter = 0; 00586 myActivePlan = 0; 00587 } 00588 00589 00590 void 00591 MSRouteHandler::closeFlow() { 00592 // let's check whether vehicles had to depart before the simulation starts 00593 myVehicleParameter->repetitionsDone = 0; 00594 SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart; 00595 while (myVehicleParameter->repetitionsDone * myVehicleParameter->repetitionOffset < offsetToBegin) { 00596 myVehicleParameter->repetitionsDone++; 00597 if (myVehicleParameter->repetitionsDone == myVehicleParameter->repetitionNumber) { 00598 return; 00599 } 00600 } 00601 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid) == 0) { 00602 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00603 } 00604 if (MSRoute::dictionary("!" + myVehicleParameter->id) == 0) { 00605 // if not, try via the (hopefully) given route-id 00606 if (MSRoute::dictionary(myVehicleParameter->routeid) == 0) { 00607 if (myVehicleParameter->routeid != "") { 00608 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00609 } else { 00610 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route."); 00611 } 00612 } 00613 } else { 00614 myVehicleParameter->routeid = "!" + myVehicleParameter->id; 00615 } 00616 myActiveRouteID = ""; 00617 00618 // check whether the vehicle shall be added directly to the network or 00619 // shall stay in the internal buffer 00620 if (checkLastDepart()) { 00621 MSNet::getInstance()->getInsertionControl().add(myVehicleParameter); 00622 } 00623 myVehicleParameter = 0; 00624 } 00625 00626 bool 00627 MSRouteHandler::checkStopPos(SUMOReal& startPos, SUMOReal& endPos, const SUMOReal laneLength, 00628 const SUMOReal minLength, const bool friendlyPos) { 00629 if (minLength > laneLength) { 00630 return false; 00631 } 00632 if (startPos < 0) { 00633 startPos += laneLength; 00634 } 00635 if (endPos < 0) { 00636 endPos += laneLength; 00637 } 00638 if (endPos < minLength || endPos > laneLength) { 00639 if (!friendlyPos) { 00640 return false; 00641 } 00642 if (endPos < minLength) { 00643 endPos = minLength; 00644 } 00645 if (endPos > laneLength) { 00646 endPos = laneLength; 00647 } 00648 } 00649 if (startPos < 0 || startPos > endPos - minLength) { 00650 if (!friendlyPos) { 00651 return false; 00652 } 00653 if (startPos < 0) { 00654 startPos = 0; 00655 } 00656 if (startPos > endPos - minLength) { 00657 startPos = endPos - minLength; 00658 } 00659 } 00660 return true; 00661 } 00662 00663 00664 void 00665 MSRouteHandler::addStop(const SUMOSAXAttributes& attrs) { 00666 bool ok = true; 00667 std::string errorSuffix; 00668 if (myActiveRouteID != "") { 00669 errorSuffix = " in route '" + myActiveRouteID + "'."; 00670 } else if (myActivePlan) { 00671 errorSuffix = " in person '" + myVehicleParameter->id + "'."; 00672 } else { 00673 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'."; 00674 } 00675 SUMOVehicleParameter::Stop stop; 00676 // try to parse the assigned bus stop 00677 if (attrs.hasAttribute(SUMO_ATTR_BUS_STOP__DEPRECATED)) { 00678 stop.busstop = attrs.getStringReporting(SUMO_ATTR_BUS_STOP__DEPRECATED, 0, ok); 00679 if (!myHaveWarnedAboutDeprecatedBusStop) { 00680 myHaveWarnedAboutDeprecatedBusStop = true; 00681 WRITE_WARNING("'bus_stop' is deprecated, please use 'busStop' instead."); 00682 } 00683 } else { 00684 stop.busstop = attrs.getOptStringReporting(SUMO_ATTR_BUS_STOP, 0, ok, ""); 00685 } 00686 if (stop.busstop != "") { 00687 // ok, we have obviously a bus stop 00688 MSBusStop* bs = MSNet::getInstance()->getBusStop(stop.busstop); 00689 if (bs != 0) { 00690 const MSLane& l = bs->getLane(); 00691 stop.lane = l.getID(); 00692 stop.endPos = bs->getEndLanePosition(); 00693 stop.startPos = bs->getBeginLanePosition(); 00694 } else { 00695 WRITE_ERROR("The bus stop '" + stop.busstop + "' is not known" + errorSuffix); 00696 return; 00697 } 00698 } else { 00699 // no, the lane and the position should be given 00700 // get the lane 00701 stop.lane = attrs.getOptStringReporting(SUMO_ATTR_LANE, 0, ok, ""); 00702 if (ok && stop.lane != "") { 00703 if (MSLane::dictionary(stop.lane) == 0) { 00704 WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix); 00705 return; 00706 } 00707 } else { 00708 WRITE_ERROR("A stop must be placed on a bus stop or a lane" + errorSuffix); 00709 return; 00710 } 00711 if (myActivePlan && 00712 !myActivePlan->empty() && 00713 &myActivePlan->back()->getDestination() != &MSLane::dictionary(stop.lane)->getEdge()) { 00714 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + MSLane::dictionary(stop.lane)->getEdge().getID() + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00715 } 00716 stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_ENDPOS, 0, ok, MSLane::dictionary(stop.lane)->getLength()); 00717 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) { 00718 WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix); 00719 stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_POSITION, 0, ok, stop.endPos); 00720 } 00721 stop.startPos = attrs.getOptSUMORealReporting(SUMO_ATTR_STARTPOS, 0, ok, stop.endPos - 2 * POSITION_EPS); 00722 if (attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) && !myHaveWarnedAboutDeprecatedFriendlyPos) { 00723 myHaveWarnedAboutDeprecatedFriendlyPos = true; 00724 WRITE_WARNING("'" + toString(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) + "' is deprecated, use '" + toString(SUMO_ATTR_FRIENDLY_POS) + "' instead."); 00725 } 00726 bool friendlyPos = attrs.hasAttribute(SUMO_ATTR_FRIENDLY_POS__DEPRECATED) 00727 ? attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS__DEPRECATED, 0, ok, false) 00728 : attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, 0, ok, false); 00729 if (!ok || !checkStopPos(stop.startPos, stop.endPos, MSLane::dictionary(stop.lane)->getLength(), POSITION_EPS, friendlyPos)) { 00730 WRITE_ERROR("Invalid start or end position for stop" + errorSuffix); 00731 return; 00732 } 00733 } 00734 00735 // get the standing duration 00736 if (!attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL)) { 00737 stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, true); 00738 stop.duration = -1; 00739 stop.until = -1; 00740 } else { 00741 stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1); 00742 stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, 0, ok, -1); 00743 if (!ok || (stop.duration < 0 && stop.until < 0)) { 00744 WRITE_ERROR("Invalid duration or end time is given for a stop" + errorSuffix); 00745 return; 00746 } 00747 stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, false); 00748 } 00749 stop.parking = attrs.getOptBoolReporting(SUMO_ATTR_PARKING, 0, ok, stop.triggered); 00750 if (!ok) { 00751 WRITE_ERROR("Invalid bool for 'triggered' or 'parking' for stop" + errorSuffix); 00752 return; 00753 } 00754 const std::string idx = attrs.getOptStringReporting(SUMO_ATTR_INDEX, 0, ok, "end"); 00755 if (idx == "end") { 00756 stop.index = STOP_INDEX_END; 00757 } else if (idx == "fit") { 00758 stop.index = STOP_INDEX_FIT; 00759 } else { 00760 stop.index = attrs.getIntReporting(SUMO_ATTR_INDEX, 0, ok); 00761 if (!ok || stop.index < 0) { 00762 WRITE_ERROR("Invalid 'index' for stop" + errorSuffix); 00763 return; 00764 } 00765 } 00766 if (myActiveRouteID != "") { 00767 myActiveRouteStops.push_back(stop); 00768 } else if (myActivePlan) { 00769 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until)); 00770 } else { 00771 myVehicleParameter->stops.push_back(stop); 00772 } 00773 } 00774 00775 00776 /****************************************************************************/