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