SUMO - Simulation of Urban MObility
MSRouteHandler.cpp
Go to the documentation of this file.
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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines