Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2007-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.h
15 : /// @author Michael Behrisch
16 : /// @author Daniel Krajzewicz
17 : /// @author Jakob Erdmann
18 : /// @date Tue, 04 Dec 2007
19 : ///
20 : // Abstract in-vehicle device
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <vector>
27 : #include <map>
28 : #include <set>
29 : #include <random>
30 : #include <microsim/MSMoveReminder.h>
31 : #include <microsim/MSNet.h>
32 : #include <microsim/MSVehicleType.h>
33 : #include <microsim/MSVehicleControl.h>
34 : #include <utils/common/Named.h>
35 : #include <utils/common/StringUtils.h>
36 : #include <utils/common/UtilExceptions.h>
37 : #include <utils/options/OptionsCont.h>
38 :
39 :
40 : // ===========================================================================
41 : // class declarations
42 : // ===========================================================================
43 : class OutputDevice;
44 : class SUMOVehicle;
45 : class MSTransportable;
46 : class SUMOSAXAttributes;
47 : class MSVehicleDevice;
48 : class MSTransportableDevice;
49 :
50 :
51 : // ===========================================================================
52 : // class definitions
53 : // ===========================================================================
54 : /**
55 : * @class MSDevice
56 : * @brief Abstract in-vehicle / in-person device
57 : *
58 : * The MSDevice-interface brings the following interfaces to a vehicle /person that
59 : * may be overwritten by real devices:
60 : * @arg Building and retrieval of a device id
61 : */
62 : class MSDevice : public Named {
63 : public:
64 : /** @brief Inserts options for building devices
65 : * @param[filled] oc The options container to add the options to
66 : */
67 : static void insertOptions(OptionsCont& oc);
68 :
69 : /** @brief check device-specific options
70 : * @param[filled] oc The options container with the user-defined options
71 : */
72 : static bool checkOptions(OptionsCont& oc);
73 :
74 :
75 : /** @brief Build devices for the given vehicle, if needed
76 : *
77 : * @param[in] v The vehicle for which a device may be built
78 : * @param[filled] into The vector to store the built device in
79 : */
80 : static void buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into);
81 :
82 : /** @brief Build devices for the given person, if needed
83 : *
84 : * @param[in] p The person for which a device may be built
85 : * @param[filled] into The vector to store the built device in
86 : */
87 : static void buildTransportableDevices(MSTransportable& p, std::vector<MSTransportableDevice*>& into);
88 :
89 : static SumoRNG* getEquipmentRNG() {
90 : return &myEquipmentRNG;
91 : }
92 :
93 : /// @brief return the name for this type of device
94 : virtual const std::string deviceName() const = 0;
95 :
96 : /// @brief perform cleanup for all devices
97 : static void cleanupAll();
98 :
99 : public:
100 : /** @brief Constructor
101 : *
102 : * @param[in] id The ID of the device
103 : */
104 2260 : MSDevice(const std::string& id) : Named(id) {
105 : }
106 :
107 :
108 : /// @brief Destructor
109 4565727 : virtual ~MSDevice() { }
110 :
111 :
112 : /** @brief Called on vehicle deletion to extend tripinfo and other outputs
113 : *
114 : * The device may write some statistics into the tripinfo output and may
115 : * choose to finalize its own outputs. It is assumed that the
116 : * information written to tripinfoOut is a valid xml-snipplet, which
117 : * will be embedded within the vehicle's tripinfo information.
118 : *
119 : * The device should use the openTag / closeTag methods of the OutputDevice
120 : * for correct indentation.
121 : *
122 : * @exception IOError not yet implemented
123 : */
124 939589 : virtual void generateOutput(OutputDevice* /*tripinfoOut*/) const {
125 939589 : }
126 :
127 : /** @brief Saves the state of the device
128 : *
129 : * The default implementation writes a warning and does nothing.
130 : * @param[in] out The OutputDevice to write the information into
131 : */
132 : virtual void saveState(OutputDevice& out) const;
133 :
134 : /** @brief Loads the state of the device from the given description
135 : *
136 : * The default implementation does nothing.
137 : * @param[in] attrs XML attributes describing the current state
138 : */
139 : virtual void loadState(const SUMOSAXAttributes& attrs);
140 :
141 : /// @brief try to retrieve the given parameter from this device. Throw exception for unsupported key
142 0 : virtual std::string getParameter(const std::string& key) const {
143 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
144 : }
145 :
146 : /// @brief try to set the given parameter for this device. Throw exception for unsupported key
147 0 : virtual void setParameter(const std::string& key, const std::string& value) {
148 : UNUSED_PARAMETER(value);
149 0 : throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
150 : }
151 :
152 : protected:
153 : /// @name Helper methods for device assignment
154 : /// @{
155 :
156 : /** @brief Adds common command options that allow to assign devices to vehicles
157 : *
158 : * @param[in] deviceName The name of the device type
159 : * @param[in] optionsTopic The options topic into which the options shall be added
160 : * @param[filled] oc The options container to add the options to
161 : */
162 : static void insertDefaultAssignmentOptions(const std::string& deviceName, const std::string& optionsTopic, OptionsCont& oc, const bool isPerson = false);
163 :
164 :
165 : /** @brief Determines whether a vehicle should get a certain device
166 : *
167 : * @param[in] oc The options container to get the information about assignment from
168 : * @param[in] deviceName The name of the device type
169 : * @param[in] v The vehicle to determine whether it shall be equipped or not
170 : */
171 : template<class DEVICEHOLDER>
172 : static bool equippedByDefaultAssignmentOptions(const OptionsCont& oc, const std::string& deviceName, DEVICEHOLDER& v, bool outputOptionSet, const bool isPerson = false);
173 : /// @}
174 :
175 :
176 : private:
177 : /// @brief vehicles which explicitly carry a device, sorted by device, first
178 : static std::map<std::string, std::set<std::string> > myExplicitIDs;
179 :
180 : /// @brief A random number generator used to choose from vtype/route distributions and computing the speed factors
181 : static SumoRNG myEquipmentRNG;
182 :
183 :
184 : private:
185 : /// @brief Invalidated copy constructor.
186 : MSDevice(const MSDevice&);
187 :
188 : /// @brief Invalidated assignment operator.
189 : MSDevice& operator=(const MSDevice&);
190 :
191 : };
192 :
193 :
194 : template<class DEVICEHOLDER> bool
195 103649666 : MSDevice::equippedByDefaultAssignmentOptions(const OptionsCont& oc, const std::string& deviceName, DEVICEHOLDER& v, bool outputOptionSet, const bool isPerson) {
196 205011261 : const std::string prefix = (isPerson ? "person-device." : "device.") + deviceName;
197 : // assignment by number
198 : bool haveByNumber = false;
199 : bool numberGiven = false;
200 206797366 : if (oc.exists(prefix + ".deterministic") && oc.getBool(prefix + ".deterministic")) {
201 : numberGiven = true;
202 12 : haveByNumber = MSNet::getInstance()->getVehicleControl().getQuota(oc.getFloat(prefix + ".probability")) == 1;
203 : } else {
204 206797342 : if (oc.exists(prefix + ".probability") && oc.getFloat(prefix + ".probability") >= 0.) {
205 : numberGiven = true;
206 265578 : haveByNumber = RandHelper::rand(&myEquipmentRNG) < oc.getFloat(prefix + ".probability");
207 : }
208 : }
209 : // assignment by name
210 : bool haveByName = false;
211 : bool nameGiven = false;
212 206797366 : if (oc.exists(prefix + ".explicit") && oc.isSet(prefix + ".explicit")) {
213 : nameGiven = true;
214 3489 : if (myExplicitIDs.find(deviceName) == myExplicitIDs.end()) {
215 450 : myExplicitIDs[deviceName] = std::set<std::string>();
216 450 : const std::vector<std::string> idList = OptionsCont::getOptions().getStringVector(prefix + ".explicit");
217 450 : myExplicitIDs[deviceName].insert(idList.begin(), idList.end());
218 450 : }
219 6978 : haveByName = myExplicitIDs[deviceName].count(v.getID()) > 0;
220 : }
221 : // assignment by abstract parameters
222 : bool haveByParameter = false;
223 : bool parameterGiven = false;
224 103649672 : const std::string key = "has." + deviceName + ".device";
225 103649666 : if (v.getParameter().hasParameter(key)) {
226 : parameterGiven = true;
227 7742 : haveByParameter = StringUtils::toBool(v.getParameter().getParameter(key, "false"));
228 103645795 : } else if (v.getVehicleType().getParameter().hasParameter(key)) {
229 : parameterGiven = true;
230 39088 : haveByParameter = StringUtils::toBool(v.getVehicleType().getParameter().getParameter(key, "false"));
231 207252496 : } else if (v.getVehicleType().getParameter().hasParameter(prefix + ".probability")) {
232 : // override global options
233 : numberGiven = true;
234 5266 : haveByNumber = RandHelper::rand(&myEquipmentRNG) < StringUtils::toDouble(v.getVehicleType().getParameter().getParameter(prefix + ".probability", "0"));
235 : }
236 : //std::cout << " deviceName=" << deviceName << " holder=" << v.getID()
237 : // << " nameGiven=" << nameGiven << " haveByName=" << haveByName
238 : // << " parameterGiven=" << parameterGiven << " haveByParameter=" << haveByParameter
239 : // << " numberGiven=" << numberGiven << " haveByNumber=" << haveByNumber
240 : // << " outputOptionSet=" << outputOptionSet << "\n";
241 103649660 : if (haveByName) {
242 : return true;
243 103648884 : } else if (parameterGiven) {
244 : return haveByParameter;
245 103625472 : } else if (numberGiven) {
246 : return haveByNumber;
247 : } else {
248 103357474 : return !nameGiven && outputOptionSet;
249 : }
250 : }
|