Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2007-2025 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 : /// @brief extracts the deviceName from the id (which includes holder id) and is subject to special cases
90 : static std::string getDeviceName(const std::string& id);
91 :
92 : static SumoRNG* getEquipmentRNG() {
93 : return &myEquipmentRNG;
94 : }
95 :
96 : /// @brief return the name for this type of device
97 : virtual const std::string deviceName() const = 0;
98 :
99 : /// @brief perform cleanup for all devices
100 : static void cleanupAll();
101 :
102 : static const std::string LOADSTATE_DEVICENAMES;
103 :
104 : public:
105 : /** @brief Constructor
106 : *
107 : * @param[in] id The ID of the device
108 : */
109 2557 : MSDevice(const std::string& id) : Named(id) {
110 : }
111 :
112 :
113 : /// @brief Destructor
114 6120964 : virtual ~MSDevice() { }
115 :
116 :
117 : /** @brief Called on vehicle deletion to extend tripinfo and other outputs
118 : *
119 : * The device may write some statistics into the tripinfo output and may
120 : * choose to finalize its own outputs. It is assumed that the
121 : * information written to tripinfoOut is a valid xml-snipplet, which
122 : * will be embedded within the vehicle's tripinfo information.
123 : *
124 : * The device should use the openTag / closeTag methods of the OutputDevice
125 : * for correct indentation.
126 : *
127 : * @exception IOError not yet implemented
128 : */
129 978751 : virtual void generateOutput(OutputDevice* /*tripinfoOut*/) const {
130 978751 : }
131 :
132 : /** @brief Saves the state of the device
133 : *
134 : * The default implementation writes a warning and does nothing.
135 : * @param[in] out The OutputDevice to write the information into
136 : */
137 : virtual void saveState(OutputDevice& out) const;
138 :
139 : /** @brief Loads the state of the device from the given description
140 : *
141 : * The default implementation does nothing.
142 : * @param[in] attrs XML attributes describing the current state
143 : */
144 : virtual void loadState(const SUMOSAXAttributes& attrs);
145 :
146 : /// @brief try to retrieve the given parameter from this device. Throw exception for unsupported key
147 0 : virtual std::string getParameter(const std::string& key) const {
148 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
149 : }
150 :
151 : /// @brief try to set the given parameter for this device. Throw exception for unsupported key
152 0 : virtual void setParameter(const std::string& key, const std::string& value) {
153 : UNUSED_PARAMETER(value);
154 0 : throw InvalidArgument("Setting parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
155 : }
156 :
157 : protected:
158 : /// @name Helper methods for device assignment
159 : /// @{
160 :
161 : /** @brief Adds common command options that allow to assign devices to vehicles
162 : *
163 : * @param[in] deviceName The name of the device type
164 : * @param[in] optionsTopic The options topic into which the options shall be added
165 : * @param[filled] oc The options container to add the options to
166 : */
167 : static void insertDefaultAssignmentOptions(const std::string& deviceName, const std::string& optionsTopic, OptionsCont& oc, const bool isPerson = false);
168 :
169 :
170 : /** @brief Determines whether a vehicle should get a certain device
171 : *
172 : * @param[in] oc The options container to get the information about assignment from
173 : * @param[in] deviceName The name of the device type
174 : * @param[in] v The vehicle to determine whether it shall be equipped or not
175 : */
176 : template<class DEVICEHOLDER>
177 : static bool equippedByDefaultAssignmentOptions(const OptionsCont& oc, const std::string& deviceName, DEVICEHOLDER& v, bool outputOptionSet, const bool isPerson = false);
178 : /// @}
179 :
180 :
181 : private:
182 : /// @brief vehicles which explicitly carry a device, sorted by device, first
183 : static std::map<std::string, std::set<std::string> > myExplicitIDs;
184 :
185 : /// @brief A random number generator used to choose from vtype/route distributions and computing the speed factors
186 : static SumoRNG myEquipmentRNG;
187 :
188 :
189 : private:
190 : /// @brief Invalidated copy constructor.
191 : MSDevice(const MSDevice&);
192 :
193 : /// @brief Invalidated assignment operator.
194 : MSDevice& operator=(const MSDevice&);
195 :
196 : };
197 :
198 :
199 : template<class DEVICEHOLDER> bool
200 109154808 : MSDevice::equippedByDefaultAssignmentOptions(const OptionsCont& oc, const std::string& deviceName, DEVICEHOLDER& v, bool outputOptionSet, const bool isPerson) {
201 215971385 : const std::string prefix = (isPerson ? "person-device." : "device.") + deviceName;
202 : // assignment by number
203 326951073 : bool numberGiven = ((oc.exists(prefix + ".deterministic") && oc.getBool(prefix + ".deterministic"))
204 435862504 : || (oc.exists(prefix + ".probability") && oc.getFloat(prefix + ".probability") >= 0.));
205 109154808 : double probability = numberGiven ? oc.getFloat(prefix + ".probability") : 0;
206 : // assignment by name
207 : bool haveByName = false;
208 : bool nameGiven = false;
209 217796265 : if (oc.exists(prefix + ".explicit") && oc.isSet(prefix + ".explicit")) {
210 : nameGiven = true;
211 13546 : if (myExplicitIDs.find(deviceName) == myExplicitIDs.end()) {
212 476 : myExplicitIDs[deviceName] = std::set<std::string>();
213 476 : const std::vector<std::string> idList = OptionsCont::getOptions().getStringVector(prefix + ".explicit");
214 476 : myExplicitIDs[deviceName].insert(idList.begin(), idList.end());
215 476 : }
216 27092 : haveByName = myExplicitIDs[deviceName].count(v.getID()) > 0;
217 : }
218 : // assignment by abstract parameters
219 : bool haveByParameter = false;
220 : bool parameterGiven = false;
221 109154814 : const std::string key = "has." + deviceName + ".device";
222 109154808 : if (v.getParameter().hasParameter(key)) {
223 : parameterGiven = true;
224 7916 : haveByParameter = StringUtils::toBool(v.getParameter().getParameter(key, "false"));
225 109150850 : } else if (v.getVehicleType().getParameter().hasParameter(key)) {
226 : parameterGiven = true;
227 39638 : haveByParameter = StringUtils::toBool(v.getVehicleType().getParameter().getParameter(key, "false"));
228 218262056 : } else if (v.getVehicleType().getParameter().hasParameter(prefix + ".probability")) {
229 : // override global options
230 : numberGiven = true;
231 5260 : probability = StringUtils::toDouble(v.getVehicleType().getParameter().getParameter(prefix + ".probability", "0"));
232 : }
233 : //std::cout << " deviceName=" << deviceName << " holder=" << v.getID()
234 : // << " nameGiven=" << nameGiven << " haveByName=" << haveByName
235 : // << " parameterGiven=" << parameterGiven << " haveByParameter=" << haveByParameter
236 : // << " numberGiven=" << numberGiven << " haveByNumber=" << haveByNumber
237 : // << " outputOptionSet=" << outputOptionSet << "\n";
238 109154802 : if (haveByName) {
239 : return true;
240 109154000 : } else if (parameterGiven) {
241 : return haveByParameter;
242 109130226 : } else if (numberGiven) {
243 544836 : if (oc.exists(prefix + ".deterministic") && oc.getBool(prefix + ".deterministic")) {
244 12 : return MSNet::getInstance()->getVehicleControl().getQuota(probability) == 1;
245 272406 : } else if (probability > 0) {
246 271604 : if (v.getParameter().hasParameter(LOADSTATE_DEVICENAMES)) {
247 : // replicate probabilistic assignment
248 2118 : const std::vector<std::string> lsdn = StringTokenizer(v.getParameter().getParameter(LOADSTATE_DEVICENAMES)).getVector();
249 1056 : return std::find(lsdn.begin(), lsdn.end(), deviceName) != lsdn.end();
250 1056 : } else {
251 270548 : return RandHelper::rand(&myEquipmentRNG) < probability;
252 : }
253 : } else {
254 : return false;
255 : }
256 : } else {
257 108857808 : return !nameGiven && outputOptionSet;
258 : }
259 : }
|