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 : // Maximal tries to sample a positive value from the gaussian distribution
86 : // used for the driver response time when a TOR is issued. (the distribution is assumed truncated at zero)
87 : #define MAX_RESPONSETIME_SAMPLE_TRIES 100
88 : // Maximal variance of responsetimes (returned for pMRM outside lookup table, i.e. pMRM>0.5), see interpolateVariance()
89 : #define MAX_RESPONSETIME_VARIANCE 10000
90 :
91 :
92 : // ---------------------------------------------------------------------------
93 : // static members
94 : // ---------------------------------------------------------------------------
95 : std::set<MSDevice_ToC*, ComparatorNumericalIdLess> MSDevice_ToC::myInstances = std::set<MSDevice_ToC*, ComparatorNumericalIdLess>();
96 : std::set<std::string> MSDevice_ToC::createdOutputFiles;
97 : int MSDevice_ToC::LCModeMRM = 768; // = 0b001100000000 - no autonomous changes, no speed adaptation
98 : SumoRNG MSDevice_ToC::myResponseTimeRNG("toc");
99 :
100 :
101 : // ===========================================================================
102 : // method definitions
103 : // ===========================================================================
104 : // ---------------------------------------------------------------------------
105 : // static initialisation methods
106 : // ---------------------------------------------------------------------------
107 : void
108 43644 : MSDevice_ToC::insertOptions(OptionsCont& oc) {
109 43644 : oc.addOptionSubTopic("ToC Device");
110 87288 : insertDefaultAssignmentOptions("toc", "ToC Device", oc);
111 :
112 43644 : oc.doRegister("device.toc.manualType", new Option_String());
113 87288 : oc.addDescription("device.toc.manualType", "ToC Device", TL("Vehicle type for manual driving regime."));
114 43644 : oc.doRegister("device.toc.automatedType", new Option_String());
115 87288 : oc.addDescription("device.toc.automatedType", "ToC Device", TL("Vehicle type for automated driving regime."));
116 43644 : oc.doRegister("device.toc.responseTime", new Option_Float(DEFAULT_RESPONSE_TIME));
117 87288 : oc.addDescription("device.toc.responseTime", "ToC Device", TL("Average response time needed by a driver to take back control."));
118 43644 : oc.doRegister("device.toc.recoveryRate", new Option_Float(DEFAULT_RECOVERY_RATE));
119 87288 : oc.addDescription("device.toc.recoveryRate", "ToC Device", TL("Recovery rate for the driver's awareness after a ToC."));
120 43644 : oc.doRegister("device.toc.lcAbstinence", new Option_Float(DEFAULT_LCABSTINENCE));
121 87288 : oc.addDescription("device.toc.lcAbstinence", "ToC Device", TL("Attention level below which a driver restrains from performing lane changes (value in [0,1])."));
122 43644 : oc.doRegister("device.toc.initialAwareness", new Option_Float(DEFAULT_INITIAL_AWARENESS));
123 87288 : oc.addDescription("device.toc.initialAwareness", "ToC Device", TL("Average awareness a driver has initially after a ToC (value in [0,1])."));
124 43644 : oc.doRegister("device.toc.mrmDecel", new Option_Float(DEFAULT_MRM_DECEL));
125 87288 : oc.addDescription("device.toc.mrmDecel", "ToC Device", TL("Deceleration rate applied during a 'minimum risk maneuver'."));
126 43644 : oc.doRegister("device.toc.dynamicToCThreshold", new Option_Float(DEFAULT_DYNAMIC_TOC_THRESHOLD));
127 87288 : 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."));
128 43644 : oc.doRegister("device.toc.dynamicMRMProbability", new Option_Float(DEFAULT_MRM_PROBABILITY));
129 87288 : oc.addDescription("device.toc.dynamicMRMProbability", "ToC Device", TL("Probability that a dynamically triggered TOR is not answered in time."));
130 43644 : oc.doRegister("device.toc.mrmKeepRight", new Option_Bool(false));
131 87288 : oc.addDescription("device.toc.mrmKeepRight", "ToC Device", TL("If true, the vehicle tries to change to the right during an MRM."));
132 43644 : oc.doRegister("device.toc.mrmSafeSpot", new Option_String());
133 87288 : oc.addDescription("device.toc.mrmSafeSpot", "ToC Device", TL("If set, the vehicle tries to reach the given named stopping place during an MRM."));
134 43644 : oc.doRegister("device.toc.mrmSafeSpotDuration", new Option_Float(60.));
135 87288 : oc.addDescription("device.toc.mrmSafeSpotDuration", "ToC Device", TL("Duration the vehicle stays at the safe spot after an MRM."));
136 43644 : oc.doRegister("device.toc.maxPreparationAccel", new Option_Float(0.0));
137 87288 : oc.addDescription("device.toc.maxPreparationAccel", "ToC Device", TL("Maximal acceleration that may be applied during the ToC preparation phase."));
138 43644 : oc.doRegister("device.toc.ogNewTimeHeadway", new Option_Float(-1.0));
139 87288 : oc.addDescription("device.toc.ogNewTimeHeadway", "ToC Device", TL("Timegap for ToC preparation phase."));
140 43644 : oc.doRegister("device.toc.ogNewSpaceHeadway", new Option_Float(-1.0));
141 87288 : oc.addDescription("device.toc.ogNewSpaceHeadway", "ToC Device", TL("Additional spacing for ToC preparation phase."));
142 43644 : oc.doRegister("device.toc.ogMaxDecel", new Option_Float(-1.0));
143 87288 : oc.addDescription("device.toc.ogMaxDecel", "ToC Device", TL("Maximal deceleration applied for establishing increased gap in ToC preparation phase."));
144 43644 : oc.doRegister("device.toc.ogChangeRate", new Option_Float(-1.0));
145 87288 : oc.addDescription("device.toc.ogChangeRate", "ToC Device", TL("Rate of adaptation towards the increased headway during ToC preparation."));
146 43644 : oc.doRegister("device.toc.useColorScheme", new Option_Bool(true));
147 87288 : oc.addDescription("device.toc.useColorScheme", "ToC Device", TL("Whether a coloring scheme shall by applied to indicate the different ToC stages."));
148 43644 : oc.doRegister("device.toc.file", new Option_String());
149 87288 : oc.addDescription("device.toc.file", "ToC Device", TL("Switches on output by specifying an output filename."));
150 43644 : }
151 :
152 :
153 : void
154 5104373 : MSDevice_ToC::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
155 5104373 : OptionsCont& oc = OptionsCont::getOptions();
156 10208746 : if (equippedByDefaultAssignmentOptions(oc, "toc", v, false)) {
157 45 : if (MSGlobals::gUseMesoSim) {
158 0 : WRITE_WARNING(TL("ToC device is not supported by the mesoscopic simulation."));
159 0 : return;
160 : }
161 90 : const std::string manualType = v.getStringParam("device.toc.manualType", true);
162 91 : const std::string automatedType = v.getStringParam("device.toc.automatedType", true);
163 47 : const SUMOTime responseTime = TIME2STEPS(v.getFloatParam("device.toc.responseTime"));
164 43 : const double recoveryRate = v.getFloatParam("device.toc.recoveryRate");
165 43 : const double lcAbstinence = v.getFloatParam("device.toc.lcAbstinence");
166 43 : const double initialAwareness = v.getFloatParam("device.toc.initialAwareness");
167 43 : const double mrmDecel = v.getFloatParam("device.toc.mrmDecel");
168 43 : const bool useColoring = v.getBoolParam("device.toc.useColorScheme");
169 88 : const std::string file = v.getStringParam("device.toc.file");
170 43 : const OpenGapParams ogp = getOpenGapParams(v);
171 43 : const double dynamicToCThreshold = v.getFloatParam("device.toc.dynamicToCThreshold");
172 43 : const double dynamicMRMProbability = getDynamicMRMProbability(v);
173 43 : const bool mrmKeepRight = v.getBoolParam("device.toc.mrmKeepRight");
174 88 : const std::string mrmSafeSpot = v.getStringParam("device.toc.mrmSafeSpot");
175 43 : const SUMOTime mrmSafeSpotDuration = TIME2STEPS(v.getFloatParam("device.toc.mrmSafeSpotDuration"));
176 43 : const double maxPreparationAccel = v.getFloatParam("device.toc.maxPreparationAccel");
177 : // build the device
178 43 : MSDevice_ToC* device = new MSDevice_ToC(v, "toc_" + v.getID(), file,
179 : manualType, automatedType, responseTime, recoveryRate,
180 : lcAbstinence, initialAwareness, mrmDecel, dynamicToCThreshold,
181 : dynamicMRMProbability, maxPreparationAccel, mrmKeepRight,
182 45 : mrmSafeSpot, mrmSafeSpotDuration, useColoring, ogp);
183 43 : into.push_back(device);
184 : }
185 : }
186 :
187 :
188 : double
189 43 : MSDevice_ToC::getDynamicMRMProbability(const SUMOVehicle& v) {
190 43 : double pMRM = v.getFloatParam("device.toc.dynamicMRMProbability");
191 43 : if (pMRM < 0 || pMRM > 0.5) {
192 1 : const double pMRMTrunc = MAX2(0.0, MIN2(0.5, pMRM));
193 2 : 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));
194 : return pMRMTrunc;
195 : }
196 : return pMRM;
197 : }
198 :
199 :
200 : MSDevice_ToC::OpenGapParams
201 43 : MSDevice_ToC::getOpenGapParams(const SUMOVehicle& v) {
202 43 : double timegap = v.getFloatParam("device.toc.ogNewTimeHeadway");
203 43 : double spacing = v.getFloatParam("device.toc.ogNewSpaceHeadway");
204 43 : double changeRate = v.getFloatParam("device.toc.ogChangeRate");
205 43 : double maxDecel = v.getFloatParam("device.toc.ogMaxDecel");
206 : bool specifiedAny = false;
207 :
208 43 : if (changeRate == -1.0) {
209 : changeRate = DEFAULT_OPENGAP_CHANGERATE;
210 : } else {
211 : specifiedAny = true;
212 : }
213 43 : if (maxDecel == -1.0) {
214 : maxDecel = DEFAULT_OPENGAP_MAXDECEL;
215 : } else {
216 : specifiedAny = true;
217 : }
218 43 : if (specifiedAny && timegap == -1 && spacing == -1) {
219 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."))
220 : }
221 43 : if (timegap == -1) {
222 : timegap = DEFAULT_OPENGAP_TIMEGAP;
223 : } else {
224 : specifiedAny = true;
225 : }
226 43 : if (spacing == -1) {
227 : spacing = DEFAULT_OPENGAP_SPACING;
228 : } else {
229 : specifiedAny = true;
230 : }
231 : #ifdef DEBUG_TOC
232 : std::cout << "Parsed openGapParams: \n"
233 : << " timegap=" << timegap
234 : << ", spacing=" << spacing
235 : << ", changeRate=" << changeRate
236 : << ", maxDecel=" << maxDecel
237 : << std::endl;
238 : #endif
239 43 : return OpenGapParams(timegap, spacing, changeRate, maxDecel, specifiedAny);
240 : }
241 :
242 : // ---------------------------------------------------------------------------
243 : // MSDevice_ToC-methods
244 : // ---------------------------------------------------------------------------
245 43 : MSDevice_ToC::MSDevice_ToC(SUMOVehicle& holder, const std::string& id, const std::string& outputFilename,
246 : const std::string& manualType, const std::string& automatedType, SUMOTime responseTime, double recoveryRate,
247 : double lcAbstinence, double initialAwareness, double mrmDecel,
248 : double dynamicToCThreshold, double dynamicMRMProbability, double maxPreparationAccel,
249 43 : bool mrmKeepRight, const std::string& mrmSafeSpot, SUMOTime mrmSafeSpotDuration, bool useColorScheme, OpenGapParams ogp) :
250 : MSVehicleDevice(holder, id),
251 43 : myManualTypeID(manualType),
252 43 : myAutomatedTypeID(automatedType),
253 43 : myResponseTime(responseTime),
254 43 : myRecoveryRate(recoveryRate),
255 43 : myLCAbstinence(lcAbstinence),
256 43 : myInitialAwareness(initialAwareness),
257 43 : myMRMDecel(mrmDecel),
258 43 : myCurrentAwareness(1.),
259 43 : myUseColorScheme(useColorScheme),
260 43 : myTriggerMRMCommand(nullptr),
261 43 : myTriggerToCCommand(nullptr),
262 43 : myRecoverAwarenessCommand(nullptr),
263 43 : myExecuteMRMCommand(nullptr),
264 43 : myPrepareToCCommand(nullptr),
265 43 : myOutputFile(nullptr),
266 : myEvents(),
267 : myEventLanes(),
268 : myEventXY(),
269 43 : myPreviousLCMode(-1),
270 43 : myOpenGapParams(ogp),
271 43 : myDynamicToCThreshold(dynamicToCThreshold),
272 43 : myMRMProbability(dynamicMRMProbability),
273 43 : myDynamicToCActive(dynamicToCThreshold > 0),
274 43 : myIssuedDynamicToC(false),
275 43 : myDynamicToCLane(-1),
276 43 : myMRMKeepRight(mrmKeepRight),
277 43 : myMRMSafeSpot(mrmSafeSpot),
278 43 : myMRMSafeSpotDuration(mrmSafeSpotDuration),
279 43 : myMaxPreparationAccel(maxPreparationAccel),
280 43 : myOriginalMaxAccel(-1) {
281 : // Take care! Holder is currently being constructed. Cast occurs before completion.
282 43 : myHolderMS = static_cast<MSVehicle*>(&holder);
283 :
284 43 : if (outputFilename != "") {
285 35 : myOutputFile = &OutputDevice::getDevice(outputFilename);
286 : // TODO: make xsd, include header
287 : // myOutputFile.writeXMLHeader("ToCDeviceLog", "ToCDeviceLog.xsd");
288 : if (createdOutputFiles.count(outputFilename) == 0) {
289 68 : myOutputFile->writeXMLHeader("ToCDeviceLog", "");
290 : createdOutputFiles.insert(outputFilename);
291 : }
292 : }
293 :
294 : // Check if the given vTypes for the ToC Device are vTypeDistributions
295 43 : MSVehicleControl& vehCtrl = MSNet::getInstance()->getVehicleControl();
296 43 : const bool automatedVTypeIsDist = vehCtrl.hasVTypeDistribution(myAutomatedTypeID);
297 43 : const bool manualVTypeIsDist = vehCtrl.hasVTypeDistribution(myManualTypeID);
298 :
299 : // Check if the vType of the holder matches one of the given vTypes
300 43 : std::string holderVTypeID = holder.getVehicleType().getID();
301 43 : if (holderVTypeID == myManualTypeID) {
302 3 : myState = ToCState::MANUAL;
303 40 : } else if (holderVTypeID == myAutomatedTypeID) {
304 38 : myState = ToCState::AUTOMATED;
305 3 : } else if (manualVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myManualTypeID) > 0) {
306 : // Holder type id is from the given manual type distribution.
307 0 : myState = ToCState::MANUAL;
308 : myManualTypeID = holderVTypeID;
309 3 : } else if (automatedVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myAutomatedTypeID) > 0) {
310 : // Holder type id is from the given automated type distribution.
311 1 : myState = ToCState::AUTOMATED;
312 : myAutomatedTypeID = holderVTypeID;
313 : } else {
314 1 : throw ProcessError("Vehicle type of vehicle '" + holder.getID() + "' ('" +
315 1 : holder.getVehicleType().getID() + "') must coincide with manualType ('" +
316 1 : manualType + "') or automatedType ('" + automatedType +
317 2 : "') specified for its ToC-device (or drawn from the specified vTypeDistributions).");
318 : }
319 42 : if (!vehCtrl.hasVType(myAutomatedTypeID)) {
320 1 : throw ProcessError("The automated vehicle type '" + myAutomatedTypeID +
321 2 : "' of vehicle '" + holder.getID() + "' is not known.");
322 : }
323 41 : if (!vehCtrl.hasVType(myManualTypeID)) {
324 0 : throw ProcessError("The manual vehicle type '" + myManualTypeID +
325 0 : "' of vehicle '" + holder.getID() + "' is not known.");
326 : }
327 :
328 : // Eventually instantiate given vTypes from distributions
329 41 : if (myState == ToCState::MANUAL && automatedVTypeIsDist) {
330 0 : myAutomatedTypeID = vehCtrl.getVType(myAutomatedTypeID, MSRouteHandler::getParsingRNG())->getID();
331 41 : } else if (myState == ToCState::AUTOMATED && manualVTypeIsDist) {
332 1 : myManualTypeID = vehCtrl.getVType(myManualTypeID, MSRouteHandler::getParsingRNG())->getID();
333 : }
334 :
335 : // register at static instance container
336 43 : myInstances.insert(this);
337 41 : initColorScheme();
338 :
339 : #ifdef DEBUG_TOC
340 : std::cout << "initialized device '" << id << "' with "
341 : << "outputFilename=" << outputFilename << ", "
342 : << "myManualType=" << myManualTypeID << ", "
343 : << "myAutomatedType=" << myAutomatedTypeID << ", "
344 : << "myResponseTime=" << myResponseTime << ", "
345 : << "myRecoveryRate=" << myRecoveryRate << ", "
346 : << "myInitialAwareness=" << myInitialAwareness << ", "
347 : << "myMRMDecel=" << myMRMDecel << ", "
348 : << "ogTimeHeadway=" << myOpenGapParams.newTimeHeadway << ", "
349 : << "ogSpaceHeadway=" << myOpenGapParams.newSpaceHeadway << ", "
350 : << "ogChangeRate=" << myOpenGapParams.changeRate << ", "
351 : << "ogMaxDecel=" << myOpenGapParams.maxDecel << ", "
352 : << "ogActive=" << myOpenGapParams.active << ", "
353 : << "myCurrentAwareness=" << myCurrentAwareness << ", "
354 : << "myState=" << _2string(myState) << std::endl;
355 : #endif
356 :
357 : assert(myInitialAwareness <= 1.0 && myInitialAwareness >= 0.0);
358 41 : }
359 :
360 :
361 :
362 : void
363 41 : MSDevice_ToC::initColorScheme() {
364 : //RGBColor(red, green, blue)
365 41 : myColorScheme[MANUAL] = MSNet::getInstance()->getVehicleControl().getVType(myManualTypeID)->getColor();
366 41 : myColorScheme[AUTOMATED] = MSNet::getInstance()->getVehicleControl().getVType(myAutomatedTypeID)->getColor();
367 41 : myColorScheme[PREPARING_TOC] = RGBColor(200, 200, 250); // light blue
368 41 : myColorScheme[MRM] = RGBColor(250, 50, 50); // red
369 41 : myColorScheme[RECOVERING] = RGBColor(250, 210, 150); // light yellow
370 41 : myColorScheme[UNDEFINED] = RGBColor(150, 150, 150); // gray
371 41 : }
372 :
373 :
374 82 : MSDevice_ToC::~MSDevice_ToC() {
375 : // unregister from static instance container
376 41 : myInstances.erase(this);
377 : // deschedule commands associated to this device
378 41 : if (myTriggerMRMCommand != nullptr) {
379 : myTriggerMRMCommand->deschedule();
380 : }
381 41 : if (myTriggerToCCommand != nullptr) {
382 : myTriggerToCCommand->deschedule();
383 : }
384 41 : if (myRecoverAwarenessCommand != nullptr) {
385 : myRecoverAwarenessCommand->deschedule();
386 : }
387 41 : if (myExecuteMRMCommand != nullptr) {
388 : myExecuteMRMCommand->deschedule();
389 2 : resetDeliberateLCs();
390 : }
391 41 : if (myPrepareToCCommand != nullptr) {
392 : myPrepareToCCommand->deschedule();
393 : }
394 123 : }
395 :
396 : void
397 501 : MSDevice_ToC::setAwareness(double value) {
398 501 : if (value > 1.0 || value < 0.0) {
399 0 : std::stringstream ss;
400 0 : ss << "Truncating invalid value for awareness (" << value << ") to lie in [0,1].";
401 0 : WRITE_WARNING(ss.str());
402 : value = MAX2(0.0, MIN2(1.0, value));
403 0 : }
404 501 : if (myCurrentAwareness >= myLCAbstinence && value < myLCAbstinence) {
405 : // Awareness is now below LC abstinence level -> prevent deliberate LCs
406 4 : deactivateDeliberateLCs();
407 497 : } else if (myCurrentAwareness < myLCAbstinence && value >= myLCAbstinence) {
408 : // Awareness is now above LC abstinence level -> allow deliberate LCs
409 4 : resetDeliberateLCs();
410 : }
411 501 : myCurrentAwareness = value;
412 501 : myHolderMS->getDriverState()->setAwareness(value);
413 501 : }
414 :
415 :
416 : void
417 255 : MSDevice_ToC::setState(ToCState state) {
418 : #ifdef DEBUG_TOC
419 : std::cout << SIMTIME << " MSDevice_ToC::setState()" << std::endl;
420 : #endif
421 255 : if (myState == state) {
422 : // No state change
423 : return;
424 : }
425 :
426 255 : if (myState == MRM) {
427 : // reset the vehicle's maxAccel
428 35 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(myOriginalMaxAccel);
429 35 : resetDeliberateLCs();
430 220 : } else if (myState == PREPARING_TOC) {
431 76 : if (myOpenGapParams.active) {
432 : // Deactivate gap control at preparation phase end
433 2 : myHolderMS->getInfluencer().deactivateGapController();
434 : }
435 76 : if (state != MRM) {
436 : // Aborting preparation
437 45 : resetDeliberateLCs();
438 45 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(myOriginalMaxAccel);
439 : }
440 144 : } else if (state == PREPARING_TOC || state == MRM) {
441 : #ifdef DEBUG_TOC
442 : std::cout << " Entering ToC preparation... " << std::endl;
443 : #endif
444 : // Prevent lane changing during takeover preparation
445 82 : deactivateDeliberateLCs();
446 : // Store original value of maxAccel for restoring it after preparation phase
447 82 : myOriginalMaxAccel = myHolderMS->getCarFollowModel().getMaxAccel();
448 : // Impose acceleration limit during preparation
449 82 : myHolderMS->getSingularType().getCarFollowModel().setMaxAccel(MIN2(myMaxPreparationAccel, myOriginalMaxAccel));
450 : }
451 :
452 255 : if (myIssuedDynamicToC) {
453 : // Reset dynamic ToC flag
454 3 : myIssuedDynamicToC = false;
455 : }
456 :
457 255 : myState = state;
458 255 : if (myUseColorScheme) {
459 255 : setVehicleColor();
460 : }
461 : }
462 :
463 : void
464 255 : MSDevice_ToC::setVehicleColor() {
465 255 : const SUMOVehicleParameter& p = myHolder.getParameter();
466 255 : p.color = myColorScheme[myState];
467 255 : p.parametersSet |= VEHPARS_COLOR_SET;
468 255 : }
469 :
470 : void
471 8 : MSDevice_ToC::requestMRM() {
472 : // Remove any preparatory process
473 8 : descheduleToCPreparation();
474 : // .. and any recovery process
475 8 : descheduleRecovery();
476 : // ... and any pending ToC to manual
477 8 : descheduleToC();
478 : // Immediately trigger the MRM process
479 8 : triggerMRM(0);
480 8 : }
481 :
482 :
483 : void
484 123 : MSDevice_ToC::requestToC(SUMOTime timeTillMRM, SUMOTime responseTime) {
485 : #ifdef DEBUG_TOC
486 : std::cout << SIMTIME << " requestToC() for vehicle '" << myHolder.getID() << "', timeTillMRM=" << timeTillMRM << ", responseTime=" << responseTime << std::endl;
487 : #endif
488 123 : if (myState == AUTOMATED) {
489 : // Initialize preparation phase
490 76 : if (responseTime == -1000) {
491 : // Sample response time from distribution
492 4 : const double sample = sampleResponseTime(STEPS2TIME(timeTillMRM));
493 : // this needs to be a separate line because TIME2STEPS may otherwise do two calls to sampleResponseTime
494 4 : responseTime = TIME2STEPS(sample);
495 : }
496 :
497 : // Schedule ToC Event
498 76 : myTriggerToCCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::triggerDownwardToC);
499 76 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myTriggerToCCommand, SIMSTEP + responseTime);
500 :
501 : assert(myExecuteMRMCommand == nullptr);
502 : assert(myTriggerMRMCommand == nullptr);
503 76 : if (responseTime > timeTillMRM && myState != MRM) {
504 : // Schedule new MRM if driver response time is higher than permitted
505 51 : myTriggerMRMCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::triggerMRM);
506 51 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myTriggerMRMCommand, SIMSTEP + timeTillMRM);
507 : }
508 :
509 : // Start ToC preparation process
510 76 : myPrepareToCCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::ToCPreparationStep);
511 76 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myPrepareToCCommand, SIMSTEP + DELTA_T);
512 76 : setState(PREPARING_TOC);
513 76 : if (myOpenGapParams.active) {
514 : // Start gap controller
515 2 : double originalTau = myHolderMS->getCarFollowModel().getHeadwayTime();
516 2 : myHolderMS->getInfluencer().activateGapController(originalTau,
517 : myOpenGapParams.newTimeHeadway, myOpenGapParams.newSpaceHeadway, -1,
518 : myOpenGapParams.changeRate, myOpenGapParams.maxDecel);
519 : }
520 : // Record event
521 76 : if (generatesOutput()) {
522 75 : myEvents.push(std::make_pair(SIMSTEP, "TOR"));
523 75 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
524 75 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
525 : }
526 : } else {
527 : // Switch to automated mode is performed immediately
528 47 : if (timeTillMRM > 0) {
529 38 : std::stringstream ss;
530 114 : ss << "[t=" << SIMTIME << "] Positive transition time (" << STEPS2TIME(timeTillMRM) << "s.) for upward ToC of vehicle '" << myHolder.getID() << "' is ignored.";
531 38 : WRITE_WARNING(ss.str());
532 38 : }
533 47 : triggerUpwardToC(SIMSTEP + DELTA_T);
534 : }
535 123 : }
536 :
537 :
538 : SUMOTime
539 37 : MSDevice_ToC::triggerMRM(SUMOTime /* t */) {
540 : #ifdef DEBUG_TOC
541 : std::cout << SIMTIME << " triggerMRM() for vehicle '" << myHolder.getID() << "'" << std::endl;
542 : #endif
543 : // Clear ongoing MRM
544 37 : descheduleMRM();
545 :
546 : // Start MRM process
547 37 : if (myMRMSafeSpot != "") {
548 0 : SUMOVehicleParameter::Stop stop;
549 0 : MSStoppingPlace* s = MSNet::getInstance()->getStoppingPlace(myMRMSafeSpot, SUMO_TAG_PARKING_AREA);
550 0 : if (s == nullptr) {
551 0 : WRITE_WARNINGF(TL("Ignoring unknown safe spot '%' for vehicle '%'."), myMRMSafeSpot, myHolder.getID());
552 : } else {
553 : stop.parkingarea = myMRMSafeSpot;
554 0 : stop.parking = ParkingType::OFFROAD;
555 0 : stop.lane = s->getLane().getID();
556 0 : stop.endPos = s->getEndLanePosition();
557 0 : stop.startPos = s->getBeginLanePosition();
558 0 : stop.duration = myMRMSafeSpotDuration;
559 0 : myHolderMS->getSingularType().setDecel(myMRMDecel);
560 : std::string error;
561 0 : if (!myHolder.addStop(stop, error)) {
562 0 : WRITE_WARNING("Could not set safe spot '" + myMRMSafeSpot + "' for vehicle '" + myHolder.getID() + "'. " + error);
563 : }
564 : }
565 0 : } else {
566 37 : myExecuteMRMCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::MRMExecutionStep);
567 37 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myExecuteMRMCommand, SIMSTEP + DELTA_T);
568 : }
569 37 : if (myState == MANUAL || myState == RECOVERING) {
570 4 : switchHolderType(myAutomatedTypeID);
571 : }
572 37 : setState(MRM);
573 37 : setAwareness(1.);
574 :
575 : // Record event
576 37 : if (generatesOutput()) {
577 36 : myEvents.push(std::make_pair(SIMSTEP, "MRM"));
578 36 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
579 36 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
580 : }
581 :
582 37 : return 0;
583 : }
584 :
585 :
586 : SUMOTime
587 48 : MSDevice_ToC::triggerUpwardToC(SUMOTime /* t */) {
588 : #ifdef DEBUG_TOC
589 : std::cout << SIMTIME << " triggerUpwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
590 : #endif
591 48 : descheduleToC();
592 : // Eventually stop ToC preparation process
593 48 : descheduleToCPreparation();
594 : // Eventually abort MRM
595 48 : descheduleMRM();
596 : // Eventually abort awareness recovery process
597 48 : descheduleRecovery();
598 :
599 48 : if (myState == MANUAL || myState == RECOVERING) {
600 17 : switchHolderType(myAutomatedTypeID);
601 : }
602 48 : setAwareness(1.);
603 48 : setState(AUTOMATED);
604 :
605 : // Record event
606 48 : if (generatesOutput()) {
607 47 : myEvents.push(std::make_pair(SIMSTEP, "ToCup"));
608 47 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
609 47 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
610 : }
611 :
612 48 : return 0;
613 : }
614 :
615 :
616 : SUMOTime
617 49 : MSDevice_ToC::triggerDownwardToC(SUMOTime /* t */) {
618 : #ifdef DEBUG_TOC
619 : std::cout << SIMTIME << " triggerDownwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
620 : #endif
621 49 : descheduleToC();
622 : // Eventually stop ToC preparation process
623 49 : descheduleToCPreparation();
624 : // Eventually abort MRM
625 49 : descheduleMRM();
626 :
627 : #ifdef DEBUG_TOC
628 : std::cout << SIMTIME << " Initial awareness after ToC: " << myCurrentAwareness << std::endl;
629 : #endif
630 :
631 : // Start awareness recovery process
632 49 : myRecoverAwarenessCommand = new WrappingCommand<MSDevice_ToC>(this, &MSDevice_ToC::awarenessRecoveryStep);
633 49 : MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myRecoverAwarenessCommand, SIMSTEP + DELTA_T);
634 49 : setState(RECOVERING);
635 :
636 : // @todo: Sample initial awareness
637 49 : double initialAwareness = myInitialAwareness;
638 49 : setAwareness(initialAwareness);
639 :
640 49 : switchHolderType(myManualTypeID);
641 :
642 : // Record event
643 49 : if (generatesOutput()) {
644 48 : myEvents.push(std::make_pair(SIMSTEP, "ToCdown"));
645 48 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
646 48 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
647 : }
648 49 : return 0;
649 : }
650 :
651 : void
652 134 : MSDevice_ToC::descheduleMRM() {
653 : // Eventually abort scheduled MRM
654 134 : if (myTriggerMRMCommand != nullptr) {
655 : myTriggerMRMCommand->deschedule();
656 51 : myTriggerMRMCommand = nullptr;
657 : }
658 : // Eventually abort ongoing MRM
659 134 : if (myExecuteMRMCommand != nullptr) {
660 : myExecuteMRMCommand->deschedule();
661 35 : resetDeliberateLCs();
662 35 : myExecuteMRMCommand = nullptr;
663 : }
664 134 : }
665 :
666 :
667 : void
668 105 : MSDevice_ToC::descheduleToC() {
669 105 : if (myTriggerToCCommand != nullptr) {
670 : myTriggerToCCommand->deschedule();
671 76 : myTriggerToCCommand = nullptr;
672 : }
673 105 : }
674 :
675 : void
676 134 : MSDevice_ToC::descheduleToCPreparation() {
677 : // Eventually stop ToC preparation process
678 134 : if (myPrepareToCCommand != nullptr) {
679 : myPrepareToCCommand->deschedule();
680 76 : if (myState != MRM) {
681 47 : resetDeliberateLCs();
682 : }
683 76 : myPrepareToCCommand = nullptr;
684 : }
685 134 : }
686 :
687 : void
688 56 : MSDevice_ToC::descheduleRecovery() {
689 : // Eventually stop ToC preparation process
690 56 : if (myRecoverAwarenessCommand != nullptr) {
691 : myRecoverAwarenessCommand->deschedule();
692 4 : myRecoverAwarenessCommand = nullptr;
693 : }
694 56 : }
695 :
696 :
697 : void
698 70 : MSDevice_ToC::switchHolderType(const std::string& targetTypeID) {
699 : #ifdef DEBUG_TOC
700 : std::cout << SIMTIME << " Switching type of vehicle '" << myHolder.getID() << "' to '" << targetTypeID << "'" << std::endl;
701 : #endif
702 70 : MSVehicleType* targetType = MSNet::getInstance()->getVehicleControl().getVType(targetTypeID);
703 70 : if (targetType == nullptr) {
704 0 : WRITE_ERRORF(TL("vType '%' for vehicle '%' is not known."), targetType->getID(), myHolder.getID());
705 0 : return;
706 : }
707 70 : myHolderMS->replaceVehicleType(targetType);
708 : }
709 :
710 :
711 : SUMOTime
712 794 : MSDevice_ToC::ToCPreparationStep(SUMOTime /* t */) {
713 : #ifdef DEBUG_TOC
714 : std::cout << SIMTIME << " ToC preparation step for vehicle '" << myHolder.getID() << "'" << std::endl;
715 : #endif
716 794 : if (myState == PREPARING_TOC) {
717 765 : return DELTA_T;
718 : } else {
719 : #ifdef DEBUG_TOC
720 : std::cout << SIMTIME << " Aborting ToC preparation for vehicle '" << myHolder.getID() << "'" << std::endl;
721 : #endif
722 29 : descheduleToCPreparation();
723 29 : return 0;
724 : }
725 : }
726 :
727 :
728 : SUMOTime
729 1213 : MSDevice_ToC::MRMExecutionStep(SUMOTime t) {
730 1213 : deactivateDeliberateLCs();
731 1213 : const double currentSpeed = myHolderMS->getSpeed();
732 : #ifdef DEBUG_TOC
733 : std::cout << SIMTIME << " MRM step for vehicle '" << myHolder.getID() << "', currentSpeed=" << currentSpeed << std::endl;
734 : #endif
735 :
736 : // Induce slowdown with MRMDecel
737 : std::vector<std::pair<SUMOTime, double> > speedTimeLine;
738 1213 : const double nextSpeed = MAX2(0., currentSpeed - ACCEL2SPEED(myMRMDecel));
739 1213 : speedTimeLine.push_back(std::make_pair(t - DELTA_T, currentSpeed));
740 1213 : speedTimeLine.push_back(std::make_pair(t, nextSpeed));
741 1213 : myHolderMS->getInfluencer().setSpeedTimeLine(speedTimeLine);
742 :
743 1213 : if (myMRMKeepRight) {
744 : // Try to change to the right
745 : std::vector<std::pair<SUMOTime, int> > laneTimeLine;
746 34 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), 0));
747 34 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + 1, 0));
748 34 : myHolderMS->getInfluencer().setLaneTimeLine(laneTimeLine);
749 : // std::cout << "Keeping right..." << std::endl;
750 34 : }
751 :
752 1213 : if (myState == MRM) {
753 1213 : return DELTA_T;
754 : } else {
755 : #ifdef DEBUG_TOC
756 : std::cout << SIMTIME << " Aborting MRM for vehicle '" << myHolder.getID() << "'" << std::endl;
757 : #endif
758 0 : resetDeliberateLCs();
759 : return 0;
760 : }
761 1213 : }
762 :
763 :
764 : SUMOTime
765 367 : MSDevice_ToC::awarenessRecoveryStep(SUMOTime /* t */) {
766 : #ifdef DEBUG_TOC
767 : std::cout << SIMTIME << " Awareness recovery step for vehicle '" << myHolder.getID() << "'" << std::endl;
768 : #endif
769 : // Proceed with awareness recovery
770 367 : if (myCurrentAwareness < 1.0) {
771 689 : setAwareness(MIN2(1.0, myCurrentAwareness + TS * myRecoveryRate));
772 : }
773 :
774 : #ifdef DEBUG_TOC
775 : std::cout << SIMTIME << " currentAwareness = " << myCurrentAwareness << std::endl;
776 : #endif
777 :
778 367 : const bool awarenessRecoveryCompleted = myCurrentAwareness == 1.0;
779 367 : if (awarenessRecoveryCompleted) {
780 : #ifdef DEBUG_TOC
781 : std::cout << SIMTIME << " Awareness recovery completed for veh '" << myHolder.getID() << "'" << std::endl;
782 : #endif
783 45 : myRecoverAwarenessCommand->deschedule();
784 45 : myRecoverAwarenessCommand = nullptr;
785 45 : setState(MANUAL);
786 45 : return 0;
787 : }
788 322 : return DELTA_T;
789 : }
790 :
791 : bool
792 15687 : MSDevice_ToC::notifyMove(SUMOTrafficObject& /*veh*/,
793 : double /*oldPos*/,
794 : double /*newPos*/,
795 : double /*newSpeed*/) {
796 15687 : if (myState == AUTOMATED && checkDynamicToC()) {
797 : // Initiate a ToC
798 : // Record event
799 3 : if (generatesOutput()) {
800 3 : myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
801 3 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
802 3 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
803 : }
804 : // Leadtime for dynamic ToC is proportional to the time assumed for the dynamic ToC threshold
805 3 : const double leadTime = myDynamicToCThreshold * 1000 * DYNAMIC_TOC_LEADTIME_FACTOR;
806 3 : requestToC((SUMOTime) leadTime);
807 : // 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)
808 3 : myIssuedDynamicToC = true;
809 3 : myDynamicToCLane = myHolderMS->getLane()->getNumericalID();
810 15684 : } else if (myIssuedDynamicToC && myState == PREPARING_TOC && !checkDynamicToC()) {
811 : // Abort dynamic ToC, FIXME: This could abort an externally requested ToC in rare occasions... (needs test)
812 : // Record event
813 1 : if (generatesOutput()) {
814 1 : myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
815 1 : myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
816 1 : myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
817 : }
818 : // NOTE: This should not occur if lane changing is prevented during ToC preparation...
819 : // TODO: Reset response time to the original value (unnecessary if re-sampling for each call to requestToC)
820 1 : triggerUpwardToC(0);
821 : }
822 15687 : return true;
823 : }
824 :
825 : std::string
826 44415 : MSDevice_ToC::getParameter(const std::string& key) const {
827 44415 : if (key == "manualType") {
828 : return myManualTypeID;
829 42585 : } else if (key == "automatedType") {
830 : return myAutomatedTypeID;
831 40755 : } else if (key == "responseTime") {
832 1830 : return toString(STEPS2TIME(myResponseTime));
833 38925 : } else if (key == "recoveryRate") {
834 1830 : return toString(myRecoveryRate);
835 37095 : } else if (key == "initialAwareness") {
836 1830 : return toString(myInitialAwareness);
837 35265 : } else if (key == "mrmDecel") {
838 1830 : return toString(myMRMDecel);
839 33435 : } else if (key == "currentAwareness") {
840 15545 : return toString(myCurrentAwareness);
841 17890 : } else if (key == "lcAbstinence") {
842 10 : return toString(myLCAbstinence);
843 17880 : } else if (key == "state") {
844 15799 : return _2string(myState);
845 2081 : } else if (key == "holder") {
846 1830 : return myHolder.getID();
847 251 : } else if (key == "hasDynamicToC") {
848 0 : return toString(myDynamicToCActive);
849 251 : } else if (key == "dynamicToCThreshold") {
850 216 : return toString(myDynamicToCThreshold);
851 35 : } else if (key == "dynamicMRMProbability") {
852 10 : return toString(myMRMProbability);
853 25 : } else if (key == "mrmKeepRight") {
854 10 : return toString(myMRMKeepRight);
855 15 : } else if (key == "mrmSafeSpot") {
856 : return myMRMSafeSpot;
857 15 : } else if (key == "mrmSafeSpotDuration") {
858 0 : return toString(STEPS2TIME(myMRMSafeSpotDuration));
859 15 : } else if (key == "maxPreparationAccel") {
860 10 : return toString(myMaxPreparationAccel);
861 5 : } else if (key == "ogNewTimeHeadway") {
862 1 : return toString(myOpenGapParams.newTimeHeadway);
863 4 : } else if (key == "ogNewSpaceHeadway") {
864 2 : return toString(myOpenGapParams.newSpaceHeadway);
865 2 : } else if (key == "ogChangeRate") {
866 1 : return toString(myOpenGapParams.changeRate);
867 1 : } else if (key == "ogMaxDecel") {
868 1 : return toString(myOpenGapParams.maxDecel);
869 : }
870 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
871 : }
872 :
873 :
874 : void
875 132 : MSDevice_ToC::setParameter(const std::string& key, const std::string& value) {
876 : #ifdef DEBUG_TOC
877 : std::cout << SIMTIME << " MSDevice_ToC::setParameter(key=" << key << ", value=" << value << ")" << std::endl;
878 : #endif
879 132 : if (key == "manualType") {
880 0 : myManualTypeID = value;
881 0 : myColorScheme[MANUAL] = MSNet::getInstance()->getVehicleControl().getVType(myManualTypeID)->getColor();
882 0 : if (myState == MANUAL) {
883 0 : switchHolderType(value);
884 : }
885 132 : } else if (key == "automatedType") {
886 0 : myAutomatedTypeID = value;
887 0 : myColorScheme[AUTOMATED] = MSNet::getInstance()->getVehicleControl().getVType(myAutomatedTypeID)->getColor();
888 0 : if (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM) {
889 0 : switchHolderType(value);
890 : }
891 132 : } else if (key == "responseTime") {
892 0 : myResponseTime = TIME2STEPS(StringUtils::toDouble(value));
893 132 : } else if (key == "recoveryRate") {
894 0 : myRecoveryRate = StringUtils::toDouble(value);
895 132 : } else if (key == "initialAwareness") {
896 0 : myInitialAwareness = StringUtils::toDouble(value);
897 132 : } else if (key == "lcAbstinence") {
898 0 : myLCAbstinence = StringUtils::toDouble(value);
899 0 : if (isManuallyDriven()) {
900 0 : setAwareness(myCurrentAwareness); // to eventually trigger LC-prevention
901 : }
902 132 : } else if (key == "currentAwareness") {
903 0 : if (isManuallyDriven()) {
904 0 : setAwareness(StringUtils::toDouble(value));
905 : } else {
906 0 : WRITE_WARNING(TL("Setting device.toc.currentAwareness during automated mode has no effect."))
907 : }
908 132 : } else if (key == "mrmDecel") {
909 0 : myMRMDecel = StringUtils::toDouble(value);
910 132 : } else if (key == "requestToC") {
911 : // setting this magic parameter gives the interface for inducing a ToC
912 120 : const SUMOTime timeTillMRM = TIME2STEPS(StringUtils::toDouble(value));
913 120 : requestToC(timeTillMRM, myResponseTime);
914 12 : } else if (key == "requestMRM") {
915 : // setting this magic parameter gives the interface for inducing an MRM
916 8 : requestMRM();
917 4 : } else if (key == "awareness") {
918 : // setting this magic parameter gives the interface for setting the driverstate's awareness
919 0 : setAwareness(StringUtils::toDouble(value));
920 4 : } else if (key == "dynamicToCThreshold") {
921 0 : const double newValue = StringUtils::toDouble(value);
922 0 : if (newValue < 0) {
923 0 : WRITE_WARNINGF(TL("Value of dynamicToCThreshold must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
924 0 : } else if (newValue == 0) {
925 0 : myDynamicToCThreshold = newValue;
926 0 : myDynamicToCActive = false;
927 : } else {
928 0 : myDynamicToCThreshold = newValue;
929 0 : myDynamicToCActive = true;
930 : }
931 4 : } else if (key == "dynamicMRMProbability") {
932 0 : const double newValue = StringUtils::toDouble(value);
933 0 : if (newValue < 0) {
934 0 : WRITE_WARNINGF(TL("Value of dynamicMRMProbability must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
935 : } else {
936 0 : myMRMProbability = newValue;
937 : }
938 4 : } else if (key == "mrmKeepRight") {
939 0 : const bool newValue = StringUtils::toBool(value);
940 0 : myMRMKeepRight = newValue;
941 4 : } else if (key == "mrmSafeSpot") {
942 0 : myMRMSafeSpot = value;
943 4 : } else if (key == "mrmSafeSpotDuration") {
944 0 : myMRMSafeSpotDuration = TIME2STEPS(StringUtils::toDouble(value));
945 4 : } else if (key == "maxPreparationAccel") {
946 0 : const double newValue = StringUtils::toDouble(value);
947 0 : if (newValue < 0) {
948 0 : WRITE_WARNINGF(TL("Value of maxPreparationAccel must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
949 : } else {
950 0 : myMaxPreparationAccel = newValue;
951 : }
952 4 : } else if (key == "ogNewTimeHeadway") {
953 1 : const double newValue = StringUtils::toDouble(value);
954 1 : myOpenGapParams.newTimeHeadway = newValue;
955 1 : myOpenGapParams.active = true;
956 3 : } else if (key == "ogNewSpaceHeadway") {
957 1 : const double newValue = StringUtils::toDouble(value);
958 1 : myOpenGapParams.newSpaceHeadway = newValue;
959 1 : myOpenGapParams.active = true;
960 2 : } else if (key == "ogChangeRate") {
961 1 : const double newValue = StringUtils::toDouble(value);
962 1 : myOpenGapParams.changeRate = newValue;
963 1 : myOpenGapParams.active = true;
964 1 : } else if (key == "ogMaxDecel") {
965 1 : const double newValue = StringUtils::toDouble(value);
966 1 : myOpenGapParams.maxDecel = newValue;
967 1 : myOpenGapParams.active = true;
968 : } else {
969 0 : throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
970 : }
971 132 : }
972 :
973 :
974 : MSDevice_ToC::ToCState
975 0 : MSDevice_ToC::_2ToCState(const std::string& str) {
976 0 : if (str == "UNDEFINED") {
977 : return UNDEFINED;
978 0 : } else if (str == "MANUAL") {
979 : return MANUAL;
980 0 : } else if (str == "AUTOMATED") {
981 : return AUTOMATED;
982 0 : } else if (str == "PREPARING_TOC") {
983 : return PREPARING_TOC;
984 0 : } else if (str == "MRM") {
985 : return MRM;
986 0 : } else if (str == "RECOVERING") {
987 : return RECOVERING;
988 : } else {
989 0 : WRITE_WARNINGF(TL("Unknown ToCState '%'"), str);
990 0 : return UNDEFINED;
991 : }
992 : }
993 :
994 :
995 : std::string
996 15799 : MSDevice_ToC::_2string(ToCState state) {
997 15799 : if (state == UNDEFINED) {
998 0 : return "UNDEFINED";
999 : } else if (state == MANUAL) {
1000 8912 : return "MANUAL";
1001 : } else if (state == AUTOMATED) {
1002 4370 : return "AUTOMATED";
1003 : } else if (state == PREPARING_TOC) {
1004 881 : return "PREPARING_TOC";
1005 : } else if (state == MRM) {
1006 1254 : return "MRM";
1007 : } else if (state == RECOVERING) {
1008 382 : return "RECOVERING";
1009 : } else {
1010 0 : WRITE_WARNINGF(TL("Unknown ToCState '%'"), toString(state));
1011 0 : return toString(state);
1012 : }
1013 : }
1014 :
1015 :
1016 : void
1017 15513 : MSDevice_ToC::writeOutput() {
1018 15513 : if (!generatesOutput()) {
1019 : assert(myEvents.empty());
1020 : return;
1021 : }
1022 15720 : while (!myEvents.empty()) {
1023 : const std::pair<SUMOTime, std::string> e = myEvents.front(); // make a copy, it is used after pop
1024 : const std::pair<std::string, double>& l = myEventLanes.front();
1025 : const std::pair<double, double>& p = myEventXY.front();
1026 207 : myOutputFile->openTag(e.second);
1027 621 : myOutputFile->writeAttr("id", myHolder.getID()).writeAttr("t", STEPS2TIME(e.first));
1028 621 : myOutputFile->writeAttr("lane", l.first).writeAttr("lanePos", l.second);
1029 621 : myOutputFile->writeAttr("x", p.first).writeAttr("y", p.second);
1030 414 : myOutputFile->closeTag();
1031 : myEvents.pop();
1032 : myEventLanes.pop();
1033 : myEventXY.pop();
1034 :
1035 207 : if (e.second.compare("DYNTOR") == 0 && !myEvents.empty()) { // skip "TOR" events if duplicate of "DYNTOR"
1036 : std::pair<SUMOTime, std::string>& eNext = myEvents.front();
1037 4 : if (eNext.second.compare("TOR") == 0 && eNext.first == e.first) {
1038 : myEvents.pop();
1039 : myEventLanes.pop();
1040 : myEventXY.pop();
1041 : }
1042 : }
1043 : }
1044 : }
1045 :
1046 :
1047 : void
1048 40275 : MSDevice_ToC::cleanup() {
1049 : // Close xml bodies for all existing files
1050 : // TODO: Check if required
1051 40308 : for (auto& fn : createdOutputFiles) {
1052 33 : OutputDevice* file = &OutputDevice::getDevice(fn);
1053 66 : file->closeTag();
1054 : }
1055 40275 : }
1056 :
1057 :
1058 : void
1059 168 : MSDevice_ToC::resetDeliberateLCs() {
1060 168 : if (myPreviousLCMode != -1) {
1061 85 : myHolderMS->getInfluencer().setLaneChangeMode(myPreviousLCMode);
1062 : #ifdef DEBUG_TOC
1063 : std::cout << SIMTIME << " MSDevice_ToC::resetLCMode() restoring LC Mode of vehicle '" << myHolder.getID() << "' to " << myPreviousLCMode << std::endl;
1064 : #endif
1065 : }
1066 168 : myPreviousLCMode = -1;
1067 168 : }
1068 :
1069 :
1070 : void
1071 1299 : MSDevice_ToC::deactivateDeliberateLCs() {
1072 1299 : const int lcModeHolder = myHolderMS->getInfluencer().getLaneChangeMode();
1073 1299 : if (lcModeHolder != LCModeMRM) {
1074 85 : myPreviousLCMode = lcModeHolder;
1075 : #ifdef DEBUG_TOC
1076 : std::cout << SIMTIME << " MSDevice_ToC::setLCModeMRM() setting LC Mode of vehicle '" << myHolder.getID()
1077 : << "' from " << myPreviousLCMode << " to " << LCModeMRM << std::endl;
1078 : #endif
1079 85 : myHolderMS->getInfluencer().setLaneChangeMode(LCModeMRM);
1080 : }
1081 1299 : }
1082 :
1083 : bool
1084 0 : MSDevice_ToC::isManuallyDriven() {
1085 0 : return (myState == MANUAL || myState == RECOVERING);
1086 : }
1087 :
1088 : bool
1089 0 : MSDevice_ToC::isAutomated() {
1090 0 : return (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM);
1091 : }
1092 :
1093 : bool
1094 4305 : MSDevice_ToC::checkDynamicToC() {
1095 : #ifdef DEBUG_DYNAMIC_TOC
1096 : std::cout << SIMTIME << " # MSDevice_ToC::checkDynamicToC() for veh '" << myHolder.getID() << "'" << std::endl;
1097 : #endif
1098 4305 : if (!myDynamicToCActive) {
1099 : return false;
1100 : }
1101 : // The vehicle's current lane
1102 233 : const MSLane* currentLane = myHolderMS->getLane();
1103 :
1104 233 : if (currentLane->isInternal()) {
1105 : // Don't start or abort dynamic ToCs on internal lanes
1106 1 : return myIssuedDynamicToC;
1107 : }
1108 :
1109 232 : if (myIssuedDynamicToC) {
1110 : #ifdef DEBUG_DYNAMIC_TOC
1111 : std::cout << SIMTIME << " Dynamic ToC is ongoing." << std::endl;
1112 : #endif
1113 : // Dynamic ToC in progress. Resist to aborting it if lane was not changed.
1114 26 : if (myDynamicToCLane == currentLane->getNumericalID()) {
1115 : return true;
1116 : }
1117 : }
1118 : // Length for which the current route can be followed
1119 207 : const std::vector<MSVehicle::LaneQ>& bestLanes = myHolderMS->getBestLanes();
1120 : // Maximal distance for route continuation without LCs over the possible start lanes
1121 : double maximalContinuationDistance = 0;
1122 : // Distance for route continuation without LCs from the vehicle's current lane
1123 : double continuationDistanceOnCurrent = 0;
1124 : // Lane of the next stop
1125 : const MSLane* nextStopLane = nullptr;
1126 :
1127 207 : if (myHolderMS->hasStops()) {
1128 79 : nextStopLane = myHolderMS->getNextStop().lane;
1129 : }
1130 528 : for (auto& i : bestLanes) {
1131 400 : maximalContinuationDistance = MAX2(maximalContinuationDistance, i.length);
1132 400 : if (currentLane == i.lane) {
1133 207 : if (myHolderMS->hasStops()) {
1134 : // Check if the next stop lies on the route continuation from the current lane
1135 79 : for (MSLane* l : i.bestContinuations) {
1136 79 : if (l == nextStopLane) {
1137 : #ifdef DEBUG_DYNAMIC_TOC
1138 : std::cout << SIMTIME << " Stop found on the route continuation from the current lane. => No ToC" << std::endl;
1139 : #endif
1140 : // Stop found on the route continuation from the current lane => no ToC necessary
1141 : return false;
1142 : }
1143 : }
1144 : }
1145 128 : continuationDistanceOnCurrent = i.length;
1146 : }
1147 : }
1148 128 : if (continuationDistanceOnCurrent == maximalContinuationDistance) {
1149 : // There is no better lane than the current, hence no desire to change lanes,
1150 : // which the driver could pursue better than the automation => no reason for ToC.
1151 : return false;
1152 : }
1153 91 : const double distFromCurrent = continuationDistanceOnCurrent - myHolderMS->getPositionOnLane();
1154 91 : const double MRMDist = 0.5 * myHolderMS->getSpeed() * myHolderMS->getSpeed() / MAX2(myMRMDecel, 0.0001);
1155 91 : double distThreshold = myHolderMS->getSpeed() * myDynamicToCThreshold + MRMDist;
1156 : #ifdef DEBUG_DYNAMIC_TOC
1157 : std::cout << " speed=" << myHolderMS->getSpeed()
1158 : << ", distFromCurrent=" << distFromCurrent
1159 : << ", maximal dist=" << maximalContinuationDistance - myHolderMS->getPositionOnLane()
1160 : << ", distThreshold=" << distThreshold
1161 : << std::endl;
1162 : #endif
1163 :
1164 91 : if (myIssuedDynamicToC) {
1165 : // In case of an ongoing ToC, add an additional resistance to abort it.
1166 : // (The lane-check above does not capture lanes subsequent to the dynamic ToC lane)
1167 0 : distThreshold *= DYNAMIC_TOC_ABORT_RESISTANCE_FACTOR;
1168 : }
1169 :
1170 91 : if (distFromCurrent < distThreshold) {
1171 : // TODO: Make this more sophisticated in dealing with low speeds/stops and route ends
1172 : #ifdef DEBUG_DYNAMIC_TOC
1173 : std::cout << SIMTIME << " * distAlongBest is below threshold! *" << std::endl;
1174 : #endif
1175 : return true;
1176 : }
1177 :
1178 : return false;
1179 : }
1180 :
1181 : double
1182 4 : MSDevice_ToC::sampleResponseTime(double leadTime) const {
1183 : #ifdef DEBUG_DYNAMIC_TOC
1184 : std::cout << "sampleResponseTime() leadTime=" << leadTime << std::endl;
1185 : #endif
1186 : const double mean = responseTimeMean(leadTime);
1187 4 : const double var = interpolateVariance(leadTime, myMRMProbability);
1188 4 : double rt = RandHelper::randNorm(mean, var, &myResponseTimeRNG);
1189 : #ifdef DEBUG_DYNAMIC_TOC
1190 : std::cout << " mean=" << mean << ", variance=" << var << " => sampled responseTime=" << rt << std::endl;
1191 : #endif
1192 : int it_count = 0;
1193 4 : while (rt < 0 && it_count < MAX_RESPONSETIME_SAMPLE_TRIES) {
1194 0 : rt = RandHelper::randNorm(mean, var, &myResponseTimeRNG);
1195 0 : it_count++;
1196 : }
1197 4 : if (rt < 0) {
1198 : // Didn't generate a positive random response time => use mean
1199 : rt = mean;
1200 : }
1201 4 : return rt;
1202 : }
1203 :
1204 : double
1205 4 : MSDevice_ToC::interpolateVariance(double leadTime, double pMRM) {
1206 : #ifdef DEBUG_DYNAMIC_TOC
1207 : std::cout << "interpolateVariance() leadTime=" << leadTime << ", pMRM=" << pMRM << std::endl;
1208 : #endif
1209 : // Calculate indices for surrounding values in lookup tables
1210 :
1211 : // Find largest p_{i-1} < pMRM < p_{i}
1212 4 : const auto pi = std::lower_bound(lookupResponseTimeMRMProbs.begin(), lookupResponseTimeMRMProbs.end(), pMRM);
1213 4 : if (pi == lookupResponseTimeMRMProbs.end()) {
1214 : // requested probability lies outside lookup table.
1215 : // => return maximal variance value
1216 : return MAX_RESPONSETIME_VARIANCE;
1217 : }
1218 4 : const size_t pi1 = pi - lookupResponseTimeMRMProbs.begin();
1219 : assert(pi1 > 0);
1220 4 : const size_t pi0 = pi1 - 1;
1221 4 : const double cp = (pMRM - * (pi - 1)) / (*pi - * (pi - 1));
1222 :
1223 : #ifdef DEBUG_DYNAMIC_TOC
1224 : std::cout << " p[=" << pi0 << "]=" << *(pi - 1) << ", p[=" << pi1 << "]=" << *pi << " => cp=" << cp << std::endl;
1225 : #endif
1226 :
1227 : // Find largest p_{i-1} < pMRM < p_{i}
1228 4 : auto li = std::lower_bound(lookupResponseTimeLeadTimes.begin(), lookupResponseTimeLeadTimes.end(), leadTime);
1229 4 : if (li == lookupResponseTimeLeadTimes.begin()) {
1230 : // Given lead time smaller than minimal lookup-value.
1231 : // Use minimal value from lookup table instead
1232 0 : leadTime = *li;
1233 : li = lookupResponseTimeLeadTimes.begin() + 1;
1234 4 : } else if (li == lookupResponseTimeLeadTimes.end()) {
1235 : // Given leadTime exceeds values in lookup table
1236 : // => induce extrapolation
1237 : li--;
1238 : }
1239 : const size_t li1 = li - lookupResponseTimeLeadTimes.begin();
1240 : const size_t li0 = li1 - 1;
1241 4 : const double cl = (leadTime - * (li - 1)) / (*li - * (li - 1));
1242 :
1243 : #ifdef DEBUG_DYNAMIC_TOC
1244 : std::cout << " l[=" << li0 << "]=" << *(li - 1) << ", l[=" << li1 << "]=" << *li << " => cp=" << cl << std::endl;
1245 : #endif
1246 :
1247 : // 2D interpolation for variance
1248 : // First, interpolate (or extrapolate) variances along leadTimes
1249 4 : const double var00 = lookupResponseTimeVariances[pi0][li0];
1250 4 : const double var01 = lookupResponseTimeVariances[pi0][li1];
1251 4 : const double var10 = lookupResponseTimeVariances[pi1][li0];
1252 4 : const double var11 = lookupResponseTimeVariances[pi1][li1];
1253 4 : const double var_0 = var00 + (var01 - var00) * cl;
1254 4 : const double var_1 = var10 + (var11 - var10) * cl;
1255 : // From these, interpolate along the pMRM-axis
1256 4 : const double var = var_0 + (var_1 - var_0) * cp;
1257 : #ifdef DEBUG_DYNAMIC_TOC
1258 : std::cout << " var00=" << var00 << ", var01=" << var01 << " var10=" << var10 << ", var11=" << var11
1259 : << " var_0=" << var_0 << ", var_1=" << var_1 << ", var=" << var << std::endl;
1260 : #endif
1261 4 : return var;
1262 : }
1263 :
1264 : // Grid of the response time distribution.
1265 : // Generated by the script generateResponseTimeDistributions.py, see Appendix to TransAID Deliverable 3.1v2.
1266 : // Probability for an MRM to occur (start with 0.0, end with 0.5)
1267 : 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};
1268 : // Lead time grid
1269 : 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};
1270 :
1271 : // Variances of the response time distribution.
1272 : std::vector<std::vector<double> > MSDevice_ToC::lookupResponseTimeVariances = {
1273 : {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},
1274 : {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},
1275 : {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},
1276 : {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},
1277 : {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},
1278 : {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},
1279 : {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},
1280 : {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},
1281 : {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},
1282 : {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},
1283 : {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},
1284 : };
1285 :
1286 :
1287 : /****************************************************************************/
|