1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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    MSDetectorControl.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Clemens Honomichl
14 /// @author  Sascha Krieg
15 /// @author  Michael Behrisch
16 /// @author  Laura Bieker
17 /// @date    2005-09-15
18 /// @version $Id$
19 ///
20 // Detectors container; responsible for string and output generation
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #include <config.h>
28 
29 #include <iostream>
30 #include "MSDetectorControl.h"
31 #include "MSMeanData_Net.h"
32 #include <utils/options/OptionsCont.h>
33 #include <utils/options/Option.h>
34 #include <utils/common/MsgHandler.h>
35 
36 
37 // ===========================================================================
38 // member method definitions
39 // ===========================================================================
MSDetectorControl()40 MSDetectorControl::MSDetectorControl() {
41 }
42 
43 
~MSDetectorControl()44 MSDetectorControl::~MSDetectorControl() {
45     for (std::map<SumoXMLTag, NamedObjectCont<MSDetectorFileOutput*> >::iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
46         (*i).second.clear();
47     }
48     for (std::vector<MSMeanData*>::const_iterator i = myMeanData.begin(); i != myMeanData.end(); ++i) {
49         delete *i;
50     }
51 }
52 
53 
54 void
close(SUMOTime step)55 MSDetectorControl::close(SUMOTime step) {
56     // flush the last values
57     writeOutput(step, true);
58     // [...] files are closed on another place [...]
59     myIntervals.clear();
60 }
61 
62 
63 void
add(SumoXMLTag type,MSDetectorFileOutput * d,const std::string & device,SUMOTime splInterval,SUMOTime begin)64 MSDetectorControl::add(SumoXMLTag type, MSDetectorFileOutput* d, const std::string& device, SUMOTime splInterval, SUMOTime begin) {
65     if (!myDetectors[type].add(d->getID(), d)) {
66         throw ProcessError(toString(type) + " detector '" + d->getID() + "' could not be build (declared twice?).");
67     }
68     addDetectorAndInterval(d, &OutputDevice::getDevice(device), splInterval, begin);
69 }
70 
71 
72 
73 void
add(SumoXMLTag type,MSDetectorFileOutput * d)74 MSDetectorControl::add(SumoXMLTag type, MSDetectorFileOutput* d) {
75     if (!myDetectors[type].add(d->getID(), d)) {
76         throw ProcessError(toString(type) + " detector '" + d->getID() + "' could not be build (declared twice?).");
77     }
78 }
79 
80 
81 
82 void
add(MSMeanData * mn,const std::string & device,SUMOTime frequency,SUMOTime begin)83 MSDetectorControl::add(MSMeanData* mn, const std::string& device,
84                        SUMOTime frequency, SUMOTime begin) {
85     myMeanData.push_back(mn);
86     addDetectorAndInterval(mn, &OutputDevice::getDevice(device), frequency, begin);
87     if (begin == string2time(OptionsCont::getOptions().getString("begin"))) {
88         mn->init();
89     }
90 }
91 
92 
93 const std::vector<SumoXMLTag>
getAvailableTypes() const94 MSDetectorControl::getAvailableTypes() const {
95     std::vector<SumoXMLTag> result;
96     for (std::map<SumoXMLTag, NamedObjectCont<MSDetectorFileOutput*> >::const_iterator i = myDetectors.begin(); i != myDetectors.end(); ++i) {
97         result.push_back(i->first);
98     }
99     return result;
100 }
101 
102 
103 const NamedObjectCont<MSDetectorFileOutput*>&
getTypedDetectors(SumoXMLTag type) const104 MSDetectorControl::getTypedDetectors(SumoXMLTag type) const {
105     if (myDetectors.find(type) == myDetectors.end()) {
106         return myEmptyContainer;
107     }
108     return myDetectors.find(type)->second;
109 }
110 
111 
112 void
updateDetectors(const SUMOTime step)113 MSDetectorControl::updateDetectors(const SUMOTime step) {
114     for (const auto& i : myDetectors) {
115         for (const auto& j : getTypedDetectors(i.first)) {
116             j.second->detectorUpdate(step);
117         }
118     }
119     for (MSMeanData* const i : myMeanData) {
120         i->detectorUpdate(step);
121     }
122 }
123 
124 
125 void
writeOutput(SUMOTime step,bool closing)126 MSDetectorControl::writeOutput(SUMOTime step, bool closing) {
127     for (Intervals::iterator i = myIntervals.begin(); i != myIntervals.end(); ++i) {
128         IntervalsKey interval = (*i).first;
129         if (myLastCalls[interval] + interval.first <= step || (closing && myLastCalls[interval] < step)) {
130             DetectorFileVec dfVec = (*i).second;
131             SUMOTime startTime = myLastCalls[interval];
132             // check whether at the end the output was already generated
133             for (DetectorFileVec::iterator it = dfVec.begin(); it != dfVec.end(); ++it) {
134                 MSDetectorFileOutput* det = it->first;
135                 det->writeXMLOutput(*(it->second), startTime, step);
136             }
137             myLastCalls[interval] = step;
138         }
139     }
140 }
141 
142 
143 void
addDetectorAndInterval(MSDetectorFileOutput * det,OutputDevice * device,SUMOTime interval,SUMOTime begin)144 MSDetectorControl::addDetectorAndInterval(MSDetectorFileOutput* det,
145         OutputDevice* device,
146         SUMOTime interval,
147         SUMOTime begin) {
148     if (begin == -1) {
149         begin = string2time(OptionsCont::getOptions().getString("begin"));
150     }
151     IntervalsKey key = std::make_pair(interval, begin);
152     Intervals::iterator it = myIntervals.find(key);
153     // Add command for given key only once to MSEventControl...
154     if (it == myIntervals.end()) {
155         DetectorFileVec detAndFileVec;
156         detAndFileVec.push_back(std::make_pair(det, device));
157         myIntervals.insert(std::make_pair(key, detAndFileVec));
158         myLastCalls[key] = begin;
159     } else {
160         DetectorFileVec& detAndFileVec = it->second;
161         if (find_if(detAndFileVec.begin(), detAndFileVec.end(), bind2nd(detectorEquals(), det)) == detAndFileVec.end()) {
162             detAndFileVec.push_back(std::make_pair(det, device));
163         } else {
164             // detector already in container. Don't add several times
165             WRITE_WARNING("MSDetectorControl::addDetectorAndInterval: detector already in container. Ignoring.");
166             return;
167         }
168     }
169     det->writeXMLDetectorProlog(*device);
170 }
171 
172 
173 
174 /****************************************************************************/
175 
176