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_ToC.cpp
15 : /// @author Leonhard Luecken
16 : /// @author Daniel Krajzewicz
17 : /// @author Michael Behrisch
18 : /// @author Jakob Erdmann
19 : /// @date 01.04.2018
20 : ///
21 : // The ToC Device controls the transition of control between automated and manual driving.
22 : //
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <algorithm>
27 : #include <memory>
28 : #include <utils/common/StringUtils.h>
29 : #include <utils/options/OptionsCont.h>
30 : #include <utils/vehicle/SUMOVehicle.h>
31 : #include <utils/common/WrappingCommand.h>
32 : #include <utils/common/RGBColor.h>
33 : #include <microsim/MSNet.h>
34 : #include <microsim/MSLane.h>
35 : #include <microsim/MSVehicle.h>
36 : #include <microsim/MSRouteHandler.h>
37 : #include <microsim/MSVehicleControl.h>
38 : #include <microsim/MSEventControl.h>
39 : #include <microsim/MSDriverState.h>
40 : #include <microsim/MSStoppingPlace.h>
41 : #include <microsim/MSStop.h>
42 : #include "MSDevice_ToC.h"
43 :
44 :
45 : // ===========================================================================
46 : // debug constants
47 : // ===========================================================================
48 : //#define DEBUG_TOC
49 : //#define DEBUG_DYNAMIC_TOC
50 :
51 : // ===========================================================================
52 : // parameter defaults
53 : // ===========================================================================
54 :
55 : // default value for the average response time, that a driver needs to take back control
56 : #define DEFAULT_RESPONSE_TIME -1.0
57 : // default value for the average rate at which the driver's awareness recovers to
58 : // 1.0 after a ToC has been performed
59 : #define DEFAULT_RECOVERY_RATE 0.1
60 : // Default value of the awareness below which no lane-changes are performed
61 : #define DEFAULT_LCABSTINENCE 0.0
62 : // The default value for the average awareness a driver has initially after a ToC
63 : #define DEFAULT_INITIAL_AWARENESS 0.5
64 : // The default value for the deceleration rate applied during a 'minimum risk maneuver'
65 : #define DEFAULT_MRM_DECEL 1.5
66 : // The default value for the dynamic ToC threshold indicates that the dynamic ToCs are deactivated
67 : #define DEFAULT_DYNAMIC_TOC_THRESHOLD 0.0
68 : // The default value for the probability of an MRM to occur after a dynamically triggered ToC
69 : // (Note that these MRMs will not induce full stops in most cases)
70 : #define DEFAULT_MRM_PROBABILITY 0.05
71 :
72 : // The factor by which the dynamic ToC threshold time is multiplied to yield the lead time given for the corresponding ToC
73 : #define DYNAMIC_TOC_LEADTIME_FACTOR 0.75
74 : // A factor applied to the check for the dynamic ToC condition to resist aborting an ongoing dynamic ToC (and prevent oscillations)
75 : #define DYNAMIC_TOC_ABORT_RESISTANCE_FACTOR 2.0
76 :
77 :
78 : // The default values for the openGap parameters applied for gap creation in preparation for a ToC
79 : #define DEFAULT_OPENGAP_TIMEGAP -1.0
80 : #define DEFAULT_OPENGAP_SPACING 0.0
81 : #define DEFAULT_OPENGAP_CHANGERATE 1.0
82 : #define DEFAULT_OPENGAP_MAXDECEL 1.0
83 :
84 :
85 : #define DEFAULT_MANUAL_TYPE ""
86 : #define DEFAULT_AUTOMATED_TYPE ""
87 :
88 : // Maximal tries to sample a positive value from the gaussian distribution
89 : // used for the driver response time when a TOR is issued. (the distribution is assumed truncated at zero)
90 : #define MAX_RESPONSETIME_SAMPLE_TRIES 100
91 : // Maximal variance of responsetimes (returned for pMRM outside lookup table, i.e. pMRM>0.5), see interpolateVariance()
92 : #define MAX_RESPONSETIME_VARIANCE 10000
93 :
94 :
95 : // ---------------------------------------------------------------------------
96 : // static members
97 : // ---------------------------------------------------------------------------
98 : std::set<MSDevice_ToC*, ComparatorNumericalIdLess> MSDevice_ToC::myInstances = std::set<MSDevice_ToC*, ComparatorNumericalIdLess>();
99 : std::set<std::string> MSDevice_ToC::createdOutputFiles;
100 : int MSDevice_ToC::LCModeMRM = 768; // = 0b001100000000 - no autonomous changes, no speed adaptation
101 : SumoRNG MSDevice_ToC::myResponseTimeRNG("toc");
102 :
103 :
104 : // ===========================================================================
105 : // method definitions
106 : // ===========================================================================
107 : // ---------------------------------------------------------------------------
108 : // static initialisation methods
109 : // ---------------------------------------------------------------------------
110 : void
111 36322 : MSDevice_ToC::insertOptions(OptionsCont& oc) {
112 36322 : oc.addOptionSubTopic("ToC Device");
113 72644 : insertDefaultAssignmentOptions("toc", "ToC Device", oc);
114 :
115 72644 : oc.doRegister("device.toc.manualType", new Option_String());
116 72644 : oc.addDescription("device.toc.manualType", "ToC Device", TL("Vehicle type for manual driving regime."));
117 72644 : oc.doRegister("device.toc.automatedType", new Option_String());
118 72644 : oc.addDescription("device.toc.automatedType", "ToC Device", TL("Vehicle type for automated driving regime."));
119 36322 : oc.doRegister("device.toc.responseTime", new Option_Float(DEFAULT_RESPONSE_TIME));
120 72644 : oc.addDescription("device.toc.responseTime", "ToC Device", TL("Average response time needed by a driver to take back control."));
121 36322 : oc.doRegister("device.toc.recoveryRate", new Option_Float(DEFAULT_RECOVERY_RATE));
122 72644 : oc.addDescription("device.toc.recoveryRate", "ToC Device", TL("Recovery rate for the driver's awareness after a ToC."));
123 36322 : oc.doRegister("device.toc.lcAbstinence", new Option_Float(DEFAULT_LCABSTINENCE));
124 72644 : oc.addDescription("device.toc.lcAbstinence", "ToC Device", TL("Attention level below which a driver restrains from performing lane changes (value in [0,1])."));
125 36322 : oc.doRegister("device.toc.initialAwareness", new Option_Float(DEFAULT_INITIAL_AWARENESS));
126 72644 : oc.addDescription("device.toc.initialAwareness", "ToC Device", TL("Average awareness a driver has initially after a ToC (value in [0,1])."));
127 36322 : oc.doRegister("device.toc.mrmDecel", new Option_Float(DEFAULT_MRM_DECEL));
128 72644 : oc.addDescription("device.toc.mrmDecel", "ToC Device", TL("Deceleration rate applied during a 'minimum risk maneuver'."));
129 36322 : oc.doRegister("device.toc.dynamicToCThreshold", new Option_Float(DEFAULT_DYNAMIC_TOC_THRESHOLD));
130 72644 : oc.addDescription("device.toc.dynamicToCThreshold", "ToC Device", TL("Time, which the vehicle requires to have ahead to continue in automated mode. The default value of 0 indicates no dynamic triggering of ToCs."));
131 36322 : oc.doRegister("device.toc.dynamicMRMProbability", new Option_Float(DEFAULT_MRM_PROBABILITY));
132 72644 : oc.addDescription("device.toc.dynamicMRMProbability", "ToC Device", TL("Probability that a dynamically triggered TOR is not answered in time."));
133 36322 : oc.doRegister("device.toc.mrmKeepRight", new Option_Bool(false));
134 72644 : oc.addDescription("device.toc.mrmKeepRight", "ToC Device", TL("If true, the vehicle tries to change to the right during an MRM."));
135 72644 : oc.doRegister("device.toc.mrmSafeSpot", new Option_String());
136 72644 : oc.addDescription("device.toc.mrmSafeSpot", "ToC Device", TL("If set, the vehicle tries to reach the given named stopping place during an MRM."));
137 36322 : oc.doRegister("device.toc.mrmSafeSpotDuration", new Option_Float(60.));
138 72644 : oc.addDescription("device.toc.mrmSafeSpotDuration", "ToC Device", TL("Duration the vehicle stays at the safe spot after an MRM."));
139 36322 : oc.doRegister("device.toc.maxPreparationAccel", new Option_Float(0.0));
140 72644 : oc.addDescription("device.toc.maxPreparationAccel", "ToC Device", TL("Maximal acceleration that may be applied during the ToC preparation phase."));
141 36322 : oc.doRegister("device.toc.ogNewTimeHeadway", new Option_Float(-1.0));
142 72644 : oc.addDescription("device.toc.ogNewTimeHeadway", "ToC Device", TL("Timegap for ToC preparation phase."));
143 36322 : oc.doRegister("device.toc.ogNewSpaceHeadway", new Option_Float(-1.0));
144 72644 : oc.addDescription("device.toc.ogNewSpaceHeadway", "ToC Device", TL("Additional spacing for ToC preparation phase."));
145 36322 : oc.doRegister("device.toc.ogMaxDecel", new Option_Float(-1.0));
146 72644 : oc.addDescription("device.toc.ogMaxDecel", "ToC Device", TL("Maximal deceleration applied for establishing increased gap in ToC preparation phase."));
147 36322 : oc.doRegister("device.toc.ogChangeRate", new Option_Float(-1.0));
148 72644 : oc.addDescription("device.toc.ogChangeRate", "ToC Device", TL("Rate of adaptation towards the increased headway during ToC preparation."));
149 36322 : oc.doRegister("device.toc.useColorScheme", new Option_Bool(true));
150 72644 : oc.addDescription("device.toc.useColorScheme", "ToC Device", TL("Whether a coloring scheme shall by applied to indicate the different ToC stages."));
151 72644 : oc.doRegister("device.toc.file", new Option_String());
152 72644 : oc.addDescription("device.toc.file", "ToC Device", TL("Switches on output by specifying an output filename."));
153 36322 : }
154 :
155 :
156 : void
157 4655777 : MSDevice_ToC::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
158 4655777 : OptionsCont& oc = OptionsCont::getOptions();
159 9311554 : if (equippedByDefaultAssignmentOptions(oc, "toc", v, false)) {
160 90 : if (MSGlobals::gUseMesoSim) {
161 0 : WRITE_WARNING(TL("ToC device is not supported by the mesoscopic simulation."));
162 0 : return;
163 : }
164 180 : const std::string manualType = getStringParam(v, oc, "toc.manualType", DEFAULT_MANUAL_TYPE, true);
165 182 : const std::string automatedType = getStringParam(v, oc, "toc.automatedType", DEFAULT_AUTOMATED_TYPE, true);
166 180 : const SUMOTime responseTime = TIME2STEPS(getFloatParam(v, oc, "toc.responseTime", DEFAULT_RESPONSE_TIME, false));
167 86 : const double recoveryRate = getFloatParam(v, oc, "toc.recoveryRate", DEFAULT_RECOVERY_RATE, false);
168 86 : const double lcAbstinence = getFloatParam(v, oc, "toc.lcAbstinence", DEFAULT_LCABSTINENCE, false);
169 86 : const double initialAwareness = getFloatParam(v, oc, "toc.initialAwareness", DEFAULT_INITIAL_AWARENESS, false);
170 86 : const double mrmDecel = getFloatParam(v, oc, "toc.mrmDecel", DEFAULT_MRM_DECEL, false);
171 176 : const bool useColoring = getBoolParam(v, oc, "toc.useColorScheme", true, false);
172 86 : const std::string deviceID = "toc_" + v.getID();
173 86 : const std::string file = getOutputFilename(v, oc);
174 86 : const OpenGapParams ogp = getOpenGapParams(v, oc);
175 86 : const double dynamicToCThreshold = getFloatParam(v, oc, "toc.dynamicToCThreshold", DEFAULT_DYNAMIC_TOC_THRESHOLD, false);
176 86 : const double dynamicMRMProbability = getDynamicMRMProbability(v, oc);
177 86 : const bool mrmKeepRight = getBoolParam(v, oc, "toc.mrmKeepRight", false, false);
178 176 : const std::string mrmSafeSpot = getStringParam(v, oc, "toc.mrmSafeSpot", "", false);
179 172 : const SUMOTime mrmSafeSpotDuration = TIME2STEPS(getFloatParam(v, oc, "toc.mrmSafeSpotDuration", 60., false));
180 86 : const double maxPreparationAccel = getFloatParam(v, oc, "toc.maxPreparationAccel", 0.0, false);
181 : // build the device
182 : MSDevice_ToC* device = new MSDevice_ToC(v, deviceID, file,
183 : manualType, automatedType, responseTime, recoveryRate,
184 : lcAbstinence, initialAwareness, mrmDecel, dynamicToCThreshold,
185 : dynamicMRMProbability, maxPreparationAccel, mrmKeepRight,
186 86 : mrmSafeSpot, mrmSafeSpotDuration, useColoring, ogp);
187 86 : into.push_back(device);
188 : }
189 : }
190 :
191 :
192 : std::string
193 86 : MSDevice_ToC::getOutputFilename(const SUMOVehicle& v, const OptionsCont& oc) {
194 : // Default of "" means no output
195 86 : std::string file = "";
196 172 : if (v.getParameter().hasParameter("device.toc.file")) {
197 : try {
198 198 : file = v.getParameter().getParameter("device.toc.file", file);
199 0 : } catch (...) {
200 0 : WRITE_WARNINGF(TL("Invalid value '%' for vehicle parameter 'ssm.measures'"), v.getParameter().getParameter("device.toc.file", file));
201 0 : }
202 40 : } else if (v.getVehicleType().getParameter().hasParameter("device.toc.file")) {
203 : try {
204 0 : file = v.getVehicleType().getParameter().getParameter("device.toc.file", file);
205 0 : } catch (...) {
206 0 : WRITE_WARNINGF(TL("Invalid value '%' for vType parameter 'ssm.measures'"), v.getVehicleType().getParameter().getParameter("device.toc.file", file));
207 0 : }
208 : } else {
209 80 : file = oc.getString("device.toc.file") == "" ? file : oc.getString("device.toc.file");
210 : }
211 86 : return file;
212 : }
213 :
214 :
215 : double
216 86 : MSDevice_ToC::getDynamicMRMProbability(const SUMOVehicle& v, const OptionsCont& oc) {
217 86 : double pMRM = getFloatParam(v, oc, "toc.dynamicMRMProbability", DEFAULT_MRM_PROBABILITY, false);
218 86 : if (pMRM < 0 || pMRM > 0.5) {
219 2 : const double pMRMTrunc = MAX2(0.0, MIN2(0.5, pMRM));
220 4 : WRITE_WARNINGF(TL("Given value for ToC device parameter 'dynamicMRMProbability' (=%) is not in the admissible range [0,0.5]. Truncated to %."), toString(pMRM), toString(pMRMTrunc));
221 2 : return pMRMTrunc;
222 : }
223 : return pMRM;
224 : }
225 :
226 :
227 : MSDevice_ToC::OpenGapParams
228 86 : MSDevice_ToC::getOpenGapParams(const SUMOVehicle& v, const OptionsCont& oc) {
229 86 : double timegap = getFloatParam(v, oc, "toc.ogNewTimeHeadway", -1.0, false);
230 86 : double spacing = getFloatParam(v, oc, "toc.ogNewSpaceHeadway", -1.0, false);
231 86 : double changeRate = getFloatParam(v, oc, "toc.ogChangeRate", -1.0, false);
232 86 : double maxDecel = getFloatParam(v, oc, "toc.ogMaxDecel", -1.0, false);
233 : bool specifiedAny = false;
234 :
235 86 : if (changeRate == -1.0) {
236 : changeRate = DEFAULT_OPENGAP_CHANGERATE;
237 : } else {
238 : specifiedAny = true;
239 : }
240 86 : if (maxDecel == -1.0) {
241 : maxDecel = DEFAULT_OPENGAP_MAXDECEL;
242 : } else {
243 : specifiedAny = true;
244 : }
245 86 : if (specifiedAny && timegap == -1 && spacing == -1) {
246 0 : WRITE_ERROR(TL("If any openGap parameters for the ToC model are specified, then at least one of toc.ogNewTimeHeadway and toc.ogNewSpaceHeadway must be defined."))
247 : }
248 86 : if (timegap == -1) {
249 : timegap = DEFAULT_OPENGAP_TIMEGAP;
250 : } else {
251 : specifiedAny = true;
252 : }
253 86 : if (spacing == -1) {
254 : spacing = DEFAULT_OPENGAP_SPACING;
255 : } else {
256 : specifiedAny = true;
257 : }
258 : #ifdef DEBUG_TOC
259 : std::cout << "Parsed openGapParams: \n"
260 : << " timegap=" << timegap
261 : << ", spacing=" << spacing
262 : << ", changeRate=" << changeRate
263 : << ", maxDecel=" << maxDecel
264 : << std::endl;
265 : #endif
266 86 : return OpenGapParams(timegap, spacing, changeRate, maxDecel, specifiedAny);
267 : }
268 :
269 : // ---------------------------------------------------------------------------
270 : // MSDevice_ToC-methods
271 : // ---------------------------------------------------------------------------
272 86 : MSDevice_ToC::MSDevice_ToC(SUMOVehicle& holder, const std::string& id, const std::string& outputFilename,
273 : const std::string& manualType, const std::string& automatedType, SUMOTime responseTime, double recoveryRate,
274 : double lcAbstinence, double initialAwareness, double mrmDecel,
275 : double dynamicToCThreshold, double dynamicMRMProbability, double maxPreparationAccel,
276 86 : bool mrmKeepRight, const std::string& mrmSafeSpot, SUMOTime mrmSafeSpotDuration, bool useColorScheme, OpenGapParams ogp) :
277 : MSVehicleDevice(holder, id),
278 86 : myManualTypeID(manualType),
279 86 : myAutomatedTypeID(automatedType),
280 86 : myResponseTime(responseTime),
281 86 : myRecoveryRate(recoveryRate),
282 86 : myLCAbstinence(lcAbstinence),
283 86 : myInitialAwareness(initialAwareness),
284 86 : myMRMDecel(mrmDecel),
285 86 : myCurrentAwareness(1.),
286 86 : myUseColorScheme(useColorScheme),
287 86 : myTriggerMRMCommand(nullptr),
288 86 : myTriggerToCCommand(nullptr),
289 86 : myRecoverAwarenessCommand(nullptr),
290 86 : myExecuteMRMCommand(nullptr),
291 86 : myPrepareToCCommand(nullptr),
292 86 : myOutputFile(nullptr),
293 : myEvents(),
294 : myEventLanes(),
295 : myEventXY(),
296 86 : myPreviousLCMode(-1),
297 86 : myOpenGapParams(ogp),
298 86 : myDynamicToCThreshold(dynamicToCThreshold),
299 86 : myMRMProbability(dynamicMRMProbability),
300 86 : myDynamicToCActive(dynamicToCThreshold > 0),
301 86 : myIssuedDynamicToC(false),
302 86 : myDynamicToCLane(-1),
303 86 : myMRMKeepRight(mrmKeepRight),
304 86 : myMRMSafeSpot(mrmSafeSpot),
305 86 : myMRMSafeSpotDuration(mrmSafeSpotDuration),
306 86 : myMaxPreparationAccel(maxPreparationAccel),
307 86 : myOriginalMaxAccel(-1) {
308 : // Take care! Holder is currently being constructed. Cast occurs before completion.
309 86 : myHolderMS = static_cast<MSVehicle*>(&holder);
310 :
311 86 : if (outputFilename != "") {
312 70 : myOutputFile = &OutputDevice::getDevice(outputFilename);
313 : // TODO: make xsd, include header
314 : // myOutputFile.writeXMLHeader("ToCDeviceLog", "ToCDeviceLog.xsd");
315 : if (createdOutputFiles.count(outputFilename) == 0) {
316 136 : myOutputFile->writeXMLHeader("ToCDeviceLog", "");
317 : createdOutputFiles.insert(outputFilename);
318 : }
319 : }
320 :
321 : // Check if the given vTypes for the ToC Device are vTypeDistributions
322 86 : MSVehicleControl& vehCtrl = MSNet::getInstance()->getVehicleControl();
323 86 : const bool automatedVTypeIsDist = vehCtrl.hasVTypeDistribution(myAutomatedTypeID);
324 86 : const bool manualVTypeIsDist = vehCtrl.hasVTypeDistribution(myManualTypeID);
325 :
326 : // Check if the vType of the holder matches one of the given vTypes
327 86 : std::string holderVTypeID = holder.getVehicleType().getID();
328 86 : if (holderVTypeID == myManualTypeID) {
329 6 : myState = ToCState::MANUAL;
330 80 : } else if (holderVTypeID == myAutomatedTypeID) {
331 76 : myState = ToCState::AUTOMATED;
332 8 : } else if (manualVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myManualTypeID) > 0) {
333 : // Holder type id is from the given manual type distribution.
334 0 : myState = ToCState::MANUAL;
335 : myManualTypeID = holderVTypeID;
336 6 : } else if (automatedVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myAutomatedTypeID) > 0) {
337 : // Holder type id is from the given automated type distribution.
338 2 : myState = ToCState::AUTOMATED;
339 : myAutomatedTypeID = holderVTypeID;
340 : } else {
341 4 : throw ProcessError("Vehicle type of vehicle '" + holder.getID() + "' ('" +
342 6 : holder.getVehicleType().getID() + "') must coincide with manualType ('" +
343 4 : manualType + "') or automatedType ('" + automatedType +
344 4 : "') specified for its ToC-device (or drawn from the specified vTypeDistributions).");
345 : }
346 84 : if (!vehCtrl.hasVType(myAutomatedTypeID)) {
347 4 : throw ProcessError("The automated vehicle type '" + myAutomatedTypeID +
348 8 : "' of vehicle '" + holder.getID() + "' is not known.");
349 : }
350 82 : if (!vehCtrl.hasVType(myManualTypeID)) {
351 0 : throw ProcessError("The manual vehicle type '" + myManualTypeID +
352 0 : "' of vehicle '" + holder.getID() + "' is not known.");
353 : }
354 :
355 : // Eventually instantiate given vTypes from distributions
356 82 : if (myState == ToCState::MANUAL && automatedVTypeIsDist) {
357 0 : myAutomatedTypeID = vehCtrl.getVType(myAutomatedTypeID, MSRouteHandler::getParsingRNG())->getID();
358 82 : } else if (myState == ToCState::AUTOMATED && manualVTypeIsDist) {
359 2 : myManualTypeID = vehCtrl.getVType(myManualTypeID, MSRouteHandler::getParsingRNG())->getID();
360 : }
361 :
362 : // register at static instance container
363 86 : myInstances.insert(this);
364 82 : initColorScheme();
365 :
366 : #ifdef DEBUG_TOC
367 : std::cout << "initialized device '" << id << "' with "
368 : << "outputFilename=" << outputFilename << ", "
369 : << "myManualType=" << myManualTypeID << ", "
370 : << "myAutomatedType=" << myAutomatedTypeID << ", "
371 : << "myResponseTime=" << myResponseTime << ", "
372 : << "myRecoveryRate=" << myRecoveryRate << ", "
373 : << "myInitialAwareness=" << myInitialAwareness << ", "
374 : << "myMRMDecel=" << myMRMDecel << ", "
375 : << "ogTimeHeadway=" << myOpenGapParams.newTimeHeadway << ", "
376 : << "ogSpaceHeadway=" << myOpenGapParams.newSpaceHeadway << ", "
377 : << "ogChangeRate=" << myOpenGapParams.changeRate << ", "
378 : << "ogMaxDecel=" << myOpenGapParams.maxDecel << ", "
379 : << "ogActive=" << myOpenGapParams.active << ", "
380 : << "myCurrentAwareness=" << myCurrentAwareness << ", "
381 : << "myState=" << _2string(myState) << std::endl;
382 : #endif
383 :
384 : assert(myInitialAwareness <= 1.0 && myInitialAwareness >= 0.0);
385 86 : }
386 :
387 :
388 :
389 : void
390 82 : MSDevice_ToC::initColorScheme() {
391 : //RGBColor(red, green, blue)
392 82 : myColorScheme[MANUAL] = MSNet::getInstance()->getVehicleControl().getVType(myManualTypeID)->getColor();
393 82 : myColorScheme[AUTOMATED] = MSNet::getInstance()->getVehicleControl().getVType(myAutomatedTypeID)->getColor();
394 82 : myColorScheme[PREPARING_TOC] = RGBColor(200, 200, 250); // light blue
395 82 : myColorScheme[MRM] = RGBColor(250, 50, 50); // red
396 82 : myColorScheme[RECOVERING] = RGBColor(250, 210, 150); // light yellow
397 82 : myColorScheme[UNDEFINED] = RGBColor(150, 150, 150); // gray
398 82 : }
399 :
400 :
401 164 : MSDevice_ToC::~MSDevice_ToC() {
402 : // unregister from static instance container
403 82 : myInstances.erase(this);
404 : // deschedule commands associated to this device
405 82 : if (myTriggerMRMCommand != nullptr) {
406 : myTriggerMRMCommand->deschedule();
407 : }
408 82 : if (myTriggerToCCommand != nullptr) {
409 : myTriggerToCCommand->deschedule();
410 : }
411 82 : if (myRecoverAwarenessCommand != nullptr) {
412 : myRecoverAwarenessCommand->deschedule();
413 : }
414 82 : if (myExecuteMRMCommand != nullptr) {
415 : myExecuteMRMCommand->deschedule();
416 4 : resetDeliberateLCs();
417 : }
418 82 : if (myPrepareToCCommand != nullptr) {
419 : myPrepareToCCommand->deschedule();
420 : }
421 164 : }
422 :
423 : void
424 1002 : MSDevice_ToC::setAwareness(double value) {
425 1002 : if (value > 1.0 || value < 0.0) {
426 0 : std::stringstream ss;
427 0 : ss << "Truncating invalid value for awareness (" << value << ") to lie in [0,1].";
428 0 : WRITE_WARNING(ss.str());
429 : value = MAX2(0.0, MIN2(1.0, value));
430 0 : }
431 1002 : if (myCurrentAwareness >= myLCAbstinence && value < myLCAbstinence) {
432 : // Awareness is now below LC abstinence level -> prevent deliberate LCs
433 8 : deactivateDeliberateLCs();
434 994 : } else if (myCurrentAwareness < myLCAbstinence && value >= myLCAbstinence) {
435 : // Awareness is now above LC abstinence level -> allow deliberate LCs
436 8 : resetDeliberateLCs();
437 : }
438 1002 : myCurrentAwareness = value;
439 1002 : myHolderMS->getDriverState()->setAwareness(value);
440 1002 : }
441 :
442 :
443 : void
444 510 : MSDevice_ToC::setState(ToCState state) {
445 : #ifdef DEBUG_TOC
446 : std::cout << SIMTIME << " MSDevice_ToC::setState()" << std::endl;
447 : #endif
448 510 : if (myState == state) {
449 : // No state change
450 : return;
451 : }
452 :
453 510 : if (myState == MRM) {
454 : // reset the vehicle's maxAccel
455 70 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(myOriginalMaxAccel);
456 70 : resetDeliberateLCs();
457 440 : } else if (myState == PREPARING_TOC) {
458 152 : if (myOpenGapParams.active) {
459 : // Deactivate gap control at preparation phase end
460 4 : myHolderMS->getInfluencer().deactivateGapController();
461 : }
462 152 : if (state != MRM) {
463 : // Aborting preparation
464 90 : resetDeliberateLCs();
465 90 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(myOriginalMaxAccel);
466 : }
467 288 : } else if (state == PREPARING_TOC || state == MRM) {
468 : #ifdef DEBUG_TOC
469 : std::cout << " Entering ToC preparation... " << std::endl;
470 : #endif
471 : // Prevent lane changing during takeover preparation
472 164 : deactivateDeliberateLCs();
473 : // Store original value of maxAccel for restoring it after preparation phase
474 164 : myOriginalMaxAccel = myHolderMS->getCarFollowModel().getMaxAccel();
475 : // Impose acceleration limit during preparation
476 164 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(MIN2(myMaxPreparationAccel, myOriginalMaxAccel));
477 : }
478 :
479 510 : if (myIssuedDynamicToC) {
480 : // Reset dynamic ToC flag
481 6 : myIssuedDynamicToC = false;
482 : }
483 :
484 510 : myState = state;
485 510 : if (myUseColorScheme) {
486 510 : setVehicleColor();
487 : }
488 : }
489 :
490 : void
491 510 : MSDevice_ToC::setVehicleColor() {
492 510 : const SUMOVehicleParameter& p = myHolder.getParameter();
493 510 : p.color = myColorScheme[myState];
494 510 : p.parametersSet |= VEHPARS_COLOR_SET;
495 510 : }
496 :
497 : void
498 16 : MSDevice_ToC::requestMRM() {
499 : // Remove any preparatory process
500 16 : descheduleToCPreparation();
501 : // .. and any recovery process
502 16 : descheduleRecovery();
503 : // ... and any pending ToC to manual
504 16 : descheduleToC();
505 : // Immediately trigger the MRM process
506 16 : triggerMRM(0);
507 16 : }
508 :
509 :
510 : void
511 246 : MSDevice_ToC::requestToC(SUMOTime timeTillMRM, SUMOTime responseTime) {
512 : #ifdef DEBUG_TOC
513 : std::cout << SIMTIME << " requestToC() for vehicle '" << myHolder.getID() << "', timeTillMRM=" << timeTillMRM << ", responseTime=" << responseTime << std::endl;
514 : #endif
515 246 : if (myState == AUTOMATED) {
516 : // Initialize preparation phase
517 152 : if (responseTime == -1000) {
518 : // Sample response time from distribution
519 8 : const double sample = sampleResponseTime(STEPS2TIME(timeTillMRM));
520 : // this needs to be a separate line because TIME2STEPS may otherwise do two calls to sampleResponseTime
521 8 : responseTime = TIME2STEPS(sample);
522 : }
523 :
524 : // Schedule ToC Event
525 152 : myTriggerToCCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::triggerDownwardToC);
526 152 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myTriggerToCCommand, SIMSTEP + responseTime);
527 :
528 : assert(myExecuteMRMCommand == nullptr);
529 : assert(myTriggerMRMCommand == nullptr);
530 152 : if (responseTime > timeTillMRM && myState != MRM) {
531 : // Schedule new MRM if driver response time is higher than permitted
532 102 : myTriggerMRMCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::triggerMRM);
533 102 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myTriggerMRMCommand, SIMSTEP + timeTillMRM);
534 : }
535 :
536 : // Start ToC preparation process
537 152 : myPrepareToCCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::ToCPreparationStep);
538 152 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myPrepareToCCommand, SIMSTEP + DELTA_T);
539 152 : setState(PREPARING_TOC);
540 152 : if (myOpenGapParams.active) {
541 : // Start gap controller
542 4 : double originalTau = myHolderMS->getCarFollowModel().getHeadwayTime();
543 4 : myHolderMS->getInfluencer().activateGapController(originalTau,
544 : myOpenGapParams.newTimeHeadway, myOpenGapParams.newSpaceHeadway, -1,
545 : myOpenGapParams.changeRate, myOpenGapParams.maxDecel);
546 : }
547 : // Record event
548 152 : if (generatesOutput()) {
549 150 : myEvents.push(std::make_pair(SIMSTEP, "TOR"));
550 150 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
551 150 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
552 : }
553 : } else {
554 : // Switch to automated mode is performed immediately
555 94 : if (timeTillMRM > 0) {
556 76 : std::stringstream ss;
557 228 : ss << "[t=" << SIMTIME << "] Positive transition time (" << STEPS2TIME(timeTillMRM) << "s.) for upward ToC of vehicle '" << myHolder.getID() << "' is ignored.";
558 76 : WRITE_WARNING(ss.str());
559 76 : }
560 94 : triggerUpwardToC(SIMSTEP + DELTA_T);
561 : }
562 246 : }
563 :
564 :
565 : SUMOTime
566 74 : MSDevice_ToC::triggerMRM(SUMOTime /* t */) {
567 : #ifdef DEBUG_TOC
568 : std::cout << SIMTIME << " triggerMRM() for vehicle '" << myHolder.getID() << "'" << std::endl;
569 : #endif
570 : // Clear ongoing MRM
571 74 : descheduleMRM();
572 :
573 : // Start MRM process
574 74 : if (myMRMSafeSpot != "") {
575 0 : SUMOVehicleParameter::Stop stop;
576 0 : MSStoppingPlace* s = MSNet::getInstance()->getStoppingPlace(myMRMSafeSpot, SUMO_TAG_PARKING_AREA);
577 0 : if (s == nullptr) {
578 0 : WRITE_WARNINGF(TL("Ignoring unknown safe spot '%' for vehicle '%'."), myMRMSafeSpot, myHolder.getID());
579 : } else {
580 : stop.parkingarea = myMRMSafeSpot;
581 0 : stop.parking = ParkingType::OFFROAD;
582 0 : stop.lane = s->getLane().getID();
583 0 : stop.endPos = s->getEndLanePosition();
584 0 : stop.startPos = s->getBeginLanePosition();
585 0 : stop.duration = myMRMSafeSpotDuration;
586 0 : myHolderMS->getSingularType().setDecel(myMRMDecel);
587 : std::string error;
588 0 : if (!myHolder.addStop(stop, error)) {
589 0 : WRITE_WARNING("Could not set safe spot '" + myMRMSafeSpot + "' for vehicle '" + myHolder.getID() + "'. " + error);
590 : }
591 : }
592 0 : } else {
593 74 : myExecuteMRMCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::MRMExecutionStep);
594 74 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myExecuteMRMCommand, SIMSTEP + DELTA_T);
595 : }
596 74 : if (myState == MANUAL || myState == RECOVERING) {
597 8 : switchHolderType(myAutomatedTypeID);
598 : }
599 74 : setState(MRM);
600 74 : setAwareness(1.);
601 :
602 : // Record event
603 74 : if (generatesOutput()) {
604 72 : myEvents.push(std::make_pair(SIMSTEP, "MRM"));
605 72 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
606 72 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
607 : }
608 :
609 74 : return 0;
610 : }
611 :
612 :
613 : SUMOTime
614 96 : MSDevice_ToC::triggerUpwardToC(SUMOTime /* t */) {
615 : #ifdef DEBUG_TOC
616 : std::cout << SIMTIME << " triggerUpwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
617 : #endif
618 96 : descheduleToC();
619 : // Eventually stop ToC preparation process
620 96 : descheduleToCPreparation();
621 : // Eventually abort MRM
622 96 : descheduleMRM();
623 : // Eventually abort awareness recovery process
624 96 : descheduleRecovery();
625 :
626 96 : if (myState == MANUAL || myState == RECOVERING) {
627 34 : switchHolderType(myAutomatedTypeID);
628 : }
629 96 : setAwareness(1.);
630 96 : setState(AUTOMATED);
631 :
632 : // Record event
633 96 : if (generatesOutput()) {
634 94 : myEvents.push(std::make_pair(SIMSTEP, "ToCup"));
635 94 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
636 94 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
637 : }
638 :
639 96 : return 0;
640 : }
641 :
642 :
643 : SUMOTime
644 98 : MSDevice_ToC::triggerDownwardToC(SUMOTime /* t */) {
645 : #ifdef DEBUG_TOC
646 : std::cout << SIMTIME << " triggerDownwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
647 : #endif
648 98 : descheduleToC();
649 : // Eventually stop ToC preparation process
650 98 : descheduleToCPreparation();
651 : // Eventually abort MRM
652 98 : descheduleMRM();
653 :
654 : #ifdef DEBUG_TOC
655 : std::cout << SIMTIME << " Initial awareness after ToC: " << myCurrentAwareness << std::endl;
656 : #endif
657 :
658 : // Start awareness recovery process
659 98 : myRecoverAwarenessCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::awarenessRecoveryStep);
660 98 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myRecoverAwarenessCommand, SIMSTEP + DELTA_T);
661 98 : setState(RECOVERING);
662 :
663 : // @todo: Sample initial awareness
664 98 : double initialAwareness = myInitialAwareness;
665 98 : setAwareness(initialAwareness);
666 :
667 98 : switchHolderType(myManualTypeID);
668 :
669 : // Record event
670 98 : if (generatesOutput()) {
671 96 : myEvents.push(std::make_pair(SIMSTEP, "ToCdown"));
672 96 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
673 96 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
674 : }
675 98 : return 0;
676 : }
677 :
678 : void
679 268 : MSDevice_ToC::descheduleMRM() {
680 : // Eventually abort scheduled MRM
681 268 : if (myTriggerMRMCommand != nullptr) {
682 : myTriggerMRMCommand->deschedule();
683 102 : myTriggerMRMCommand = nullptr;
684 : }
685 : // Eventually abort ongoing MRM
686 268 : if (myExecuteMRMCommand != nullptr) {
687 : myExecuteMRMCommand->deschedule();
688 70 : resetDeliberateLCs();
689 70 : myExecuteMRMCommand = nullptr;
690 : }
691 268 : }
692 :
693 :
694 : void
695 210 : MSDevice_ToC::descheduleToC() {
696 210 : if (myTriggerToCCommand != nullptr) {
697 : myTriggerToCCommand->deschedule();
698 152 : myTriggerToCCommand = nullptr;
699 : }
700 210 : }
701 :
702 : void
703 268 : MSDevice_ToC::descheduleToCPreparation() {
704 : // Eventually stop ToC preparation process
705 268 : if (myPrepareToCCommand != nullptr) {
706 : myPrepareToCCommand->deschedule();
707 152 : if (myState != MRM) {
708 94 : resetDeliberateLCs();
709 : }
710 152 : myPrepareToCCommand = nullptr;
711 : }
712 268 : }
713 :
714 : void
715 112 : MSDevice_ToC::descheduleRecovery() {
716 : // Eventually stop ToC preparation process
717 112 : if (myRecoverAwarenessCommand != nullptr) {
718 : myRecoverAwarenessCommand->deschedule();
719 8 : myRecoverAwarenessCommand = nullptr;
720 : }
721 112 : }
722 :
723 :
724 : void
725 140 : MSDevice_ToC::switchHolderType(const std::string& targetTypeID) {
726 : #ifdef DEBUG_TOC
727 : std::cout << SIMTIME << " Switching type of vehicle '" << myHolder.getID() << "' to '" << targetTypeID << "'" << std::endl;
728 : #endif
729 140 : MSVehicleType* targetType = MSNet::getInstance()->getVehicleControl().getVType(targetTypeID);
730 140 : if (targetType == nullptr) {
731 0 : WRITE_ERRORF(TL("vType '%' for vehicle '%' is not known."), targetType->getID(), myHolder.getID());
732 0 : return;
733 : }
734 140 : myHolderMS->replaceVehicleType(targetType);
735 : }
736 :
737 :
738 : SUMOTime
739 1588 : MSDevice_ToC::ToCPreparationStep(SUMOTime /* t */) {
740 : #ifdef DEBUG_TOC
741 : std::cout << SIMTIME << " ToC preparation step for vehicle '" << myHolder.getID() << "'" << std::endl;
742 : #endif
743 1588 : if (myState == PREPARING_TOC) {
744 1530 : return DELTA_T;
745 : } else {
746 : #ifdef DEBUG_TOC
747 : std::cout << SIMTIME << " Aborting ToC preparation for vehicle '" << myHolder.getID() << "'" << std::endl;
748 : #endif
749 58 : descheduleToCPreparation();
750 58 : return 0;
751 : }
752 : }
753 :
754 :
755 : SUMOTime
756 2426 : MSDevice_ToC::MRMExecutionStep(SUMOTime t) {
757 2426 : deactivateDeliberateLCs();
758 2426 : const double currentSpeed = myHolderMS->getSpeed();
759 : #ifdef DEBUG_TOC
760 : std::cout << SIMTIME << " MRM step for vehicle '" << myHolder.getID() << "', currentSpeed=" << currentSpeed << std::endl;
761 : #endif
762 :
763 : // Induce slowdown with MRMDecel
764 : std::vector<std::pair<SUMOTime, double> > speedTimeLine;
765 2426 : const double nextSpeed = MAX2(0., currentSpeed - ACCEL2SPEED(myMRMDecel));
766 2426 : speedTimeLine.push_back(std::make_pair(t - DELTA_T, currentSpeed));
767 2426 : speedTimeLine.push_back(std::make_pair(t, nextSpeed));
768 2426 : myHolderMS->getInfluencer().setSpeedTimeLine(speedTimeLine);
769 :
770 2426 : if (myMRMKeepRight) {
771 : // Try to change to the right
772 : std::vector<std::pair<SUMOTime, int> > laneTimeLine;
773 68 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), 0));
774 68 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + 1, 0));
775 68 : myHolderMS->getInfluencer().setLaneTimeLine(laneTimeLine);
776 : // std::cout << "Keeping right..." << std::endl;
777 : }
778 :
779 2426 : if (myState == MRM) {
780 2426 : return DELTA_T;
781 : } else {
782 : #ifdef DEBUG_TOC
783 : std::cout << SIMTIME << " Aborting MRM for vehicle '" << myHolder.getID() << "'" << std::endl;
784 : #endif
785 0 : resetDeliberateLCs();
786 : return 0;
787 : }
788 : }
789 :
790 :
791 : SUMOTime
792 734 : MSDevice_ToC::awarenessRecoveryStep(SUMOTime /* t */) {
793 : #ifdef DEBUG_TOC
794 : std::cout << SIMTIME << " Awareness recovery step for vehicle '" << myHolder.getID() << "'" << std::endl;
795 : #endif
796 : // Proceed with awareness recovery
797 734 : if (myCurrentAwareness < 1.0) {
798 1378 : setAwareness(MIN2(1.0, myCurrentAwareness + TS * myRecoveryRate));
799 : }
800 :
801 : #ifdef DEBUG_TOC
802 : std::cout << SIMTIME << " currentAwareness = " << myCurrentAwareness << std::endl;
803 : #endif
804 :
805 734 : const bool awarenessRecoveryCompleted = myCurrentAwareness == 1.0;
806 734 : if (awarenessRecoveryCompleted) {
807 : #ifdef DEBUG_TOC
808 : std::cout << SIMTIME << " Awareness recovery completed for veh '" << myHolder.getID() << "'" << std::endl;
809 : #endif
810 90 : myRecoverAwarenessCommand->deschedule();
811 90 : myRecoverAwarenessCommand = nullptr;
812 90 : setState(MANUAL);
813 90 : return 0;
814 : }
815 644 : return DELTA_T;
816 : }
817 :
818 : bool
819 31262 : MSDevice_ToC::notifyMove(SUMOTrafficObject& /*veh*/,
820 : double /*oldPos*/,
821 : double /*newPos*/,
822 : double /*newSpeed*/) {
823 31262 : if (myState == AUTOMATED && checkDynamicToC()) {
824 : // Initiate a ToC
825 : // Record event
826 6 : if (generatesOutput()) {
827 6 : myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
828 6 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
829 6 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
830 : }
831 : // Leadtime for dynamic ToC is proportional to the time assumed for the dynamic ToC threshold
832 6 : const double leadTime = myDynamicToCThreshold * 1000 * DYNAMIC_TOC_LEADTIME_FACTOR;
833 6 : requestToC((SUMOTime) leadTime);
834 : // TODO: Alter the response time according to the given lead time. Consider re-sampling it at each call of requestToC(). (Conditional to whether a non-negative response time was given in the configuration)
835 6 : myIssuedDynamicToC = true;
836 6 : myDynamicToCLane = myHolderMS->getLane()->getNumericalID();
837 31256 : } else if (myIssuedDynamicToC && myState == PREPARING_TOC && !checkDynamicToC()) {
838 : // Abort dynamic ToC, FIXME: This could abort an externally requested ToC in rare occasions... (needs test)
839 : // Record event
840 2 : if (generatesOutput()) {
841 2 : myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
842 2 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
843 2 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
844 : }
845 : // NOTE: This should not occur if lane changing is prevented during ToC preparation...
846 : // TODO: Reset response time to the original value (unnecessary if re-sampling for each call to requestToC)
847 2 : triggerUpwardToC(0);
848 : }
849 31262 : return true;
850 : }
851 :
852 : std::string
853 87894 : MSDevice_ToC::getParameter(const std::string& key) const {
854 87894 : if (key == "manualType") {
855 : return myManualTypeID;
856 84334 : } else if (key == "automatedType") {
857 : return myAutomatedTypeID;
858 80774 : } else if (key == "responseTime") {
859 3560 : return toString(STEPS2TIME(myResponseTime));
860 77214 : } else if (key == "recoveryRate") {
861 3560 : return toString(myRecoveryRate);
862 73654 : } else if (key == "initialAwareness") {
863 3560 : return toString(myInitialAwareness);
864 70094 : } else if (key == "mrmDecel") {
865 3560 : return toString(myMRMDecel);
866 66534 : } else if (key == "currentAwareness") {
867 30978 : return toString(myCurrentAwareness);
868 35556 : } else if (key == "lcAbstinence") {
869 20 : return toString(myLCAbstinence);
870 35536 : } else if (key == "state") {
871 31478 : return _2string(myState);
872 4058 : } else if (key == "holder") {
873 3560 : return myHolder.getID();
874 498 : } else if (key == "hasDynamicToC") {
875 0 : return toString(myDynamicToCActive);
876 498 : } else if (key == "dynamicToCThreshold") {
877 428 : return toString(myDynamicToCThreshold);
878 70 : } else if (key == "dynamicMRMProbability") {
879 20 : return toString(myMRMProbability);
880 50 : } else if (key == "mrmKeepRight") {
881 20 : return toString(myMRMKeepRight);
882 30 : } else if (key == "mrmSafeSpot") {
883 : return myMRMSafeSpot;
884 30 : } else if (key == "mrmSafeSpotDuration") {
885 0 : return toString(STEPS2TIME(myMRMSafeSpotDuration));
886 30 : } else if (key == "maxPreparationAccel") {
887 20 : return toString(myMaxPreparationAccel);
888 10 : } else if (key == "ogNewTimeHeadway") {
889 2 : return toString(myOpenGapParams.newTimeHeadway);
890 8 : } else if (key == "ogNewSpaceHeadway") {
891 4 : return toString(myOpenGapParams.newSpaceHeadway);
892 4 : } else if (key == "ogChangeRate") {
893 2 : return toString(myOpenGapParams.changeRate);
894 2 : } else if (key == "ogMaxDecel") {
895 2 : return toString(myOpenGapParams.maxDecel);
896 : }
897 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
898 : }
899 :
900 :
901 : void
902 264 : MSDevice_ToC::setParameter(const std::string& key, const std::string& value) {
903 : #ifdef DEBUG_TOC
904 : std::cout << SIMTIME << " MSDevice_ToC::setParameter(key=" << key << ", value=" << value << ")" << std::endl;
905 : #endif
906 264 : if (key == "manualType") {
907 0 : myManualTypeID = value;
908 0 : myColorScheme[MANUAL] = MSNet::getInstance()->getVehicleControl().getVType(myManualTypeID)->getColor();
909 0 : if (myState == MANUAL) {
910 0 : switchHolderType(value);
911 : }
912 264 : } else if (key == "automatedType") {
913 0 : myAutomatedTypeID = value;
914 0 : myColorScheme[AUTOMATED] = MSNet::getInstance()->getVehicleControl().getVType(myAutomatedTypeID)->getColor();
915 0 : if (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM) {
916 0 : switchHolderType(value);
917 : }
918 264 : } else if (key == "responseTime") {
919 0 : myResponseTime = TIME2STEPS(StringUtils::toDouble(value));
920 264 : } else if (key == "recoveryRate") {
921 0 : myRecoveryRate = StringUtils::toDouble(value);
922 264 : } else if (key == "initialAwareness") {
923 0 : myInitialAwareness = StringUtils::toDouble(value);
924 264 : } else if (key == "lcAbstinence") {
925 0 : myLCAbstinence = StringUtils::toDouble(value);
926 0 : if (isManuallyDriven()) {
927 0 : setAwareness(myCurrentAwareness); // to eventually trigger LC-prevention
928 : }
929 264 : } else if (key == "currentAwareness") {
930 0 : if (isManuallyDriven()) {
931 0 : setAwareness(StringUtils::toDouble(value));
932 : } else {
933 0 : WRITE_WARNING(TL("Setting device.toc.currentAwareness during automated mode has no effect."))
934 : }
935 264 : } else if (key == "mrmDecel") {
936 0 : myMRMDecel = StringUtils::toDouble(value);
937 264 : } else if (key == "requestToC") {
938 : // setting this magic parameter gives the interface for inducing a ToC
939 240 : const SUMOTime timeTillMRM = TIME2STEPS(StringUtils::toDouble(value));
940 240 : requestToC(timeTillMRM, myResponseTime);
941 24 : } else if (key == "requestMRM") {
942 : // setting this magic parameter gives the interface for inducing an MRM
943 16 : requestMRM();
944 8 : } else if (key == "awareness") {
945 : // setting this magic parameter gives the interface for setting the driverstate's awareness
946 0 : setAwareness(StringUtils::toDouble(value));
947 8 : } else if (key == "dynamicToCThreshold") {
948 0 : const double newValue = StringUtils::toDouble(value);
949 0 : if (newValue < 0) {
950 0 : WRITE_WARNINGF(TL("Value of dynamicToCThreshold must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
951 0 : } else if (newValue == 0) {
952 0 : myDynamicToCThreshold = newValue;
953 0 : myDynamicToCActive = false;
954 : } else {
955 0 : myDynamicToCThreshold = newValue;
956 0 : myDynamicToCActive = true;
957 : }
958 8 : } else if (key == "dynamicMRMProbability") {
959 0 : const double newValue = StringUtils::toDouble(value);
960 0 : if (newValue < 0) {
961 0 : WRITE_WARNINGF(TL("Value of dynamicMRMProbability must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
962 : } else {
963 0 : myMRMProbability = newValue;
964 : }
965 8 : } else if (key == "mrmKeepRight") {
966 0 : const bool newValue = StringUtils::toBool(value);
967 0 : myMRMKeepRight = newValue;
968 8 : } else if (key == "mrmSafeSpot") {
969 0 : myMRMSafeSpot = value;
970 8 : } else if (key == "mrmSafeSpotDuration") {
971 0 : myMRMSafeSpotDuration = TIME2STEPS(StringUtils::toDouble(value));
972 8 : } else if (key == "maxPreparationAccel") {
973 0 : const double newValue = StringUtils::toDouble(value);
974 0 : if (newValue < 0) {
975 0 : WRITE_WARNINGF(TL("Value of maxPreparationAccel must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
976 : } else {
977 0 : myMaxPreparationAccel = newValue;
978 : }
979 8 : } else if (key == "ogNewTimeHeadway") {
980 2 : const double newValue = StringUtils::toDouble(value);
981 2 : myOpenGapParams.newTimeHeadway = newValue;
982 2 : myOpenGapParams.active = true;
983 6 : } else if (key == "ogNewSpaceHeadway") {
984 2 : const double newValue = StringUtils::toDouble(value);
985 2 : myOpenGapParams.newSpaceHeadway = newValue;
986 2 : myOpenGapParams.active = true;
987 4 : } else if (key == "ogChangeRate") {
988 2 : const double newValue = StringUtils::toDouble(value);
989 2 : myOpenGapParams.changeRate = newValue;
990 2 : myOpenGapParams.active = true;
991 2 : } else if (key == "ogMaxDecel") {
992 2 : const double newValue = StringUtils::toDouble(value);
993 2 : myOpenGapParams.maxDecel = newValue;
994 2 : myOpenGapParams.active = true;
995 : } else {
996 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
997 : }
998 264 : }
999 :
1000 :
1001 : MSDevice_ToC::ToCState
1002 0 : MSDevice_ToC::_2ToCState(const std::string& str) {
1003 0 : if (str == "UNDEFINED") {
1004 : return UNDEFINED;
1005 0 : } else if (str == "MANUAL") {
1006 : return MANUAL;
1007 0 : } else if (str == "AUTOMATED") {
1008 : return AUTOMATED;
1009 0 : } else if (str == "PREPARING_TOC") {
1010 : return PREPARING_TOC;
1011 0 : } else if (str == "MRM") {
1012 : return MRM;
1013 0 : } else if (str == "RECOVERING") {
1014 : return RECOVERING;
1015 : } else {
1016 0 : WRITE_WARNINGF(TL("Unknown ToCState '%'"), str);
1017 0 : return UNDEFINED;
1018 : }
1019 : }
1020 :
1021 :
1022 : std::string
1023 31478 : MSDevice_ToC::_2string(ToCState state) {
1024 31478 : if (state == UNDEFINED) {
1025 0 : return "UNDEFINED";
1026 : } else if (state == MANUAL) {
1027 17704 : return "MANUAL";
1028 : } else if (state == AUTOMATED) {
1029 8740 : return "AUTOMATED";
1030 : } else if (state == PREPARING_TOC) {
1031 1762 : return "PREPARING_TOC";
1032 : } else if (state == MRM) {
1033 2508 : return "MRM";
1034 : } else if (state == RECOVERING) {
1035 764 : return "RECOVERING";
1036 : } else {
1037 0 : WRITE_WARNINGF(TL("Unknown ToCState '%'"), toString(state));
1038 0 : return toString(state);
1039 : }
1040 : }
1041 :
1042 :
1043 : void
1044 30914 : MSDevice_ToC::writeOutput() {
1045 30914 : if (!generatesOutput()) {
1046 : assert(myEvents.empty());
1047 : return;
1048 : }
1049 31328 : while (!myEvents.empty()) {
1050 : const std::pair<SUMOTime, std::string> e = myEvents.front(); // make a copy, it is used after pop
1051 : const std::pair<std::string, double>& l = myEventLanes.front();
1052 : const std::pair<double, double>& p = myEventXY.front();
1053 414 : myOutputFile->openTag(e.second);
1054 1242 : myOutputFile->writeAttr("id", myHolder.getID()).writeAttr("t", STEPS2TIME(e.first));
1055 1242 : myOutputFile->writeAttr("lane", l.first).writeAttr("lanePos", l.second);
1056 1242 : myOutputFile->writeAttr("x", p.first).writeAttr("y", p.second);
1057 828 : myOutputFile->closeTag();
1058 : myEvents.pop();
1059 : myEventLanes.pop();
1060 : myEventXY.pop();
1061 :
1062 414 : if (e.second.compare("DYNTOR") == 0 && !myEvents.empty()) { // skip "TOR" events if duplicate of "DYNTOR"
1063 : std::pair<SUMOTime, std::string>& eNext = myEvents.front();
1064 8 : if (eNext.second.compare("TOR") == 0 && eNext.first == e.first) {
1065 : myEvents.pop();
1066 : myEventLanes.pop();
1067 : myEventXY.pop();
1068 : }
1069 : }
1070 : }
1071 : }
1072 :
1073 :
1074 : void
1075 35160 : MSDevice_ToC::cleanup() {
1076 : // Close xml bodies for all existing files
1077 : // TODO: Check if required
1078 35226 : for (auto& fn : createdOutputFiles) {
1079 66 : OutputDevice* file = &OutputDevice::getDevice(fn);
1080 132 : file->closeTag();
1081 : }
1082 35160 : }
1083 :
1084 :
1085 : void
1086 336 : MSDevice_ToC::resetDeliberateLCs() {
1087 336 : if (myPreviousLCMode != -1) {
1088 170 : myHolderMS->getInfluencer().setLaneChangeMode(myPreviousLCMode);
1089 : #ifdef DEBUG_TOC
1090 : std::cout << SIMTIME << " MSDevice_ToC::resetLCMode() restoring LC Mode of vehicle '" << myHolder.getID() << "' to " << myPreviousLCMode << std::endl;
1091 : #endif
1092 : }
1093 336 : myPreviousLCMode = -1;
1094 336 : }
1095 :
1096 :
1097 : void
1098 2598 : MSDevice_ToC::deactivateDeliberateLCs() {
1099 2598 : const int lcModeHolder = myHolderMS->getInfluencer().getLaneChangeMode();
1100 2598 : if (lcModeHolder != LCModeMRM) {
1101 170 : myPreviousLCMode = lcModeHolder;
1102 : #ifdef DEBUG_TOC
1103 : std::cout << SIMTIME << " MSDevice_ToC::setLCModeMRM() setting LC Mode of vehicle '" << myHolder.getID()
1104 : << "' from " << myPreviousLCMode << " to " << LCModeMRM << std::endl;
1105 : #endif
1106 170 : myHolderMS->getInfluencer().setLaneChangeMode(LCModeMRM);
1107 : }
1108 2598 : }
1109 :
1110 : bool
1111 0 : MSDevice_ToC::isManuallyDriven() {
1112 0 : return (myState == MANUAL || myState == RECOVERING);
1113 : }
1114 :
1115 : bool
1116 0 : MSDevice_ToC::isAutomated() {
1117 0 : return (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM);
1118 : }
1119 :
1120 : bool
1121 8610 : MSDevice_ToC::checkDynamicToC() {
1122 : #ifdef DEBUG_DYNAMIC_TOC
1123 : std::cout << SIMTIME << " # MSDevice_ToC::checkDynamicToC() for veh '" << myHolder.getID() << "'" << std::endl;
1124 : #endif
1125 8610 : if (!myDynamicToCActive) {
1126 : return false;
1127 : }
1128 : // The vehicle's current lane
1129 466 : const MSLane* currentLane = myHolderMS->getLane();
1130 :
1131 466 : if (currentLane->isInternal()) {
1132 : // Don't start or abort dynamic ToCs on internal lanes
1133 2 : return myIssuedDynamicToC;
1134 : }
1135 :
1136 464 : if (myIssuedDynamicToC) {
1137 : #ifdef DEBUG_DYNAMIC_TOC
1138 : std::cout << SIMTIME << " Dynamic ToC is ongoing." << std::endl;
1139 : #endif
1140 : // Dynamic ToC in progress. Resist to aborting it if lane was not changed.
1141 52 : if (myDynamicToCLane == currentLane->getNumericalID()) {
1142 : return true;
1143 : }
1144 : }
1145 : // Length for which the current route can be followed
1146 414 : const std::vector<MSVehicle::LaneQ>& bestLanes = myHolderMS->getBestLanes();
1147 : // Maximal distance for route continuation without LCs over the possible start lanes
1148 : double maximalContinuationDistance = 0;
1149 : // Distance for route continuation without LCs from the vehicle's current lane
1150 : double continuationDistanceOnCurrent = 0;
1151 : // Lane of the next stop
1152 : const MSLane* nextStopLane = nullptr;
1153 :
1154 414 : if (myHolderMS->hasStops()) {
1155 158 : nextStopLane = myHolderMS->getNextStop().lane;
1156 : }
1157 1056 : for (auto& i : bestLanes) {
1158 800 : maximalContinuationDistance = MAX2(maximalContinuationDistance, i.length);
1159 800 : if (currentLane == i.lane) {
1160 414 : if (myHolderMS->hasStops()) {
1161 : // Check if the next stop lies on the route continuation from the current lane
1162 158 : for (MSLane* l : i.bestContinuations) {
1163 158 : if (l == nextStopLane) {
1164 : #ifdef DEBUG_DYNAMIC_TOC
1165 : std::cout << SIMTIME << " Stop found on the route continuation from the current lane. => No ToC" << std::endl;
1166 : #endif
1167 : // Stop found on the route continuation from the current lane => no ToC necessary
1168 : return false;
1169 : }
1170 : }
1171 : }
1172 256 : continuationDistanceOnCurrent = i.length;
1173 : }
1174 : }
1175 256 : if (continuationDistanceOnCurrent == maximalContinuationDistance) {
1176 : // There is no better lane than the current, hence no desire to change lanes,
1177 : // which the driver could pursue better than the automation => no reason for ToC.
1178 : return false;
1179 : }
1180 182 : const double distFromCurrent = continuationDistanceOnCurrent - myHolderMS->getPositionOnLane();
1181 182 : const double MRMDist = 0.5 * myHolderMS->getSpeed() * myHolderMS->getSpeed() / MAX2(myMRMDecel, 0.0001);
1182 182 : double distThreshold = myHolderMS->getSpeed() * myDynamicToCThreshold + MRMDist;
1183 : #ifdef DEBUG_DYNAMIC_TOC
1184 : std::cout << " speed=" << myHolderMS->getSpeed()
1185 : << ", distFromCurrent=" << distFromCurrent
1186 : << ", maximal dist=" << maximalContinuationDistance - myHolderMS->getPositionOnLane()
1187 : << ", distThreshold=" << distThreshold
1188 : << std::endl;
1189 : #endif
1190 :
1191 182 : if (myIssuedDynamicToC) {
1192 : // In case of an ongoing ToC, add an additional resistance to abort it.
1193 : // (The lane-check above does not capture lanes subsequent to the dynamic ToC lane)
1194 0 : distThreshold *= DYNAMIC_TOC_ABORT_RESISTANCE_FACTOR;
1195 : }
1196 :
1197 182 : if (distFromCurrent < distThreshold) {
1198 : // TODO: Make this more sophisticated in dealing with low speeds/stops and route ends
1199 : #ifdef DEBUG_DYNAMIC_TOC
1200 : std::cout << SIMTIME << " * distAlongBest is below threshold! *" << std::endl;
1201 : #endif
1202 6 : return true;
1203 : }
1204 :
1205 : return false;
1206 : }
1207 :
1208 : double
1209 8 : MSDevice_ToC::sampleResponseTime(double leadTime) const {
1210 : #ifdef DEBUG_DYNAMIC_TOC
1211 : std::cout << "sampleResponseTime() leadTime=" << leadTime << std::endl;
1212 : #endif
1213 : const double mean = responseTimeMean(leadTime);
1214 8 : const double var = interpolateVariance(leadTime, myMRMProbability);
1215 8 : double rt = RandHelper::randNorm(mean, var, &myResponseTimeRNG);
1216 : #ifdef DEBUG_DYNAMIC_TOC
1217 : std::cout << " mean=" << mean << ", variance=" << var << " => sampled responseTime=" << rt << std::endl;
1218 : #endif
1219 : int it_count = 0;
1220 8 : while (rt < 0 && it_count < MAX_RESPONSETIME_SAMPLE_TRIES) {
1221 0 : rt = RandHelper::randNorm(mean, var, &myResponseTimeRNG);
1222 0 : it_count++;
1223 : }
1224 8 : if (rt < 0) {
1225 : // Didn't generate a positive random response time => use mean
1226 : rt = mean;
1227 : }
1228 8 : return rt;
1229 : }
1230 :
1231 : double
1232 8 : MSDevice_ToC::interpolateVariance(double leadTime, double pMRM) {
1233 : #ifdef DEBUG_DYNAMIC_TOC
1234 : std::cout << "interpolateVariance() leadTime=" << leadTime << ", pMRM=" << pMRM << std::endl;
1235 : #endif
1236 : // Calculate indices for surrounding values in lookup tables
1237 :
1238 : // Find largest p_{i-1} < pMRM < p_{i}
1239 : const auto pi = std::lower_bound(lookupResponseTimeMRMProbs.begin(), lookupResponseTimeMRMProbs.end(), pMRM);
1240 8 : if (pi == lookupResponseTimeMRMProbs.end()) {
1241 : // requested probability lies outside lookup table.
1242 : // => return maximal variance value
1243 : return MAX_RESPONSETIME_VARIANCE;
1244 : }
1245 8 : const size_t pi1 = pi - lookupResponseTimeMRMProbs.begin();
1246 : assert(pi1 > 0);
1247 8 : const size_t pi0 = pi1 - 1;
1248 8 : const double cp = (pMRM - * (pi - 1)) / (*pi - * (pi - 1));
1249 :
1250 : #ifdef DEBUG_DYNAMIC_TOC
1251 : std::cout << " p[=" << pi0 << "]=" << *(pi - 1) << ", p[=" << pi1 << "]=" << *pi << " => cp=" << cp << std::endl;
1252 : #endif
1253 :
1254 : // Find largest p_{i-1} < pMRM < p_{i}
1255 : auto li = std::lower_bound(lookupResponseTimeLeadTimes.begin(), lookupResponseTimeLeadTimes.end(), leadTime);
1256 8 : if (li == lookupResponseTimeLeadTimes.begin()) {
1257 : // Given lead time smaller than minimal lookup-value.
1258 : // Use minimal value from lookup table instead
1259 0 : leadTime = *li;
1260 : li = lookupResponseTimeLeadTimes.begin() + 1;
1261 8 : } else if (li == lookupResponseTimeLeadTimes.end()) {
1262 : // Given leadTime exceeds values in lookup table
1263 : // => induce extrapolation
1264 : li--;
1265 : }
1266 : const size_t li1 = li - lookupResponseTimeLeadTimes.begin();
1267 : const size_t li0 = li1 - 1;
1268 8 : const double cl = (leadTime - * (li - 1)) / (*li - * (li - 1));
1269 :
1270 : #ifdef DEBUG_DYNAMIC_TOC
1271 : std::cout << " l[=" << li0 << "]=" << *(li - 1) << ", l[=" << li1 << "]=" << *li << " => cp=" << cl << std::endl;
1272 : #endif
1273 :
1274 : // 2D interpolation for variance
1275 : // First, interpolate (or extrapolate) variances along leadTimes
1276 8 : const double var00 = lookupResponseTimeVariances[pi0][li0];
1277 8 : const double var01 = lookupResponseTimeVariances[pi0][li1];
1278 8 : const double var10 = lookupResponseTimeVariances[pi1][li0];
1279 8 : const double var11 = lookupResponseTimeVariances[pi1][li1];
1280 8 : const double var_0 = var00 + (var01 - var00) * cl;
1281 8 : const double var_1 = var10 + (var11 - var10) * cl;
1282 : // From these, interpolate along the pMRM-axis
1283 8 : const double var = var_0 + (var_1 - var_0) * cp;
1284 : #ifdef DEBUG_DYNAMIC_TOC
1285 : std::cout << " var00=" << var00 << ", var01=" << var01 << " var10=" << var10 << ", var11=" << var11
1286 : << " var_0=" << var_0 << ", var_1=" << var_1 << ", var=" << var << std::endl;
1287 : #endif
1288 8 : return var;
1289 : }
1290 :
1291 : // Grid of the response time distribution.
1292 : // Generated by the script generateResponseTimeDistributions.py, see Appendix to TransAID Deliverable 3.1v2.
1293 : // Probability for an MRM to occur (start with 0.0, end with 0.5)
1294 : std::vector<double> MSDevice_ToC::lookupResponseTimeMRMProbs = {0.0, 0.05, 0.1, 0.15000000000000002, 0.2, 0.25, 0.30000000000000004, 0.35000000000000003, 0.4, 0.45, 0.5};
1295 : // Lead time grid
1296 : std::vector<double> MSDevice_ToC::lookupResponseTimeLeadTimes = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.0999999999999999, 1.2, 1.3, 1.4, 1.5, 1.5999999999999999, 1.7, 1.8, 1.9, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0};
1297 :
1298 : // Variances of the response time distribution.
1299 : std::vector<std::vector<double> > MSDevice_ToC::lookupResponseTimeVariances = {
1300 : {0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001},
1301 : {0.018238371642696278, 0.03647674328603705, 0.054715114926535656, 0.07295348656987645, 0.09119185821321724, 0.10943022985371582, 0.12766860149705656, 0.14590697314039733, 0.16414534478089599, 0.18238371642423673, 0.2006220880675775, 0.21886045971091828, 0.2370988313514169, 0.25533720299475765, 0.27357557463809845, 0.291813946278597, 0.3100523179219377, 0.32829068956527846, 0.3465290612057772, 0.36476743284911795, 0.4103633619560487, 0.45595929106297967, 0.5015552201670682, 0.5471511492739992, 0.59274707838093, 0.6383430074850186, 0.6839389365919495, 0.7295348656988803, 0.7751307948058112, 0.8207267239098999, 0.8663226530168309, 0.9119185821237615, 1.003110440334781, 1.0943022985486428, 1.1854941567596624, 1.2766860149735242, 1.3678778731845436, 1.4590697313984053, 1.622588042723657, 1.8236013818166044, 2.0271872430355344, 2.2329896377033402, 2.440681612959606, 2.6499766330096066, 2.8606328744048484, 3.0724517481497657, 3.285273075453899, 3.4989689745182173, 3.713437758931686, 3.928598499444084, 4.144386478335934, 4.360749535794346, 4.577645204319768, 4.795038495182951, 5.012900204026633, 5.231205620052272, 5.449933544477286, 5.669065543877604, 5.888585381094657, 6.108478580034079, 6.328732091514834, 6.5493340353396325, 6.991540386888257, 7.4350193801571836, 7.8797023900653835, 8.325528107903486, 8.772441019472117, 9.220390365425358, 9.66932940241786, 10.11921485679467, 10.570006505095746, 11.021666840703753, 11.474160800924851, 11.927455537955435, 12.381520222795276, 12.836325874663427, 13.291845210806684, 13.748052512926236, 14.204923507573522, 14.662435258383752, 15.120566068535554, 15.57929539219183, 16.03860375377652, 16.498472674274336, 16.958884603774735, 17.41982285960362, 17.881271569514066, 18.343215619413176, 18.805640605235663, 19.268532788517863, 19.731879055399546, 20.195666878723525},
1302 : {0.023394708584543455, 0.04678941716973141, 0.07018412575207719, 0.09357883433726513, 0.11697354292245306, 0.14036825150764104, 0.16376296009282898, 0.18715766867517475, 0.2105523772603627, 0.23394708584555063, 0.25734179443073857, 0.2807365030130844, 0.3041312115982723, 0.3275259201834602, 0.3509206287686481, 0.37431533735099387, 0.3977100459361818, 0.42110475452136986, 0.4444994631065578, 0.46789417168890357, 0.5263809431504523, 0.5848677146120012, 0.6433544860735498, 0.7018412575350985, 0.7603280289966473, 0.8188148004581961, 0.8773015719197449, 0.9357883433784517, 0.9942751148400004, 1.0527618863015489, 1.111248657763098, 1.169735429224647, 1.2867089721477445, 1.4036825150708419, 1.520656057991097, 1.6376296009141948, 1.7546031438372918, 1.8715766867603902, 2.080324923070349, 2.3356056603653466, 2.592695753086048, 2.851065033244823, 3.110348235805368, 3.37030701064756, 3.630792243424829, 3.8917140872434826, 4.153020535352749, 4.414682984212653, 4.676686852454919, 4.939025633083471, 5.201697195938797, 5.4647015339779985, 5.728039423002128, 5.991711652753062, 6.255718611539178, 6.520060086487768, 6.784735192689795, 7.0497423770254475, 7.315079462951026, 7.580743715621537, 7.846731914823575, 8.113040428416943, 8.646602223970579, 9.181394311584102, 9.717379133745458, 10.25451769188949, 10.792770521511661, 11.332098388641393, 11.872462773672844, 12.41382619675905, 12.956152426938662, 13.499406606935544, 14.04355531739462, 14.588566598200957, 15.134409939740127, 15.681056253544272, 16.228477829207687, 16.776648282531472, 17.32554249848686, 17.875136571609353, 18.425407745596857, 18.976334353419617, 19.527895758814104, 20.080072299738145, 20.632845234156534, 21.18619668838177, 21.740109608063758, 22.294567711842525, 22.849555447666962, 23.405057951674344, 23.96106100953682, 24.517551020220964},
1303 : {0.028809965676139145, 0.05761993135292278, 0.08642989702686427, 0.11523986270364789, 0.14404982838043154, 0.172859794054373, 0.20166975973115658, 0.23047972540794023, 0.2592896910818817, 0.2880996567586654, 0.31690962243544896, 0.34571958811223263, 0.37452955378617403, 0.4033395194629576, 0.4321494851397413, 0.4609594508136828, 0.4897694164904665, 0.51857938216725, 0.5473893478411916, 0.5761993135179752, 0.6482242277085132, 0.7202491418990512, 0.7922740560867471, 0.864298970277285, 0.9363238844678232, 1.0083487986555189, 1.0803737128460569, 1.152398627036595, 1.224423541227133, 1.296448455414829, 1.368473369605367, 1.4404982837959048, 1.584548112174139, 1.7285979405552145, 1.8726477689334486, 2.0166975973145242, 2.1607474256927586, 2.3047972540738346, 2.5572219533483644, 2.8623099438447785, 3.167154753839855, 3.4715923078311928, 3.775618300633292, 4.079301412505033, 4.3827364323759, 4.686020985499979, 4.989245061612653, 5.2924871133699085, 5.595813357348367, 5.89927852360174, 6.202927167199209, 6.506795109670751, 6.810910812533207, 7.115296603265157, 7.419969732096102, 7.724943265058281, 8.030226829842663, 8.33582723446787, 8.641748978492437, 8.947994674556652, 9.254565395777925, 9.561460961999748, 10.17622101728854, 10.792256328037844, 11.409539737303032, 12.02803871883203, 12.647717622463388, 13.268539213916304, 13.890465727714453, 14.513459582113466, 15.137483858085837, 15.76250261298258, 16.388481078046894, 17.015385774331957, 17.643184571383188, 18.271846706039163, 18.901342773672106, 19.531644700723955, 20.16272570482796, 20.79456024708863, 21.427123979740387, 22.06039369148417, 22.694347252144688, 23.32896355779389, 23.964222477085105, 24.600104799357926, 25.23659218482918, 25.873667117046345, 26.51131285772261, 27.149513403967962, 27.788253447896256, 28.427518338543063},
1304 : {0.03496845765860337, 0.06993691531785123, 0.1049053729770991, 0.13987383063634692, 0.17484228829559478, 0.20981074595200053, 0.24477920361124836, 0.2797476612704962, 0.314716118929744, 0.34968457658899194, 0.38465303424823977, 0.41962149190748765, 0.4545899495638933, 0.48955840722314126, 0.5245268648823892, 0.5594953225416369, 0.5944637802008848, 0.6294322378601326, 0.6644006955193805, 0.6993691531757862, 0.7867902973239058, 0.8742114414720256, 0.961632585617303, 1.0490537297654225, 1.1364748739135424, 1.2238960180588196, 1.3113171622069395, 1.3987383063550594, 1.4861594505003368, 1.5735805946484562, 1.6610017387965759, 1.748422882941853, 1.9232651712352506, 2.0981074595314895, 2.272949747824887, 2.4477920361182846, 2.6226343244145234, 2.7974766127079205, 3.0926745755509586, 3.44395841916428, 3.7929654946149927, 4.140199155580832, 4.48610487276643, 4.8310499148399675, 5.175327720605737, 5.519169410160118, 5.862755881539858, 6.20622837304298, 6.549697059107542, 6.893247832651301, 7.236947584569466, 7.580848293751031, 7.924990195098607, 8.2694042393908, 8.614114010475241, 8.959137226336916, 9.30448692001335, 9.650172373181427, 9.996199857775714, 10.342573227835842, 10.689294393844476, 11.036363704475946, 11.73154213703699, 12.428090426873897, 13.125980076789245, 13.825176212794954, 14.52564028426291, 15.227331883606062, 15.930209972250445, 16.634233702118422, 17.339362959284276, 18.045558715641334, 18.752783247333983, 19.461000260660008, 20.170174953762714, 20.880274034013603, 21.591265705145904, 22.303119634055196, 23.015806904341318, 23.7292999616137, 24.443572554090043, 25.158599671023588, 25.874357480669964, 26.590823269047004, 27.30797538027189, 28.025793159035764, 28.74425689552527, 29.46334777297606, 30.183047817969005, 30.903339853423454, 31.624207454305022, 32.345634905899644},
1305 : {0.04208452197242317, 0.08416904394549082, 0.12625356591855852, 0.16833808789162616, 0.21042260986469383, 0.25250713183776147, 0.294591653807987, 0.33667617578105463, 0.3787606977541223, 0.42084521972719, 0.46292974170025764, 0.5050142636733252, 0.5470987856463931, 0.5891833076194606, 0.6312678295925284, 0.6733523515627537, 0.7154368735358214, 0.7575213955088891, 0.7996059174819568, 0.8416904394550245, 0.9469017443876938, 1.0521130493203628, 1.1573243542501899, 1.2625356591828591, 1.3677469641155282, 1.472958269045355, 1.5781695739780248, 1.6833808789106937, 1.7885921838433625, 1.8938034887731896, 1.9990147937058587, 2.104226098638527, 2.314648708501024, 2.5250713183663627, 2.7354939282288586, 2.9459165380941967, 3.1563391479566936, 3.3667617578220317, 3.703839316684887, 4.098607599735211, 4.490071039515135, 4.879192386567447, 5.266673871161598, 5.6530296960510835, 6.038639278868162, 6.423784955842712, 6.808678484059117, 7.1934797498117895, 7.578310096881422, 7.9632619279700085, 8.348405702022065, 8.733795092290785, 9.119470830182808, 9.505463599150936, 9.891796234154242, 10.278485408041451, 10.665542934966393, 11.05297678524097, 11.440791880843797, 11.828990722803214, 12.217573888696098, 12.606540429161571, 13.385614043672865, 14.166184035906006, 14.948213302277296, 15.731659164963906, 16.51647601334669, 17.302617053034968, 18.09003546045466, 18.87868513730469, 19.66852119352658, 20.459500245021562, 21.251580584675224, 22.044722266798285, 22.838887132598156, 23.634038796019215, 24.430142603281702, 25.22716557558935, 26.025076341551085, 26.823845063912813, 27.62344336382784, 28.423844244828874, 29.22502201803638, 30.026952229552563, 30.82961159071451, 31.63297791152784, 32.43703003753926, 33.24174779014256, 34.047111910360435, 34.85310400598881, 35.65970650197814, 36.46690259392711},
1306 : {0.05029020480396514, 0.10058040960573261, 0.15087061441034225, 0.2011608192121097, 0.2514510240167194, 0.301741228821329, 0.35203143362309647, 0.40232163842770624, 0.45261184322947356, 0.5029020480340831, 0.5531922528358507, 0.6034824576404602, 0.6537726624450699, 0.7040628672468374, 0.7543530720514469, 0.8046432768532146, 0.8549334816578241, 0.9052236864595916, 0.9555138912642014, 1.0058040960688106, 1.1315296080760717, 1.2572551200833324, 1.382980632093436, 1.5087061441006968, 1.6344316561107992, 1.7601571681180603, 1.8858826801253215, 2.0116081921354243, 2.137333704142684, 2.263059216152788, 2.3887847281600485, 2.514510240170152, 2.765961264184674, 3.017412288202038, 3.2688633122194015, 3.520314336236765, 3.7717653602541295, 4.023216384271493, 4.402923686706604, 4.840923169412718, 5.275628140231794, 5.708106387011112, 6.139096012777341, 6.569117835239806, 6.998545742885471, 7.427651941064436, 7.856636809801444, 8.28564907733453, 8.714799743029685, 9.144171870687785, 9.573827594895418, 10.00381321001211, 10.43416291693517, 10.864901615202994, 11.296047006509264, 11.72761119486633, 12.159601914603718, 12.592023480161025, 13.024877525833228, 13.458163585558754, 13.891879549849177, 14.326022027631314, 15.195568219985953, 16.066758980781113, 16.93954397110994, 17.813869202173244, 18.68967930447209, 19.566918991345418, 20.44553399181503, 21.325471630737475, 22.206681173178218, 23.089114010781095, 23.972723742457497, 24.857466184805716, 25.743299336515662, 26.63018331333154, 27.518080264958197, 28.4069542817556, 29.296771296561822, 30.187498985305254, 31.07910666877645, 31.97156521721369, 32.86484695863455, 33.75892559154721, 34.653776102328635, 35.54937468734068, 36.44569867980954, 37.34272648128694, 38.24043749755077, 39.13881207875172, 40.03783146350794, 40.937477726773984},
1307 : {0.05974016468300759, 0.11948032936381749, 0.17922049404462742, 0.23896065872827943, 0.29870082340908927, 0.35844098808989927, 0.4181811527735513, 0.47792131745436117, 0.5376614821380133, 0.5974016468188231, 0.657141811499633, 0.7168819761832851, 0.7766221408640949, 0.8363623055449051, 0.8961024702285572, 0.955842634909367, 1.0155827995930191, 1.0753229642738293, 1.135063128954639, 1.1948032936382913, 1.344153705341737, 1.493504117048025, 1.6428545287514704, 1.7922049404549163, 1.9415553521612046, 2.0909057638646504, 2.2402561755709387, 2.389606587274385, 2.5389569989806726, 2.688307410684118, 2.8376578223904056, 2.987008234093852, 3.2857090575035857, 3.58440988091332, 3.8831107043230535, 4.181811527729945, 4.48051235113968, 4.779213174549414, 5.204876111923692, 5.688848562937568, 6.170159044583231, 6.6497495644421285, 7.128261753669921, 7.606142949678828, 8.083710709627423, 8.561193555361694, 9.038757543068261, 9.516524068724227, 9.99458208377549, 10.47299664830626, 10.951815027051936, 11.431071102373838, 11.910788612986488, 12.39098355983018, 12.871666012589971, 13.352841479046571, 13.834511951858257, 14.316676714667919, 14.799332966945224, 15.282476311040416, 15.766101133711286, 16.250200906162327, 17.219795978620663, 18.1911988298489, 19.164342959599296, 20.139160814458737, 21.115585503946967, 22.093551853025446, 23.07299702417972, 24.053860858945782, 25.036086036434696, 26.019618113131642, 27.004405486541614, 27.990399311257423, 28.977553386435417, 29.965824027565322, 30.95516993094154, 31.94555203660525, 32.93693339332716, 33.92927902800424, 34.92255582087156, 35.91673238727074, 36.91177896637648, 37.907667316880286, 38.90437061956949, 39.90186338652862, 40.90012137664726, 41.899121517093974, 42.89884183037187, 43.8992613666098, 44.90036014068208, 45.90211907383619},
1308 : {0.07067515415184052, 0.14135030830148337, 0.2120254624511261, 0.2827006166036112, 0.35337577075325394, 0.4240509249028968, 0.49472607905538185, 0.5654012332050246, 0.6360763873575095, 0.7067515415071527, 0.7774266956567951, 0.8481018498092803, 0.9187770039589231, 0.9894521581085659, 1.060127312261051, 1.1308024664106937, 1.2014776205603366, 1.2721527747128218, 1.3428279288624643, 1.41350308301495, 1.5901909683904774, 1.7668788537660056, 1.943566739144376, 2.120254624519904, 2.2969425098982743, 2.473630395273803, 2.6503182806493313, 2.8270061660277013, 3.0036940514032295, 3.1803819367816004, 3.3570698221571273, 3.5337577075354982, 3.8871334782865548, 4.240509249040453, 4.593885019794351, 4.947260790548251, 5.300636561302148, 5.654012332053204, 6.131630444292413, 6.6672022906208355, 7.200987739963464, 7.733716006955079, 8.265882445019285, 8.797830454475601, 9.32980159851235, 9.861967438834494, 10.394450401173598, 10.927337816806162, 11.460691587201293, 11.994554966496775, 12.528957402009762, 13.06391803975272, 13.599448295828148, 14.135553763816139, 14.672235643520898, 15.209491820318211, 15.747317686564726, 16.285706770680626, 16.82465122144653, 17.364142182462015, 17.904170082649248, 18.444724862108774, 19.52737339128757, 20.612003289072593, 21.69853012990063, 22.786871401229217, 23.87694757433194, 24.968682680039276, 26.062004572321317, 27.156844995848896, 28.253139532174295, 29.350827472729005, 30.449851649907924, 31.55015824661291, 32.651696597281045, 33.75441898881355, 34.85828046658357, 35.96323864863796, 37.06925354984671, 38.176287416815526, 39.2843045737864, 40.39327127936956, 41.50315559373177, 42.613927255723794, 43.72555756930443, 44.838019298684486, 45.951286571522466, 47.065334789581065, 48.18014054623036, 49.29568155028052, 50.41193655559852, 51.52888529603219},
1309 : {0.0834623671324666, 0.16692473426273555, 0.2503871013958466, 0.33384946852611547, 0.4173118356592266, 0.5007742027894957, 0.5842365699226064, 0.6676989370528754, 0.7511613041859866, 0.8346236713162553, 0.9180860384493664, 1.0015484055796355, 1.0850107727127467, 1.1684731398430155, 1.2519355069761264, 1.3353978741063957, 1.4188602412395066, 1.5023226083697758, 1.5857849755028866, 1.6692473426331556, 1.8779032604630912, 2.0865591782930264, 2.29521509612012, 2.5038710139500555, 2.7125269317799905, 2.921182849609927, 3.1298387674370196, 3.338494685266956, 3.547150603096892, 3.7558065209268268, 3.96446243875392, 4.173118356583855, 4.590430192243725, 5.007742027900754, 5.425053863557784, 5.842365699217655, 6.259677534874682, 6.676989370534554, 7.215284811865045, 7.810942636066625, 8.405713438558344, 9.000109193262631, 9.594476065866042, 10.189051324756685, 10.783998757795331, 11.379431470741277, 11.975426983124095, 12.572037465005534, 13.169296821117609, 13.767225679430393, 14.365834957075359, 14.965128442509108, 15.565104686191797, 16.165758398192054, 16.767081489665355, 17.369063854126264, 17.971693956723634, 18.574959280506526, 19.178846665295886, 19.78334256540095, 20.38843324553279, 20.994104929469565, 22.20713664504607, 23.42233029997001, 24.63958259994195, 25.858795291719396, 27.079875555554814, 28.302736078822026, 29.527294941445533, 30.75347539415742, 31.981205580215, 33.21041823195959, 34.44105036161415, 35.67304295805245, 36.90634069627536, 38.14089166337484, 39.3766471025938, 40.61356117597085, 41.851590745280404, 43.090695170440334, 44.33083612445286, 45.57197742365028, 46.814084872185866, 48.05712611949615, 49.301070529748834, 50.54588906213925, 51.79155416112571, 53.0380396556748, 54.285320666751495, 55.533373522224736, 56.782175678619716, 58.031705649011975},
1310 : {0.09864342769295685, 0.19728685538371601, 0.2959302830773173, 0.39457371076807657, 0.49321713846167803, 0.5918605661524371, 0.6905039938460386, 0.7891474215367978, 0.887790849230399, 0.9864342769211584, 1.0850777046147597, 1.1837211323055188, 1.2823645599991202, 1.38100798768988, 1.4796514153834808, 1.5782948430742403, 1.6769382707678415, 1.7755816984586006, 1.874225126152202, 1.972868553842961, 2.219477123074122, 2.4660856923052834, 2.7126942615364444, 2.9593028307647646, 3.2059113999959257, 3.4525199692270867, 3.6991285384582473, 3.945737107686567, 4.192345676917727, 4.438954246148888, 4.68556281538005, 4.932171384608369, 5.425388523070691, 5.918605661530172, 6.411822799992494, 6.905039938451975, 7.398257076914296, 7.891474215373778, 8.502335361374866, 9.169831074405188, 9.837265003168877, 10.504960425335845, 11.173131332846934, 11.841919360545138, 12.511417180930938, 13.181683762841976, 13.85275456878272, 14.524648510968875, 15.197372779403622, 15.870926242469201, 16.545301871890324, 17.220488489846183, 17.896472038316816, 18.573236507380663, 19.250764617377587, 19.929038321651447, 20.608039177427425, 21.287748619021162, 21.968148158299684, 22.64921953063529, 23.330944799863957, 24.013306432352234, 25.37987095153259, 26.74878238692951, 28.119918223260417, 29.4931641334551, 30.8684136985658, 32.245567980998565, 33.624535031317535, 35.005229375702534, 36.38757151118004, 37.77148742362557, 39.156908136182956, 40.54376929127801, 41.93201076678101, 43.32157632534552, 44.712413295099445, 46.1044722794653, 47.497706893719666, 48.892073525949804, 50.2875311201024, 51.68404097903562, 53.081566585544806, 54.48007343965984, 55.87952891050276, 57.27990210130182, 58.68116372625177, 60.08328599798667, 61.48624252468206, 62.890008215820075, 64.29455919573915, 65.6998727243063},
1311 : };
1312 :
1313 :
1314 : /****************************************************************************/
|