Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2013-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSDevice_FCD.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @author Jakob Erdmann
18 : /// @date 11.06.2013
19 : ///
20 : // A device which stands as an implementation FCD and which outputs movereminder calls
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <bitset>
25 : #include <utils/common/StringUtils.h>
26 : #include <utils/options/OptionsCont.h>
27 : #include <utils/iodevices/OutputDevice.h>
28 : #include <utils/vehicle/SUMOVehicle.h>
29 : #include <utils/shapes/ShapeContainer.h>
30 : #include <utils/shapes/SUMOPolygon.h>
31 : #include <microsim/MSNet.h>
32 : #include <microsim/MSLane.h>
33 : #include <microsim/MSEdge.h>
34 : #include <microsim/MSVehicle.h>
35 : #include "MSDevice_FCD.h"
36 :
37 :
38 : // ===========================================================================
39 : // static members
40 : // ===========================================================================
41 : std::set<const MSEdge*> MSDevice_FCD::myEdgeFilter;
42 : std::vector<PositionVector> MSDevice_FCD::myShape4Filters;
43 : bool MSDevice_FCD::myEdgeFilterInitialized(false);
44 : bool MSDevice_FCD::myShapeFilterInitialized(false);
45 : bool MSDevice_FCD::myShapeFilterDesired(false);
46 : SumoXMLAttrMask MSDevice_FCD::myWrittenAttributes(getDefaultMask());
47 :
48 : // ===========================================================================
49 : // method definitions
50 : // ===========================================================================
51 : // ---------------------------------------------------------------------------
52 : // static initialisation methods
53 : // ---------------------------------------------------------------------------
54 : void
55 43644 : MSDevice_FCD::insertOptions(OptionsCont& oc) {
56 43644 : oc.addOptionSubTopic("FCD Device");
57 87288 : insertDefaultAssignmentOptions("fcd", "FCD Device", oc);
58 :
59 87288 : oc.doRegister("device.fcd.begin", new Option_String("-1"));
60 87288 : oc.addDescription("device.fcd.begin", "FCD Device", TL("Recording begin time for FCD-data"));
61 :
62 87288 : oc.doRegister("device.fcd.period", new Option_String("0"));
63 87288 : oc.addDescription("device.fcd.period", "FCD Device", TL("Recording period for FCD-data"));
64 :
65 43644 : oc.doRegister("device.fcd.radius", new Option_Float(0));
66 87288 : oc.addDescription("device.fcd.radius", "FCD Device", TL("Record objects in a radius around equipped vehicles"));
67 43644 : }
68 :
69 :
70 : void
71 5104369 : MSDevice_FCD::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
72 5104369 : OptionsCont& oc = OptionsCont::getOptions();
73 10208738 : if (equippedByDefaultAssignmentOptions(oc, "fcd", v, oc.isSet("fcd-output"))) {
74 19477 : MSDevice_FCD* device = new MSDevice_FCD(v, "fcd_" + v.getID());
75 19477 : into.push_back(device);
76 19477 : initOnce();
77 : }
78 5104369 : }
79 :
80 :
81 : // ---------------------------------------------------------------------------
82 : // MSDevice_FCD-methods
83 : // ---------------------------------------------------------------------------
84 19477 : MSDevice_FCD::MSDevice_FCD(SUMOVehicle& holder, const std::string& id) :
85 19477 : MSVehicleDevice(holder, id) {
86 19477 : }
87 :
88 :
89 38950 : MSDevice_FCD::~MSDevice_FCD() {
90 38950 : }
91 :
92 :
93 : SumoXMLAttrMask
94 83879 : MSDevice_FCD::getDefaultMask() {
95 83879 : SumoXMLAttrMask mask;
96 : // set all bits to 1
97 : mask.set();
98 : // some attributes are not written by default and must be enabled via option fcd-output.attributes
99 : // (or with an explicit attribute list)
100 : mask.reset(SUMO_ATTR_VEHICLE);
101 : mask.reset(SUMO_ATTR_ODOMETER);
102 : mask.reset(SUMO_ATTR_SPEED_LAT);
103 : mask.reset(SUMO_ATTR_POSITION_LAT);
104 : mask.reset(SUMO_ATTR_ARRIVALDELAY);
105 : mask.reset(SUMO_ATTR_SEGMENT);
106 : mask.reset(SUMO_ATTR_QUEUE);
107 : mask.reset(SUMO_ATTR_ENTRYTIME);
108 : mask.reset(SUMO_ATTR_EVENTTIME);
109 : mask.reset(SUMO_ATTR_BLOCKTIME);
110 83879 : return mask;
111 : }
112 :
113 :
114 : bool
115 2696 : MSDevice_FCD::shapeFilter(const SUMOTrafficObject* veh) {
116 : // lazily build the shape filter in the case where route file is loaded as an additional file
117 2696 : if (!myShapeFilterInitialized) {
118 6 : buildShapeFilter();
119 : }
120 2696 : const MSVehicle* msVeh = dynamic_cast<const MSVehicle*>(veh);
121 4882 : for (auto shape : myShape4Filters) {
122 4308 : if (shape.around(veh->getPosition()) || ((msVeh != nullptr) && shape.around(msVeh->getBackPosition()))) {
123 : return true;
124 : }
125 2696 : }
126 2186 : return false;
127 : }
128 :
129 :
130 : void
131 12 : MSDevice_FCD::buildShapeFilter(void) {
132 12 : const OptionsCont& oc = OptionsCont::getOptions();
133 24 : if (oc.isSet("fcd-output.filter-shapes")) {
134 12 : const ShapeContainer& loadedShapes = MSNet::getInstance()->getShapeContainer();
135 12 : if (loadedShapes.getPolygons().size() > 0) {
136 18 : for (std::string attrName : oc.getStringVector("fcd-output.filter-shapes")) {
137 6 : if (loadedShapes.getPolygons().get(attrName) == 0) {
138 0 : WRITE_ERRORF(TL("Specified shape '%' for filtering fcd-output could not be found."), attrName);
139 : } else {
140 : // store the PositionVector, not reference, as traci can manipulate / detete the polygons
141 6 : myShape4Filters.push_back(loadedShapes.getPolygons().get(attrName)->getShape());
142 : }
143 : }
144 6 : myShapeFilterInitialized = true;
145 : }
146 : } else {
147 0 : myShapeFilterInitialized = true;
148 : }
149 12 : }
150 :
151 :
152 : void
153 21426 : MSDevice_FCD::initOnce() {
154 21426 : if (myEdgeFilterInitialized) {
155 : return;
156 : }
157 2684 : myEdgeFilterInitialized = true;
158 2684 : const OptionsCont& oc = OptionsCont::getOptions();
159 5368 : if (oc.isSet("fcd-output.filter-edges.input-file")) {
160 12 : const std::string file = oc.getString("fcd-output.filter-edges.input-file");
161 6 : std::ifstream strm(file.c_str());
162 6 : if (!strm.good()) {
163 0 : throw ProcessError(TLF("Could not load names of edges for filtering fcd-output from '%'.", file));
164 : }
165 12 : while (strm.good()) {
166 : std::string name;
167 6 : strm >> name;
168 : // maybe we're loading an edge-selection
169 12 : if (StringUtils::startsWith(name, "edge:")) {
170 12 : name = name.substr(5);
171 : }
172 6 : myEdgeFilter.insert(MSEdge::dictionary(name));
173 : }
174 6 : }
175 5368 : if (oc.isSet("fcd-output.attributes")) {
176 : myWrittenAttributes.reset();
177 1134 : for (std::string attrName : oc.getStringVector("fcd-output.attributes")) {
178 555 : if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
179 25 : if (attrName == "all") {
180 : myWrittenAttributes.set();
181 : } else {
182 0 : WRITE_ERRORF(TL("Unknown attribute '%' to write in fcd output."), attrName);
183 : }
184 : continue;
185 : }
186 505 : int attr = SUMOXMLDefinitions::Attrs.get(attrName);
187 505 : myWrittenAttributes.set(attr);
188 : }
189 : }
190 :
191 5368 : if (oc.isSet("fcd-output.filter-shapes")) {
192 : // build the shape filter if it is desired
193 6 : myShapeFilterDesired = true;
194 6 : buildShapeFilter();
195 : }
196 : //std::cout << "mask=" << myWrittenAttributes << " binary=" << std::bitset<64>(myWrittenAttributes) << "\n";
197 : }
198 :
199 :
200 : void
201 40275 : MSDevice_FCD::cleanup() {
202 : myEdgeFilter.clear();
203 : myShape4Filters.clear();
204 40275 : myEdgeFilterInitialized = false;
205 40275 : myShapeFilterInitialized = false;
206 40275 : myShapeFilterDesired = false;
207 40275 : myWrittenAttributes = getDefaultMask();
208 40275 : }
209 :
210 :
211 : /****************************************************************************/
|