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 SUMORouteHandler(file), 00070 myActivePlan(0), 00071 myAddVehiclesDirectly(addVehiclesDirectly), 00072 myCurrentVTypeDistribution(0), 00073 myCurrentRouteDistribution(0), 00074 myScale(-1.) { 00075 OptionsCont& oc = OptionsCont::getOptions(); 00076 if (oc.isSet("incremental-dua-step")) { 00077 myScale = oc.getInt("incremental-dua-step") / static_cast<SUMOReal>(oc.getInt("incremental-dua-base")); 00078 } 00079 if (oc.isSet("scale")) { 00080 myScale = oc.getFloat("scale"); 00081 } 00082 myActiveRoute.reserve(100); 00083 } 00084 00085 00086 MSRouteHandler::~MSRouteHandler() { 00087 } 00088 00089 00090 void 00091 MSRouteHandler::myStartElement(int element, 00092 const SUMOSAXAttributes& attrs) { 00093 SUMORouteHandler::myStartElement(element, attrs); 00094 switch (element) { 00095 case SUMO_TAG_PERSON: 00096 myActivePlan = new MSPerson::MSPersonPlan(); 00097 break; 00098 case SUMO_TAG_RIDE: { 00099 const std::string pid = myVehicleParameter->id; 00100 bool ok = true; 00101 MSEdge* from = 0; 00102 if (attrs.hasAttribute(SUMO_ATTR_FROM)) { 00103 const std::string fromID = attrs.getStringReporting(SUMO_ATTR_FROM, pid.c_str(), ok); 00104 from = MSEdge::dictionary(fromID); 00105 if (from == 0) { 00106 throw ProcessError("The from edge '" + fromID + "' within a ride of person '" + pid + "' is not known."); 00107 } 00108 if (!myActivePlan->empty() && &myActivePlan->back()->getDestination() != from) { 00109 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + fromID + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00110 } 00111 if (myActivePlan->empty()) { 00112 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(*from, -1, myVehicleParameter->depart)); 00113 } 00114 } 00115 const std::string toID = attrs.getStringReporting(SUMO_ATTR_TO, pid.c_str(), ok); 00116 MSEdge* to = MSEdge::dictionary(toID); 00117 if (to == 0) { 00118 throw ProcessError("The to edge '" + toID + "' within a ride of person '" + pid + "' is not known."); 00119 } 00120 const std::string desc = attrs.getStringReporting(SUMO_ATTR_LINES, pid.c_str(), ok); 00121 StringTokenizer st(desc); 00122 myActivePlan->push_back(new MSPerson::MSPersonStage_Driving(*to, st.getVector())); 00123 break; 00124 } 00125 case SUMO_TAG_WALK: { 00126 myActiveRoute.clear(); 00127 bool ok = true; 00128 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_EDGES, myVehicleParameter->id.c_str(), ok), myActiveRoute, myActiveRouteID); 00129 if (myActiveRoute.empty()) { 00130 throw ProcessError("No edges to walk for person '" + myVehicleParameter->id + "'."); 00131 } 00132 if (!myActivePlan->empty() && &myActivePlan->back()->getDestination() != myActiveRoute.front()) { 00133 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + myActiveRoute.front()->getID() + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00134 } 00135 if (myActivePlan->empty()) { 00136 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(*myActiveRoute.front(), -1, myVehicleParameter->depart)); 00137 } 00138 const SUMOTime duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1); 00139 const SUMOReal speed = attrs.getOptSUMORealReporting(SUMO_ATTR_SPEED, 0, ok, -1); 00140 myActivePlan->push_back(new MSPerson::MSPersonStage_Walking(myActiveRoute, duration, speed)); 00141 myActiveRoute.clear(); 00142 break; 00143 } 00144 case SUMO_TAG_FLOW: 00145 if (attrs.hasAttribute(SUMO_ATTR_FROM) && attrs.hasAttribute(SUMO_ATTR_TO)) { 00146 myActiveRouteID = "!" + myVehicleParameter->id; 00147 bool ok = true; 00148 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), 00149 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00150 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok), 00151 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00152 closeRoute(); 00153 } 00154 break; 00155 case SUMO_TAG_TRIP__DEPRECATED: 00156 case SUMO_TAG_TRIP: { 00157 bool ok = true; 00158 if (attrs.hasAttribute(SUMO_ATTR_FROM) || !myVehicleParameter->wasSet(VEHPARS_TAZ_SET)) { 00159 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_FROM, myVehicleParameter->id.c_str(), ok), 00160 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00161 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_TO, myVehicleParameter->id.c_str(), ok), 00162 myActiveRoute, "for vehicle '" + myVehicleParameter->id + "'"); 00163 } else { 00164 const MSEdge* fromTaz = MSEdge::dictionary(myVehicleParameter->fromTaz + "-source"); 00165 if (fromTaz == 0) { 00166 WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' not known for '" + myVehicleParameter->id + "'!"); 00167 } else if (fromTaz->getNoFollowing() == 0) { 00168 WRITE_ERROR("Source district '" + myVehicleParameter->fromTaz + "' has no outgoing edges for '" + myVehicleParameter->id + "'!"); 00169 } else { 00170 myActiveRoute.push_back(fromTaz->getFollower(0)); 00171 } 00172 } 00173 closeRoute(); 00174 closeVehicle(); 00175 } 00176 break; 00177 default: 00178 break; 00179 } 00180 // parse embedded vtype information 00181 if (myCurrentVType != 0 && element != SUMO_TAG_VTYPE && element != SUMO_TAG_VTYPE__DEPRECATED) { 00182 SUMOVehicleParserHelper::parseVTypeEmbedded(*myCurrentVType, element, attrs); 00183 return; 00184 } 00185 } 00186 00187 00188 void 00189 MSRouteHandler::openVehicleTypeDistribution(const SUMOSAXAttributes& attrs) { 00190 bool ok = true; 00191 myCurrentVTypeDistributionID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00192 if (ok) { 00193 myCurrentVTypeDistribution = new RandomDistributor<MSVehicleType*>(); 00194 if (attrs.hasAttribute(SUMO_ATTR_VTYPES) || attrs.hasAttribute(SUMO_ATTR_VTYPES__DEPRECATED)) { 00195 const std::string vTypes = attrs.getStringReporting(SUMO_ATTR_VTYPES, myCurrentVTypeDistributionID.c_str(), ok); 00196 StringTokenizer st(vTypes); 00197 while (st.hasNext()) { 00198 std::string vtypeID = st.next(); 00199 MSVehicleType* type = MSNet::getInstance()->getVehicleControl().getVType(vtypeID); 00200 if (type == 0) { 00201 throw ProcessError("Unknown vtype '" + vtypeID + "' in distribution '" + myCurrentVTypeDistributionID + "'."); 00202 } 00203 myCurrentVTypeDistribution->add(type->getDefaultProbability(), type); 00204 } 00205 } 00206 } 00207 } 00208 00209 00210 void 00211 MSRouteHandler::closeVehicleTypeDistribution() { 00212 if (myCurrentVTypeDistribution != 0) { 00213 if (myCurrentVTypeDistribution->getOverallProb() == 0) { 00214 delete myCurrentVTypeDistribution; 00215 WRITE_ERROR("Vehicle type distribution '" + myCurrentVTypeDistributionID + "' is empty."); 00216 } else if (!MSNet::getInstance()->getVehicleControl().addVTypeDistribution(myCurrentVTypeDistributionID, myCurrentVTypeDistribution)) { 00217 delete myCurrentVTypeDistribution; 00218 WRITE_ERROR("Another vehicle type (or distribution) with the id '" + myCurrentVTypeDistributionID + "' exists."); 00219 } 00220 myCurrentVTypeDistribution = 0; 00221 } 00222 } 00223 00224 00225 void 00226 MSRouteHandler::openRoute(const SUMOSAXAttributes& attrs) { 00227 // check whether the id is really necessary 00228 std::string rid; 00229 if (myCurrentRouteDistribution != 0) { 00230 myActiveRouteID = myCurrentRouteDistributionID + "#" + toString(myCurrentRouteDistribution->getProbs().size()); // !!! document this 00231 rid = "distribution '" + myCurrentRouteDistributionID + "'"; 00232 } else if (myVehicleParameter != 0) { 00233 // ok, a vehicle is wrapping the route, 00234 // we may use this vehicle's id as default 00235 myActiveRouteID = "!" + myVehicleParameter->id; // !!! document this 00236 if (attrs.hasAttribute(SUMO_ATTR_ID)) { 00237 WRITE_WARNING("Ids of internal routes are ignored (vehicle '" + myVehicleParameter->id + "')."); 00238 } 00239 } else { 00240 bool ok = true; 00241 myActiveRouteID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok, false); 00242 if (!ok) { 00243 return; 00244 } 00245 rid = "'" + myActiveRouteID + "'"; 00246 } 00247 if (myVehicleParameter != 0) { // have to do this here for nested route distributions 00248 rid = "for vehicle '" + myVehicleParameter->id + "'"; 00249 } 00250 bool ok = true; 00251 if (attrs.hasAttribute(SUMO_ATTR_EDGES)) { 00252 MSEdge::parseEdgesList(attrs.getStringReporting(SUMO_ATTR_EDGES, myActiveRouteID.c_str(), ok), myActiveRoute, rid); 00253 } 00254 myActiveRouteRefID = attrs.getOptStringReporting(SUMO_ATTR_REFID, myActiveRouteID.c_str(), ok, ""); 00255 if (myActiveRouteRefID != "" && MSRoute::dictionary(myActiveRouteRefID) == 0) { 00256 WRITE_ERROR("Invalid reference to route '" + myActiveRouteRefID + "' in route " + rid + "."); 00257 } 00258 myActiveRouteProbability = attrs.getOptSUMORealReporting(SUMO_ATTR_PROB, myActiveRouteID.c_str(), ok, DEFAULT_VEH_PROB); 00259 myActiveRouteColor = attrs.hasAttribute(SUMO_ATTR_COLOR) ? RGBColor::parseColorReporting(attrs.getString(SUMO_ATTR_COLOR), attrs.getObjectType(), myActiveRouteID.c_str(), true, ok) : RGBColor::getDefaultColor(); 00260 } 00261 00262 00263 void 00264 MSRouteHandler::myEndElement(int element) { 00265 SUMORouteHandler::myEndElement(element); 00266 switch (element) { 00267 case SUMO_TAG_VTYPE: { 00268 MSVehicleType* vehType = MSVehicleType::build(*myCurrentVType); 00269 delete myCurrentVType; 00270 myCurrentVType = 0; 00271 if (!MSNet::getInstance()->getVehicleControl().addVType(vehType)) { 00272 const std::string id = vehType->getID(); 00273 delete vehType; 00274 #ifdef HAVE_MESOSIM 00275 if (!MSGlobals::gStateLoaded) { 00276 #endif 00277 throw ProcessError("Another vehicle type (or distribution) with the id '" + id + "' exists."); 00278 #ifdef HAVE_MESOSIM 00279 } 00280 #endif 00281 } else { 00282 if (myCurrentVTypeDistribution != 0) { 00283 myCurrentVTypeDistribution->add(vehType->getDefaultProbability(), vehType); 00284 } 00285 } 00286 } 00287 break; 00288 default: 00289 break; 00290 } 00291 } 00292 00293 00294 void 00295 MSRouteHandler::closeRoute() { 00296 if (myActiveRoute.size() == 0) { 00297 if (myActiveRouteRefID != "" && myCurrentRouteDistribution != 0) { 00298 myCurrentRouteDistribution->add(myActiveRouteProbability, MSRoute::dictionary(myActiveRouteRefID)); 00299 myActiveRouteID = ""; 00300 myActiveRouteRefID = ""; 00301 return; 00302 } 00303 if (myVehicleParameter != 0) { 00304 throw ProcessError("Vehicle's '" + myVehicleParameter->id + "' route has no edges."); 00305 } else { 00306 throw ProcessError("Route '" + myActiveRouteID + "' has no edges."); 00307 } 00308 } 00309 MSRoute* route = new MSRoute(myActiveRouteID, myActiveRoute, 00310 myVehicleParameter == 0 || myVehicleParameter->repetitionNumber >= 1, 00311 myActiveRouteColor, myActiveRouteStops); 00312 myActiveRoute.clear(); 00313 if (!MSRoute::dictionary(myActiveRouteID, route)) { 00314 delete route; 00315 #ifdef HAVE_MESOSIM 00316 if (!MSGlobals::gStateLoaded) { 00317 #endif 00318 if (myVehicleParameter != 0) { 00319 if (MSNet::getInstance()->getVehicleControl().getVehicle(myVehicleParameter->id) == 0) { 00320 throw ProcessError("Another route for vehicle '" + myVehicleParameter->id + "' exists."); 00321 } else { 00322 throw ProcessError("A vehicle with id '" + myVehicleParameter->id + "' already exists."); 00323 } 00324 } else { 00325 throw ProcessError("Another route (or distribution) with the id '" + myActiveRouteID + "' exists."); 00326 } 00327 #ifdef HAVE_MESOSIM 00328 } 00329 #endif 00330 } else { 00331 if (myCurrentRouteDistribution != 0) { 00332 myCurrentRouteDistribution->add(myActiveRouteProbability, route); 00333 } 00334 } 00335 myActiveRouteID = ""; 00336 myActiveRouteStops.clear(); 00337 } 00338 00339 00340 void 00341 MSRouteHandler::openRouteDistribution(const SUMOSAXAttributes& attrs) { 00342 // check whether the id is really necessary 00343 bool ok = true; 00344 if (myVehicleParameter != 0) { 00345 // ok, a vehicle is wrapping the route, 00346 // we may use this vehicle's id as default 00347 myCurrentRouteDistributionID = "!" + myVehicleParameter->id; // !!! document this 00348 } else { 00349 myCurrentRouteDistributionID = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00350 if (!ok) { 00351 return; 00352 } 00353 } 00354 myCurrentRouteDistribution = new RandomDistributor<const MSRoute*>(); 00355 if (attrs.hasAttribute(SUMO_ATTR_ROUTES)) { 00356 bool ok = true; 00357 StringTokenizer st(attrs.getStringReporting(SUMO_ATTR_ROUTES, myCurrentRouteDistributionID.c_str(), ok)); 00358 while (st.hasNext()) { 00359 std::string routeID = st.next(); 00360 const MSRoute* route = MSRoute::dictionary(routeID); 00361 if (route == 0) { 00362 throw ProcessError("Unknown route '" + routeID + "' in distribution '" + myCurrentRouteDistributionID + "'."); 00363 } 00364 myCurrentRouteDistribution->add(1., route, false); 00365 } 00366 } 00367 } 00368 00369 00370 void 00371 MSRouteHandler::closeRouteDistribution() { 00372 if (myCurrentRouteDistribution != 0) { 00373 if (myCurrentRouteDistribution->getOverallProb() == 0) { 00374 delete myCurrentRouteDistribution; 00375 WRITE_ERROR("Route distribution '" + myCurrentRouteDistributionID + "' is empty."); 00376 } else if (!MSRoute::dictionary(myCurrentRouteDistributionID, myCurrentRouteDistribution)) { 00377 delete myCurrentRouteDistribution; 00378 WRITE_ERROR("Another route (or distribution) with the id '" + myCurrentRouteDistributionID + "' exists."); 00379 } 00380 myCurrentRouteDistribution = 0; 00381 } 00382 } 00383 00384 00385 void 00386 MSRouteHandler::closeVehicle() { 00387 // get nested route 00388 const MSRoute* route = MSRoute::dictionary("!" + myVehicleParameter->id); 00389 MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl(); 00390 if (myVehicleParameter->departProcedure == DEPART_GIVEN) { 00391 // let's check whether this vehicle had to depart before the simulation starts 00392 if (!(myAddVehiclesDirectly || checkLastDepart()) || myVehicleParameter->depart < string2time(OptionsCont::getOptions().getString("begin"))) { 00393 if (route != 0) { 00394 route->addReference(); 00395 route->release(); 00396 } 00397 return; 00398 } 00399 } 00400 // get the vehicle's type 00401 MSVehicleType* vtype = 0; 00402 if (myVehicleParameter->vtypeid != "") { 00403 vtype = vehControl.getVType(myVehicleParameter->vtypeid); 00404 if (vtype == 0) { 00405 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00406 } 00407 } else { 00408 // there should be one (at least the default one) 00409 vtype = vehControl.getVType(); 00410 } 00411 if (route == 0) { 00412 // if there is no nested route, try via the (hopefully) given route-id 00413 route = MSRoute::dictionary(myVehicleParameter->routeid); 00414 } 00415 if (route == 0) { 00416 // nothing found? -> error 00417 if (myVehicleParameter->routeid != "") { 00418 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00419 } else { 00420 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route."); 00421 } 00422 } 00423 myActiveRouteID = ""; 00424 00425 // try to build the vehicle 00426 SUMOVehicle* vehicle = 0; 00427 if (vehControl.getVehicle(myVehicleParameter->id) == 0) { 00428 vehicle = vehControl.buildVehicle(myVehicleParameter, route, vtype); 00429 // maybe we do not want this vehicle to be inserted due to scaling 00430 if (myScale < 0 || vehControl.isInQuota(myScale)) { 00431 // add the vehicle to the vehicle control 00432 vehControl.addVehicle(myVehicleParameter->id, vehicle); 00433 if (myVehicleParameter->departProcedure == DEPART_TRIGGERED) { 00434 vehControl.addWaiting(*route->begin(), vehicle); 00435 vehControl.registerOneWaitingForPerson(); 00436 } 00437 registerLastDepart(); 00438 myVehicleParameter = 0; 00439 } else { 00440 vehControl.deleteVehicle(vehicle, true); 00441 myVehicleParameter = 0; 00442 vehicle = 0; 00443 } 00444 } else { 00445 // strange: another vehicle with the same id already exists 00446 #ifdef HAVE_MESOSIM 00447 if (!MSGlobals::gStateLoaded) { 00448 #endif 00449 // and was not loaded while loading a simulation state 00450 // -> error 00451 throw ProcessError("Another vehicle with the id '" + myVehicleParameter->id + "' exists."); 00452 #ifdef HAVE_MESOSIM 00453 } else { 00454 // ok, it seems to be loaded previously while loading a simulation state 00455 vehicle = 0; 00456 } 00457 #endif 00458 } 00459 // check whether the vehicle shall be added directly to the network or 00460 // shall stay in the internal buffer 00461 if (vehicle != 0) { 00462 if (vehicle->getParameter().departProcedure == DEPART_GIVEN) { 00463 MSNet::getInstance()->getInsertionControl().add(vehicle); 00464 } 00465 } 00466 } 00467 00468 00469 void 00470 MSRouteHandler::closePerson() { 00471 if (myActivePlan->size() == 0) { 00472 throw ProcessError("Person '" + myVehicleParameter->id + "' has no plan."); 00473 } 00474 MSPerson* person = new MSPerson(myVehicleParameter, myActivePlan); 00475 // @todo: consider myScale? 00476 if ((myAddVehiclesDirectly || checkLastDepart()) && MSNet::getInstance()->getPersonControl().add(myVehicleParameter->id, person)) { 00477 MSNet::getInstance()->getPersonControl().setArrival(myVehicleParameter->depart, person); 00478 registerLastDepart(); 00479 } else { 00480 delete person; 00481 } 00482 myVehicleParameter = 0; 00483 myActivePlan = 0; 00484 } 00485 00486 00487 void 00488 MSRouteHandler::closeFlow() { 00489 // @todo: consider myScale? 00490 // let's check whether vehicles had to depart before the simulation starts 00491 myVehicleParameter->repetitionsDone = 0; 00492 SUMOTime offsetToBegin = string2time(OptionsCont::getOptions().getString("begin")) - myVehicleParameter->depart; 00493 while (myVehicleParameter->repetitionsDone * myVehicleParameter->repetitionOffset < offsetToBegin) { 00494 myVehicleParameter->repetitionsDone++; 00495 if (myVehicleParameter->repetitionsDone == myVehicleParameter->repetitionNumber) { 00496 return; 00497 } 00498 } 00499 if (MSNet::getInstance()->getVehicleControl().getVType(myVehicleParameter->vtypeid) == 0) { 00500 throw ProcessError("The vehicle type '" + myVehicleParameter->vtypeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00501 } 00502 if (MSRoute::dictionary("!" + myVehicleParameter->id) == 0) { 00503 // if not, try via the (hopefully) given route-id 00504 if (MSRoute::dictionary(myVehicleParameter->routeid) == 0) { 00505 if (myVehicleParameter->routeid != "") { 00506 throw ProcessError("The route '" + myVehicleParameter->routeid + "' for vehicle '" + myVehicleParameter->id + "' is not known."); 00507 } else { 00508 throw ProcessError("Vehicle '" + myVehicleParameter->id + "' has no route."); 00509 } 00510 } 00511 } else { 00512 myVehicleParameter->routeid = "!" + myVehicleParameter->id; 00513 } 00514 myActiveRouteID = ""; 00515 00516 // check whether the vehicle shall be added directly to the network or 00517 // shall stay in the internal buffer 00518 if (myAddVehiclesDirectly || checkLastDepart()) { 00519 MSNet::getInstance()->getInsertionControl().add(myVehicleParameter); 00520 registerLastDepart(); 00521 } 00522 myVehicleParameter = 0; 00523 } 00524 00525 00526 void 00527 MSRouteHandler::addStop(const SUMOSAXAttributes& attrs) { 00528 bool ok = true; 00529 std::string errorSuffix; 00530 if (myActiveRouteID != "") { 00531 errorSuffix = " in route '" + myActiveRouteID + "'."; 00532 } else if (myActivePlan) { 00533 errorSuffix = " in person '" + myVehicleParameter->id + "'."; 00534 } else { 00535 errorSuffix = " in vehicle '" + myVehicleParameter->id + "'."; 00536 } 00537 SUMOVehicleParameter::Stop stop; 00538 // try to parse the assigned bus stop 00539 stop.busstop = attrs.getOptStringReporting(SUMO_ATTR_BUS_STOP, 0, ok, ""); 00540 if (stop.busstop != "") { 00541 // ok, we have obviously a bus stop 00542 MSBusStop* bs = MSNet::getInstance()->getBusStop(stop.busstop); 00543 if (bs != 0) { 00544 const MSLane& l = bs->getLane(); 00545 stop.lane = l.getID(); 00546 stop.endPos = bs->getEndLanePosition(); 00547 stop.startPos = bs->getBeginLanePosition(); 00548 } else { 00549 WRITE_ERROR("The bus stop '" + stop.busstop + "' is not known" + errorSuffix); 00550 return; 00551 } 00552 } else { 00553 // no, the lane and the position should be given 00554 // get the lane 00555 stop.lane = attrs.getOptStringReporting(SUMO_ATTR_LANE, 0, ok, ""); 00556 if (ok && stop.lane != "") { 00557 if (MSLane::dictionary(stop.lane) == 0) { 00558 WRITE_ERROR("The lane '" + stop.lane + "' for a stop is not known" + errorSuffix); 00559 return; 00560 } 00561 } else { 00562 WRITE_ERROR("A stop must be placed on a bus stop or a lane" + errorSuffix); 00563 return; 00564 } 00565 if (myActivePlan && 00566 !myActivePlan->empty() && 00567 &myActivePlan->back()->getDestination() != &MSLane::dictionary(stop.lane)->getEdge()) { 00568 throw ProcessError("Disconnected plan for person '" + myVehicleParameter->id + "' (" + MSLane::dictionary(stop.lane)->getEdge().getID() + "!=" + myActivePlan->back()->getDestination().getID() + ")."); 00569 } 00570 stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_ENDPOS, 0, ok, MSLane::dictionary(stop.lane)->getLength()); 00571 if (attrs.hasAttribute(SUMO_ATTR_POSITION)) { 00572 WRITE_WARNING("Deprecated attribute 'pos' in description of stop" + errorSuffix); 00573 stop.endPos = attrs.getOptSUMORealReporting(SUMO_ATTR_POSITION, 0, ok, stop.endPos); 00574 } 00575 stop.startPos = attrs.getOptSUMORealReporting(SUMO_ATTR_STARTPOS, 0, ok, stop.endPos - 2 * POSITION_EPS); 00576 const bool friendlyPos = attrs.getOptBoolReporting(SUMO_ATTR_FRIENDLY_POS, 0, ok, false); 00577 if (!ok || !checkStopPos(stop.startPos, stop.endPos, MSLane::dictionary(stop.lane)->getLength(), POSITION_EPS, friendlyPos)) { 00578 WRITE_ERROR("Invalid start or end position for stop" + errorSuffix); 00579 return; 00580 } 00581 } 00582 00583 // get the standing duration 00584 if (!attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL)) { 00585 stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, true); 00586 stop.duration = -1; 00587 stop.until = -1; 00588 } else { 00589 stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, 0, ok, -1); 00590 stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, 0, ok, -1); 00591 if (!ok || (stop.duration < 0 && stop.until < 0)) { 00592 WRITE_ERROR("Invalid duration or end time is given for a stop" + errorSuffix); 00593 return; 00594 } 00595 stop.triggered = attrs.getOptBoolReporting(SUMO_ATTR_TRIGGERED, 0, ok, false); 00596 } 00597 stop.parking = attrs.getOptBoolReporting(SUMO_ATTR_PARKING, 0, ok, stop.triggered); 00598 if (!ok) { 00599 WRITE_ERROR("Invalid bool for 'triggered' or 'parking' for stop" + errorSuffix); 00600 return; 00601 } 00602 const std::string idx = attrs.getOptStringReporting(SUMO_ATTR_INDEX, 0, ok, "end"); 00603 if (idx == "end") { 00604 stop.index = STOP_INDEX_END; 00605 } else if (idx == "fit") { 00606 stop.index = STOP_INDEX_FIT; 00607 } else { 00608 stop.index = attrs.getIntReporting(SUMO_ATTR_INDEX, 0, ok); 00609 if (!ok || stop.index < 0) { 00610 WRITE_ERROR("Invalid 'index' for stop" + errorSuffix); 00611 return; 00612 } 00613 } 00614 if (myActiveRouteID != "") { 00615 myActiveRouteStops.push_back(stop); 00616 } else if (myActivePlan) { 00617 myActivePlan->push_back(new MSPerson::MSPersonStage_Waiting(MSLane::dictionary(stop.lane)->getEdge(), stop.duration, stop.until)); 00618 } else { 00619 myVehicleParameter->stops.push_back(stop); 00620 } 00621 } 00622 00623 00624 /****************************************************************************/