1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2008-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSRouteProbe.cpp
11 /// @author  Michael Behrisch
12 /// @author  Daniel Krajzewicz
13 /// @author  Tino Morenz
14 /// @author  Jakob Erdmann
15 /// @date    Thu, 04.12.2008
16 /// @version $Id$
17 ///
18 // Writes route distributions at a certain edge
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
28 #include <microsim/MSEdge.h>
29 #include <microsim/MSLane.h>
30 #include <microsim/MSGlobals.h>
31 #include <microsim/MSRoute.h>
32 #include <microsim/MSVehicle.h>
33 #include <utils/common/ToString.h>
34 #include <utils/iodevices/OutputDevice.h>
35 #include <mesosim/MELoop.h>
36 #include <mesosim/MESegment.h>
37 #include "MSRouteProbe.h"
38 
39 
40 // ===========================================================================
41 // method definitions
42 // ===========================================================================
MSRouteProbe(const std::string & id,const MSEdge * edge,const std::string & distID,const std::string & lastID,const std::string & vTypes)43 MSRouteProbe::MSRouteProbe(const std::string& id, const MSEdge* edge, const std::string& distID, const std::string& lastID,
44                            const std::string& vTypes) :
45     MSDetectorFileOutput(id, vTypes), MSMoveReminder(id) {
46     myCurrentRouteDistribution = std::make_pair(distID, MSRoute::distDictionary(distID));
47     if (myCurrentRouteDistribution.second == 0) {
48         myCurrentRouteDistribution.second = new RandomDistributor<const MSRoute*>();
49         MSRoute::dictionary(distID, myCurrentRouteDistribution.second, false);
50     }
51     myLastRouteDistribution = std::make_pair(lastID, MSRoute::distDictionary(lastID));
52     if (MSGlobals::gUseMesoSim) {
53         MESegment* seg = MSGlobals::gMesoNet->getSegmentForEdge(*edge);
54         while (seg != nullptr) {
55             seg->addDetector(this);
56             seg = seg->getNextSegment();
57         }
58         return;
59     }
60     for (std::vector<MSLane*>::const_iterator it = edge->getLanes().begin(); it != edge->getLanes().end(); ++it) {
61         (*it)->addMoveReminder(this);
62     }
63 }
64 
65 
~MSRouteProbe()66 MSRouteProbe::~MSRouteProbe() {
67 }
68 
69 
70 bool
notifyEnter(SUMOTrafficObject & veh,MSMoveReminder::Notification reason,const MSLane *)71 MSRouteProbe::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
72     if (!vehicleApplies(veh)) {
73         return false;
74     }
75     if (reason != MSMoveReminder::NOTIFICATION_SEGMENT && reason != MSMoveReminder::NOTIFICATION_LANE_CHANGE) {
76         SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
77         if (vehicle != nullptr) {
78             if (myCurrentRouteDistribution.second->add(&vehicle->getRoute(), 1.)) {
79                 vehicle->getRoute().addReference();
80             }
81         }
82     }
83     return false;
84 }
85 
86 
87 void
writeXMLOutput(OutputDevice & dev,SUMOTime startTime,SUMOTime stopTime)88 MSRouteProbe::writeXMLOutput(OutputDevice& dev,
89                              SUMOTime startTime, SUMOTime stopTime) {
90     if (myCurrentRouteDistribution.second->getOverallProb() > 0) {
91         dev.openTag("routeDistribution") << " id=\"" << getID() + "_" + time2string(startTime) << "\"";
92         const std::vector<const MSRoute*>& routes = myCurrentRouteDistribution.second->getVals();
93         const std::vector<double>& probs = myCurrentRouteDistribution.second->getProbs();
94         for (int j = 0; j < (int)routes.size(); ++j) {
95             const MSRoute* r = routes[j];
96             dev.openTag("route") << " id=\"" << r->getID() + "_" + time2string(startTime) << "\" edges=\"";
97             for (MSRouteIterator i = r->begin(); i != r->end(); ++i) {
98                 if (i != r->begin()) {
99                     dev << " ";
100                 }
101                 dev << (*i)->getID();
102             }
103             dev << "\" probability=\"" << probs[j] << "\"";
104             dev.closeTag();
105         }
106         dev.closeTag();
107         if (myLastRouteDistribution.second != 0) {
108             MSRoute::checkDist(myLastRouteDistribution.first);
109         }
110         myLastRouteDistribution = myCurrentRouteDistribution;
111         myCurrentRouteDistribution.first = getID() + "_" + toString(stopTime);
112         myCurrentRouteDistribution.second = new RandomDistributor<const MSRoute*>();
113         MSRoute::dictionary(myCurrentRouteDistribution.first, myCurrentRouteDistribution.second, false);
114     }
115 }
116 
117 
118 void
writeXMLDetectorProlog(OutputDevice & dev) const119 MSRouteProbe::writeXMLDetectorProlog(OutputDevice& dev) const {
120     dev.writeXMLHeader("routes", "routes_file.xsd");
121 }
122 
123 
124 const MSRoute*
getRoute() const125 MSRouteProbe::getRoute() const {
126     if (myLastRouteDistribution.second == 0) {
127         if (myCurrentRouteDistribution.second->getOverallProb() > 0) {
128             return myCurrentRouteDistribution.second->get();
129         }
130         return nullptr;
131     }
132     return myLastRouteDistribution.second->get();
133 }
134