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     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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines