Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSDevice_ToC.cpp
Go to the documentation of this file.
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/****************************************************************************/
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>
33#include <microsim/MSNet.h>
34#include <microsim/MSLane.h>
35#include <microsim/MSVehicle.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// ---------------------------------------------------------------------------
95std::set<MSDevice_ToC*, ComparatorNumericalIdLess> MSDevice_ToC::myInstances = std::set<MSDevice_ToC*, ComparatorNumericalIdLess>();
96std::set<std::string> MSDevice_ToC::createdOutputFiles;
97int MSDevice_ToC::LCModeMRM = 768; // = 0b001100000000 - no autonomous changes, no speed adaptation
99
100
101// ===========================================================================
102// method definitions
103// ===========================================================================
104// ---------------------------------------------------------------------------
105// static initialisation methods
106// ---------------------------------------------------------------------------
107void
109 oc.addOptionSubTopic("ToC Device");
110 insertDefaultAssignmentOptions("toc", "ToC Device", oc);
111
112 oc.doRegister("device.toc.manualType", new Option_String());
113 oc.addDescription("device.toc.manualType", "ToC Device", TL("Vehicle type for manual driving regime."));
114 oc.doRegister("device.toc.automatedType", new Option_String());
115 oc.addDescription("device.toc.automatedType", "ToC Device", TL("Vehicle type for automated driving regime."));
116 oc.doRegister("device.toc.responseTime", new Option_Float(DEFAULT_RESPONSE_TIME));
117 oc.addDescription("device.toc.responseTime", "ToC Device", TL("Average response time needed by a driver to take back control."));
118 oc.doRegister("device.toc.recoveryRate", new Option_Float(DEFAULT_RECOVERY_RATE));
119 oc.addDescription("device.toc.recoveryRate", "ToC Device", TL("Recovery rate for the driver's awareness after a ToC."));
120 oc.doRegister("device.toc.lcAbstinence", new Option_Float(DEFAULT_LCABSTINENCE));
121 oc.addDescription("device.toc.lcAbstinence", "ToC Device", TL("Attention level below which a driver restrains from performing lane changes (value in [0,1])."));
122 oc.doRegister("device.toc.initialAwareness", new Option_Float(DEFAULT_INITIAL_AWARENESS));
123 oc.addDescription("device.toc.initialAwareness", "ToC Device", TL("Average awareness a driver has initially after a ToC (value in [0,1])."));
124 oc.doRegister("device.toc.mrmDecel", new Option_Float(DEFAULT_MRM_DECEL));
125 oc.addDescription("device.toc.mrmDecel", "ToC Device", TL("Deceleration rate applied during a 'minimum risk maneuver'."));
126 oc.doRegister("device.toc.dynamicToCThreshold", new Option_Float(DEFAULT_DYNAMIC_TOC_THRESHOLD));
127 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 oc.doRegister("device.toc.dynamicMRMProbability", new Option_Float(DEFAULT_MRM_PROBABILITY));
129 oc.addDescription("device.toc.dynamicMRMProbability", "ToC Device", TL("Probability that a dynamically triggered TOR is not answered in time."));
130 oc.doRegister("device.toc.mrmKeepRight", new Option_Bool(false));
131 oc.addDescription("device.toc.mrmKeepRight", "ToC Device", TL("If true, the vehicle tries to change to the right during an MRM."));
132 oc.doRegister("device.toc.mrmSafeSpot", new Option_String());
133 oc.addDescription("device.toc.mrmSafeSpot", "ToC Device", TL("If set, the vehicle tries to reach the given named stopping place during an MRM."));
134 oc.doRegister("device.toc.mrmSafeSpotDuration", new Option_Float(60.));
135 oc.addDescription("device.toc.mrmSafeSpotDuration", "ToC Device", TL("Duration the vehicle stays at the safe spot after an MRM."));
136 oc.doRegister("device.toc.maxPreparationAccel", new Option_Float(0.0));
137 oc.addDescription("device.toc.maxPreparationAccel", "ToC Device", TL("Maximal acceleration that may be applied during the ToC preparation phase."));
138 oc.doRegister("device.toc.ogNewTimeHeadway", new Option_Float(-1.0));
139 oc.addDescription("device.toc.ogNewTimeHeadway", "ToC Device", TL("Timegap for ToC preparation phase."));
140 oc.doRegister("device.toc.ogNewSpaceHeadway", new Option_Float(-1.0));
141 oc.addDescription("device.toc.ogNewSpaceHeadway", "ToC Device", TL("Additional spacing for ToC preparation phase."));
142 oc.doRegister("device.toc.ogMaxDecel", new Option_Float(-1.0));
143 oc.addDescription("device.toc.ogMaxDecel", "ToC Device", TL("Maximal deceleration applied for establishing increased gap in ToC preparation phase."));
144 oc.doRegister("device.toc.ogChangeRate", new Option_Float(-1.0));
145 oc.addDescription("device.toc.ogChangeRate", "ToC Device", TL("Rate of adaptation towards the increased headway during ToC preparation."));
146 oc.doRegister("device.toc.useColorScheme", new Option_Bool(true));
147 oc.addDescription("device.toc.useColorScheme", "ToC Device", TL("Whether a coloring scheme shall by applied to indicate the different ToC stages."));
148 oc.doRegister("device.toc.file", new Option_String());
149 oc.addDescription("device.toc.file", "ToC Device", TL("Switches on output by specifying an output filename."));
150}
151
152
153void
154MSDevice_ToC::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
156 if (equippedByDefaultAssignmentOptions(oc, "toc", v, false)) {
158 WRITE_WARNING(TL("ToC device is not supported by the mesoscopic simulation."));
159 return;
160 }
161 const std::string manualType = v.getStringParam("device.toc.manualType", true);
162 const std::string automatedType = v.getStringParam("device.toc.automatedType", true);
163 const SUMOTime responseTime = TIME2STEPS(v.getFloatParam("device.toc.responseTime"));
164 const double recoveryRate = v.getFloatParam("device.toc.recoveryRate");
165 const double lcAbstinence = v.getFloatParam("device.toc.lcAbstinence");
166 const double initialAwareness = v.getFloatParam("device.toc.initialAwareness");
167 const double mrmDecel = v.getFloatParam("device.toc.mrmDecel");
168 const bool useColoring = v.getBoolParam("device.toc.useColorScheme");
169 const std::string file = v.getStringParam("device.toc.file");
170 const OpenGapParams ogp = getOpenGapParams(v);
171 const double dynamicToCThreshold = v.getFloatParam("device.toc.dynamicToCThreshold");
172 const double dynamicMRMProbability = getDynamicMRMProbability(v);
173 const bool mrmKeepRight = v.getBoolParam("device.toc.mrmKeepRight");
174 const std::string mrmSafeSpot = v.getStringParam("device.toc.mrmSafeSpot");
175 const SUMOTime mrmSafeSpotDuration = TIME2STEPS(v.getFloatParam("device.toc.mrmSafeSpotDuration"));
176 const double maxPreparationAccel = v.getFloatParam("device.toc.maxPreparationAccel");
177 // build the device
178 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 mrmSafeSpot, mrmSafeSpotDuration, useColoring, ogp);
183 into.push_back(device);
184 }
185}
186
187
188double
190 double pMRM = v.getFloatParam("device.toc.dynamicMRMProbability");
191 if (pMRM < 0 || pMRM > 0.5) {
192 const double pMRMTrunc = MAX2(0.0, MIN2(0.5, pMRM));
193 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
202 double timegap = v.getFloatParam("device.toc.ogNewTimeHeadway");
203 double spacing = v.getFloatParam("device.toc.ogNewSpaceHeadway");
204 double changeRate = v.getFloatParam("device.toc.ogChangeRate");
205 double maxDecel = v.getFloatParam("device.toc.ogMaxDecel");
206 bool specifiedAny = false;
207
208 if (changeRate == -1.0) {
209 changeRate = DEFAULT_OPENGAP_CHANGERATE;
210 } else {
211 specifiedAny = true;
212 }
213 if (maxDecel == -1.0) {
214 maxDecel = DEFAULT_OPENGAP_MAXDECEL;
215 } else {
216 specifiedAny = true;
217 }
218 if (specifiedAny && timegap == -1 && spacing == -1) {
219 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 if (timegap == -1) {
222 timegap = DEFAULT_OPENGAP_TIMEGAP;
223 } else {
224 specifiedAny = true;
225 }
226 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 return OpenGapParams(timegap, spacing, changeRate, maxDecel, specifiedAny);
240}
241
242// ---------------------------------------------------------------------------
243// MSDevice_ToC-methods
244// ---------------------------------------------------------------------------
245MSDevice_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 bool mrmKeepRight, const std::string& mrmSafeSpot, SUMOTime mrmSafeSpotDuration, bool useColorScheme, OpenGapParams ogp) :
250 MSVehicleDevice(holder, id),
251 myManualTypeID(manualType),
252 myAutomatedTypeID(automatedType),
253 myResponseTime(responseTime),
254 myRecoveryRate(recoveryRate),
255 myLCAbstinence(lcAbstinence),
256 myInitialAwareness(initialAwareness),
257 myMRMDecel(mrmDecel),
258 myCurrentAwareness(1.),
259 myUseColorScheme(useColorScheme),
260 myTriggerMRMCommand(nullptr),
261 myTriggerToCCommand(nullptr),
262 myRecoverAwarenessCommand(nullptr),
263 myExecuteMRMCommand(nullptr),
264 myPrepareToCCommand(nullptr),
265 myOutputFile(nullptr),
266 myEvents(),
267 myEventLanes(),
268 myEventXY(),
269 myPreviousLCMode(-1),
270 myOpenGapParams(ogp),
271 myDynamicToCThreshold(dynamicToCThreshold),
272 myMRMProbability(dynamicMRMProbability),
273 myDynamicToCActive(dynamicToCThreshold > 0),
274 myIssuedDynamicToC(false),
275 myDynamicToCLane(-1),
276 myMRMKeepRight(mrmKeepRight),
277 myMRMSafeSpot(mrmSafeSpot),
278 myMRMSafeSpotDuration(mrmSafeSpotDuration),
279 myMaxPreparationAccel(maxPreparationAccel),
280 myOriginalMaxAccel(-1) {
281 // Take care! Holder is currently being constructed. Cast occurs before completion.
282 myHolderMS = static_cast<MSVehicle*>(&holder);
283
284 if (outputFilename != "") {
285 myOutputFile = &OutputDevice::getDevice(outputFilename);
286 // TODO: make xsd, include header
287 // myOutputFile.writeXMLHeader("ToCDeviceLog", "ToCDeviceLog.xsd");
288 if (createdOutputFiles.count(outputFilename) == 0) {
289 myOutputFile->writeXMLHeader("ToCDeviceLog", "");
290 createdOutputFiles.insert(outputFilename);
291 }
292 }
293
294 // Check if the given vTypes for the ToC Device are vTypeDistributions
296 const bool automatedVTypeIsDist = vehCtrl.hasVTypeDistribution(myAutomatedTypeID);
297 const bool manualVTypeIsDist = vehCtrl.hasVTypeDistribution(myManualTypeID);
298
299 // Check if the vType of the holder matches one of the given vTypes
300 std::string holderVTypeID = holder.getVehicleType().getID();
301 if (holderVTypeID == myManualTypeID) {
303 } else if (holderVTypeID == myAutomatedTypeID) {
305 } else if (manualVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myManualTypeID) > 0) {
306 // Holder type id is from the given manual type distribution.
308 myManualTypeID = holderVTypeID;
309 } else if (automatedVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myAutomatedTypeID) > 0) {
310 // Holder type id is from the given automated type distribution.
312 myAutomatedTypeID = holderVTypeID;
313 } else {
314 throw ProcessError("Vehicle type of vehicle '" + holder.getID() + "' ('" +
315 holder.getVehicleType().getID() + "') must coincide with manualType ('" +
316 manualType + "') or automatedType ('" + automatedType +
317 "') specified for its ToC-device (or drawn from the specified vTypeDistributions).");
318 }
319 if (!vehCtrl.hasVType(myAutomatedTypeID)) {
320 throw ProcessError("The automated vehicle type '" + myAutomatedTypeID +
321 "' of vehicle '" + holder.getID() + "' is not known.");
322 }
323 if (!vehCtrl.hasVType(myManualTypeID)) {
324 throw ProcessError("The manual vehicle type '" + myManualTypeID +
325 "' of vehicle '" + holder.getID() + "' is not known.");
326 }
327
328 // Eventually instantiate given vTypes from distributions
329 if (myState == ToCState::MANUAL && automatedVTypeIsDist) {
331 } else if (myState == ToCState::AUTOMATED && manualVTypeIsDist) {
333 }
334
335 // register at static instance container
336 myInstances.insert(this);
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}
359
360
361
362void
364 //RGBColor(red, green, blue)
367 myColorScheme[PREPARING_TOC] = RGBColor(200, 200, 250); // light blue
368 myColorScheme[MRM] = RGBColor(250, 50, 50); // red
369 myColorScheme[RECOVERING] = RGBColor(250, 210, 150); // light yellow
370 myColorScheme[UNDEFINED] = RGBColor(150, 150, 150); // gray
371}
372
373
375 // unregister from static instance container
376 myInstances.erase(this);
377 // deschedule commands associated to this device
378 if (myTriggerMRMCommand != nullptr) {
380 }
381 if (myTriggerToCCommand != nullptr) {
383 }
384 if (myRecoverAwarenessCommand != nullptr) {
386 }
387 if (myExecuteMRMCommand != nullptr) {
390 }
391 if (myPrepareToCCommand != nullptr) {
393 }
394}
395
396void
398 if (value > 1.0 || value < 0.0) {
399 std::stringstream ss;
400 ss << "Truncating invalid value for awareness (" << value << ") to lie in [0,1].";
401 WRITE_WARNING(ss.str());
402 value = MAX2(0.0, MIN2(1.0, value));
403 }
405 // Awareness is now below LC abstinence level -> prevent deliberate LCs
407 } else if (myCurrentAwareness < myLCAbstinence && value >= myLCAbstinence) {
408 // Awareness is now above LC abstinence level -> allow deliberate LCs
410 }
411 myCurrentAwareness = value;
412 myHolderMS->getDriverState()->setAwareness(value);
413}
414
415
416void
418#ifdef DEBUG_TOC
419 std::cout << SIMTIME << " MSDevice_ToC::setState()" << std::endl;
420#endif
421 if (myState == state) {
422 // No state change
423 return;
424 }
425
426 if (myState == MRM) {
427 // reset the vehicle's maxAccel
430 } else if (myState == PREPARING_TOC) {
432 // Deactivate gap control at preparation phase end
434 }
435 if (state != MRM) {
436 // Aborting preparation
439 }
440 } 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
446 // Store original value of maxAccel for restoring it after preparation phase
448 // Impose acceleration limit during preparation
450 }
451
452 if (myIssuedDynamicToC) {
453 // Reset dynamic ToC flag
454 myIssuedDynamicToC = false;
455 }
456
457 myState = state;
458 if (myUseColorScheme) {
460 }
461}
462
463void
469
470void
472 // Remove any preparatory process
474 // .. and any recovery process
476 // ... and any pending ToC to manual
478 // Immediately trigger the MRM process
479 triggerMRM(0);
480}
481
482
483void
484MSDevice_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 if (myState == AUTOMATED) {
489 // Initialize preparation phase
490 if (responseTime == -1000) {
491 // Sample response time from distribution
492 const double sample = sampleResponseTime(STEPS2TIME(timeTillMRM));
493 // this needs to be a separate line because TIME2STEPS may otherwise do two calls to sampleResponseTime
494 responseTime = TIME2STEPS(sample);
495 }
496
497 // Schedule ToC Event
500
501 assert(myExecuteMRMCommand == nullptr);
502 assert(myTriggerMRMCommand == nullptr);
503 if (responseTime > timeTillMRM && myState != MRM) {
504 // Schedule new MRM if driver response time is higher than permitted
507 }
508
509 // Start ToC preparation process
514 // Start gap controller
515 double originalTau = myHolderMS->getCarFollowModel().getHeadwayTime();
519 }
520 // Record event
521 if (generatesOutput()) {
522 myEvents.push(std::make_pair(SIMSTEP, "TOR"));
523 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
524 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 if (timeTillMRM > 0) {
529 std::stringstream ss;
530 ss << "[t=" << SIMTIME << "] Positive transition time (" << STEPS2TIME(timeTillMRM) << "s.) for upward ToC of vehicle '" << myHolder.getID() << "' is ignored.";
531 WRITE_WARNING(ss.str());
532 }
534 }
535}
536
537
540#ifdef DEBUG_TOC
541 std::cout << SIMTIME << " triggerMRM() for vehicle '" << myHolder.getID() << "'" << std::endl;
542#endif
543 // Clear ongoing MRM
545
546 // Start MRM process
547 if (myMRMSafeSpot != "") {
550 if (s == nullptr) {
551 WRITE_WARNINGF(TL("Ignoring unknown safe spot '%' for vehicle '%'."), myMRMSafeSpot, myHolder.getID());
552 } else {
555 stop.lane = s->getLane().getID();
556 stop.endPos = s->getEndLanePosition();
557 stop.startPos = s->getBeginLanePosition();
560 std::string error;
561 if (!myHolder.addStop(stop, error)) {
562 WRITE_WARNING("Could not set safe spot '" + myMRMSafeSpot + "' for vehicle '" + myHolder.getID() + "'. " + error);
563 }
564 }
565 } else {
568 }
569 if (myState == MANUAL || myState == RECOVERING) {
571 }
572 setState(MRM);
573 setAwareness(1.);
574
575 // Record event
576 if (generatesOutput()) {
577 myEvents.push(std::make_pair(SIMSTEP, "MRM"));
578 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
579 myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
580 }
581
582 return 0;
583}
584
585
588#ifdef DEBUG_TOC
589 std::cout << SIMTIME << " triggerUpwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
590#endif
592 // Eventually stop ToC preparation process
594 // Eventually abort MRM
596 // Eventually abort awareness recovery process
598
599 if (myState == MANUAL || myState == RECOVERING) {
601 }
602 setAwareness(1.);
604
605 // Record event
606 if (generatesOutput()) {
607 myEvents.push(std::make_pair(SIMSTEP, "ToCup"));
608 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
609 myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
610 }
611
612 return 0;
613}
614
615
618#ifdef DEBUG_TOC
619 std::cout << SIMTIME << " triggerDownwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
620#endif
622 // Eventually stop ToC preparation process
624 // Eventually abort MRM
626
627#ifdef DEBUG_TOC
628 std::cout << SIMTIME << " Initial awareness after ToC: " << myCurrentAwareness << std::endl;
629#endif
630
631 // Start awareness recovery process
635
636 // @todo: Sample initial awareness
637 double initialAwareness = myInitialAwareness;
638 setAwareness(initialAwareness);
639
641
642 // Record event
643 if (generatesOutput()) {
644 myEvents.push(std::make_pair(SIMSTEP, "ToCdown"));
645 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
646 myEventXY.push(std::make_pair(myHolder.getPosition().x(), myHolder.getPosition().y())); // add (x, y) position
647 }
648 return 0;
649}
650
651void
653 // Eventually abort scheduled MRM
654 if (myTriggerMRMCommand != nullptr) {
656 myTriggerMRMCommand = nullptr;
657 }
658 // Eventually abort ongoing MRM
659 if (myExecuteMRMCommand != nullptr) {
662 myExecuteMRMCommand = nullptr;
663 }
664}
665
666
667void
674
675void
677 // Eventually stop ToC preparation process
678 if (myPrepareToCCommand != nullptr) {
680 if (myState != MRM) {
682 }
683 myPrepareToCCommand = nullptr;
684 }
685}
686
687void
689 // Eventually stop ToC preparation process
690 if (myRecoverAwarenessCommand != nullptr) {
693 }
694}
695
696
697void
698MSDevice_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 MSVehicleType* targetType = MSNet::getInstance()->getVehicleControl().getVType(targetTypeID);
703 if (targetType == nullptr) {
704 WRITE_ERRORF(TL("vType '%' for vehicle '%' is not known."), targetType->getID(), myHolder.getID());
705 return;
706 }
707 myHolderMS->replaceVehicleType(targetType);
708}
709
710
713#ifdef DEBUG_TOC
714 std::cout << SIMTIME << " ToC preparation step for vehicle '" << myHolder.getID() << "'" << std::endl;
715#endif
716 if (myState == PREPARING_TOC) {
717 return DELTA_T;
718 } else {
719#ifdef DEBUG_TOC
720 std::cout << SIMTIME << " Aborting ToC preparation for vehicle '" << myHolder.getID() << "'" << std::endl;
721#endif
723 return 0;
724 }
725}
726
727
731 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 const double nextSpeed = MAX2(0., currentSpeed - ACCEL2SPEED(myMRMDecel));
739 speedTimeLine.push_back(std::make_pair(t - DELTA_T, currentSpeed));
740 speedTimeLine.push_back(std::make_pair(t, nextSpeed));
741 myHolderMS->getInfluencer().setSpeedTimeLine(speedTimeLine);
742
743 if (myMRMKeepRight) {
744 // Try to change to the right
745 std::vector<std::pair<SUMOTime, int> > laneTimeLine;
746 laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), 0));
747 laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + 1, 0));
749// std::cout << "Keeping right..." << std::endl;
750 }
751
752 if (myState == MRM) {
753 return DELTA_T;
754 } else {
755#ifdef DEBUG_TOC
756 std::cout << SIMTIME << " Aborting MRM for vehicle '" << myHolder.getID() << "'" << std::endl;
757#endif
759 return 0;
760 }
761}
762
763
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 if (myCurrentAwareness < 1.0) {
772 }
773
774#ifdef DEBUG_TOC
775 std::cout << SIMTIME << " currentAwareness = " << myCurrentAwareness << std::endl;
776#endif
777
778 const bool awarenessRecoveryCompleted = myCurrentAwareness == 1.0;
779 if (awarenessRecoveryCompleted) {
780#ifdef DEBUG_TOC
781 std::cout << SIMTIME << " Awareness recovery completed for veh '" << myHolder.getID() << "'" << std::endl;
782#endif
786 return 0;
787 }
788 return DELTA_T;
789}
790
791bool
793 double /*oldPos*/,
794 double /*newPos*/,
795 double /*newSpeed*/) {
796 if (myState == AUTOMATED && checkDynamicToC()) {
797 // Initiate a ToC
798 // Record event
799 if (generatesOutput()) {
800 myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
801 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
802 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 const double leadTime = myDynamicToCThreshold * 1000 * DYNAMIC_TOC_LEADTIME_FACTOR;
806 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 myIssuedDynamicToC = true;
811 // Abort dynamic ToC, FIXME: This could abort an externally requested ToC in rare occasions... (needs test)
812 // Record event
813 if (generatesOutput()) {
814 myEvents.push(std::make_pair(SIMSTEP, "DYNTOR"));
815 myEventLanes.push(std::make_pair(myHolder.getLane()->getID(), myHolder.getPositionOnLane())); // add lane and lanepos
816 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)
821 }
822 return true;
823}
824
825std::string
826MSDevice_ToC::getParameter(const std::string& key) const {
827 if (key == "manualType") {
828 return myManualTypeID;
829 } else if (key == "automatedType") {
830 return myAutomatedTypeID;
831 } else if (key == "responseTime") {
833 } else if (key == "recoveryRate") {
834 return toString(myRecoveryRate);
835 } else if (key == "initialAwareness") {
837 } else if (key == "mrmDecel") {
838 return toString(myMRMDecel);
839 } else if (key == "currentAwareness") {
841 } else if (key == "lcAbstinence") {
842 return toString(myLCAbstinence);
843 } else if (key == "state") {
844 return _2string(myState);
845 } else if (key == "holder") {
846 return myHolder.getID();
847 } else if (key == "hasDynamicToC") {
849 } else if (key == "dynamicToCThreshold") {
851 } else if (key == "dynamicMRMProbability") {
853 } else if (key == "mrmKeepRight") {
854 return toString(myMRMKeepRight);
855 } else if (key == "mrmSafeSpot") {
856 return myMRMSafeSpot;
857 } else if (key == "mrmSafeSpotDuration") {
859 } else if (key == "maxPreparationAccel") {
861 } else if (key == "ogNewTimeHeadway") {
863 } else if (key == "ogNewSpaceHeadway") {
865 } else if (key == "ogChangeRate") {
867 } else if (key == "ogMaxDecel") {
869 }
870 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
871}
872
873
874void
875MSDevice_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 if (key == "manualType") {
880 myManualTypeID = value;
882 if (myState == MANUAL) {
883 switchHolderType(value);
884 }
885 } else if (key == "automatedType") {
886 myAutomatedTypeID = value;
888 if (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM) {
889 switchHolderType(value);
890 }
891 } else if (key == "responseTime") {
893 } else if (key == "recoveryRate") {
895 } else if (key == "initialAwareness") {
897 } else if (key == "lcAbstinence") {
899 if (isManuallyDriven()) {
900 setAwareness(myCurrentAwareness); // to eventually trigger LC-prevention
901 }
902 } else if (key == "currentAwareness") {
903 if (isManuallyDriven()) {
905 } else {
906 WRITE_WARNING(TL("Setting device.toc.currentAwareness during automated mode has no effect."))
907 }
908 } else if (key == "mrmDecel") {
910 } else if (key == "requestToC") {
911 // setting this magic parameter gives the interface for inducing a ToC
912 const SUMOTime timeTillMRM = TIME2STEPS(StringUtils::toDouble(value));
913 requestToC(timeTillMRM, myResponseTime);
914 } else if (key == "requestMRM") {
915 // setting this magic parameter gives the interface for inducing an MRM
916 requestMRM();
917 } else if (key == "awareness") {
918 // setting this magic parameter gives the interface for setting the driverstate's awareness
920 } else if (key == "dynamicToCThreshold") {
921 const double newValue = StringUtils::toDouble(value);
922 if (newValue < 0) {
923 WRITE_WARNINGF(TL("Value of dynamicToCThreshold must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
924 } else if (newValue == 0) {
925 myDynamicToCThreshold = newValue;
926 myDynamicToCActive = false;
927 } else {
928 myDynamicToCThreshold = newValue;
929 myDynamicToCActive = true;
930 }
931 } else if (key == "dynamicMRMProbability") {
932 const double newValue = StringUtils::toDouble(value);
933 if (newValue < 0) {
934 WRITE_WARNINGF(TL("Value of dynamicMRMProbability must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
935 } else {
936 myMRMProbability = newValue;
937 }
938 } else if (key == "mrmKeepRight") {
939 const bool newValue = StringUtils::toBool(value);
940 myMRMKeepRight = newValue;
941 } else if (key == "mrmSafeSpot") {
942 myMRMSafeSpot = value;
943 } else if (key == "mrmSafeSpotDuration") {
945 } else if (key == "maxPreparationAccel") {
946 const double newValue = StringUtils::toDouble(value);
947 if (newValue < 0) {
948 WRITE_WARNINGF(TL("Value of maxPreparationAccel must be non-negative. (Given value % for vehicle % is ignored)"), value, myHolderMS->getID());
949 } else {
950 myMaxPreparationAccel = newValue;
951 }
952 } else if (key == "ogNewTimeHeadway") {
953 const double newValue = StringUtils::toDouble(value);
955 myOpenGapParams.active = true;
956 } else if (key == "ogNewSpaceHeadway") {
957 const double newValue = StringUtils::toDouble(value);
959 myOpenGapParams.active = true;
960 } else if (key == "ogChangeRate") {
961 const double newValue = StringUtils::toDouble(value);
962 myOpenGapParams.changeRate = newValue;
963 myOpenGapParams.active = true;
964 } else if (key == "ogMaxDecel") {
965 const double newValue = StringUtils::toDouble(value);
966 myOpenGapParams.maxDecel = newValue;
967 myOpenGapParams.active = true;
968 } else {
969 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
970 }
971}
972
973
975MSDevice_ToC::_2ToCState(const std::string& str) {
976 if (str == "UNDEFINED") {
977 return UNDEFINED;
978 } else if (str == "MANUAL") {
979 return MANUAL;
980 } else if (str == "AUTOMATED") {
981 return AUTOMATED;
982 } else if (str == "PREPARING_TOC") {
983 return PREPARING_TOC;
984 } else if (str == "MRM") {
985 return MRM;
986 } else if (str == "RECOVERING") {
987 return RECOVERING;
988 } else {
989 WRITE_WARNINGF(TL("Unknown ToCState '%'"), str);
990 return UNDEFINED;
991 }
992}
993
994
995std::string
997 if (state == UNDEFINED) {
998 return "UNDEFINED";
999 } else if (state == MANUAL) {
1000 return "MANUAL";
1001 } else if (state == AUTOMATED) {
1002 return "AUTOMATED";
1003 } else if (state == PREPARING_TOC) {
1004 return "PREPARING_TOC";
1005 } else if (state == MRM) {
1006 return "MRM";
1007 } else if (state == RECOVERING) {
1008 return "RECOVERING";
1009 } else {
1010 WRITE_WARNINGF(TL("Unknown ToCState '%'"), toString(state));
1011 return toString(state);
1012 }
1013}
1014
1015
1016void
1018 if (!generatesOutput()) {
1019 assert(myEvents.empty());
1020 return;
1021 }
1022 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 myOutputFile->openTag(e.second);
1027 myOutputFile->writeAttr("id", myHolder.getID()).writeAttr("t", STEPS2TIME(e.first));
1028 myOutputFile->writeAttr("lane", l.first).writeAttr("lanePos", l.second);
1029 myOutputFile->writeAttr("x", p.first).writeAttr("y", p.second);
1031 myEvents.pop();
1032 myEventLanes.pop();
1033 myEventXY.pop();
1034
1035 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 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
1047void
1049 // Close xml bodies for all existing files
1050 // TODO: Check if required
1051 for (auto& fn : createdOutputFiles) {
1053 file->closeTag();
1054 }
1055}
1056
1057
1058void
1060 if (myPreviousLCMode != -1) {
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 myPreviousLCMode = -1;
1067}
1068
1069
1070void
1072 const int lcModeHolder = myHolderMS->getInfluencer().getLaneChangeMode();
1073 if (lcModeHolder != LCModeMRM) {
1074 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
1080 }
1081}
1082
1083bool
1087
1088bool
1092
1093bool
1095#ifdef DEBUG_DYNAMIC_TOC
1096 std::cout << SIMTIME << " # MSDevice_ToC::checkDynamicToC() for veh '" << myHolder.getID() << "'" << std::endl;
1097#endif
1098 if (!myDynamicToCActive) {
1099 return false;
1100 }
1101 // The vehicle's current lane
1102 const MSLane* currentLane = myHolderMS->getLane();
1103
1104 if (currentLane->isInternal()) {
1105 // Don't start or abort dynamic ToCs on internal lanes
1106 return myIssuedDynamicToC;
1107 }
1108
1109 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 if (myDynamicToCLane == currentLane->getNumericalID()) {
1115 return true;
1116 }
1117 }
1118 // Length for which the current route can be followed
1119 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 if (myHolderMS->hasStops()) {
1128 nextStopLane = myHolderMS->getNextStop().lane;
1129 }
1130 for (auto& i : bestLanes) {
1131 maximalContinuationDistance = MAX2(maximalContinuationDistance, i.length);
1132 if (currentLane == i.lane) {
1133 if (myHolderMS->hasStops()) {
1134 // Check if the next stop lies on the route continuation from the current lane
1135 for (MSLane* l : i.bestContinuations) {
1136 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 continuationDistanceOnCurrent = i.length;
1146 }
1147 }
1148 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 const double distFromCurrent = continuationDistanceOnCurrent - myHolderMS->getPositionOnLane();
1154 const double MRMDist = 0.5 * myHolderMS->getSpeed() * myHolderMS->getSpeed() / MAX2(myMRMDecel, 0.0001);
1155 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 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 distThreshold *= DYNAMIC_TOC_ABORT_RESISTANCE_FACTOR;
1168 }
1169
1170 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
1181double
1182MSDevice_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 const double var = interpolateVariance(leadTime, myMRMProbability);
1188 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 while (rt < 0 && it_count < MAX_RESPONSETIME_SAMPLE_TRIES) {
1194 rt = RandHelper::randNorm(mean, var, &myResponseTimeRNG);
1195 it_count++;
1196 }
1197 if (rt < 0) {
1198 // Didn't generate a positive random response time => use mean
1199 rt = mean;
1200 }
1201 return rt;
1202}
1203
1204double
1205MSDevice_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 const auto pi = std::lower_bound(lookupResponseTimeMRMProbs.begin(), lookupResponseTimeMRMProbs.end(), pMRM);
1213 if (pi == lookupResponseTimeMRMProbs.end()) {
1214 // requested probability lies outside lookup table.
1215 // => return maximal variance value
1217 }
1218 const size_t pi1 = pi - lookupResponseTimeMRMProbs.begin();
1219 assert(pi1 > 0);
1220 const size_t pi0 = pi1 - 1;
1221 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 auto li = std::lower_bound(lookupResponseTimeLeadTimes.begin(), lookupResponseTimeLeadTimes.end(), leadTime);
1229 if (li == lookupResponseTimeLeadTimes.begin()) {
1230 // Given lead time smaller than minimal lookup-value.
1231 // Use minimal value from lookup table instead
1232 leadTime = *li;
1233 li = lookupResponseTimeLeadTimes.begin() + 1;
1234 } 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 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 const double var00 = lookupResponseTimeVariances[pi0][li0];
1250 const double var01 = lookupResponseTimeVariances[pi0][li1];
1251 const double var10 = lookupResponseTimeVariances[pi1][li0];
1252 const double var11 = lookupResponseTimeVariances[pi1][li1];
1253 const double var_0 = var00 + (var01 - var00) * cl;
1254 const double var_1 = var10 + (var11 - var10) * cl;
1255 // From these, interpolate along the pMRM-axis
1256 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 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)
1267std::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
1269std::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.
1272std::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/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEFAULT_DYNAMIC_TOC_THRESHOLD
#define DEFAULT_RESPONSE_TIME
#define DEFAULT_OPENGAP_SPACING
#define DEFAULT_MRM_DECEL
#define DEFAULT_OPENGAP_CHANGERATE
#define DEFAULT_INITIAL_AWARENESS
#define DEFAULT_OPENGAP_TIMEGAP
#define DYNAMIC_TOC_ABORT_RESISTANCE_FACTOR
#define DYNAMIC_TOC_LEADTIME_FACTOR
#define DEFAULT_RECOVERY_RATE
#define DEFAULT_LCABSTINENCE
#define MAX_RESPONSETIME_VARIANCE
#define DEFAULT_MRM_PROBABILITY
#define MAX_RESPONSETIME_SAMPLE_TRIES
#define DEFAULT_OPENGAP_MAXDECEL
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:315
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SIMSTEP
Definition SUMOTime.h:61
#define ACCEL2SPEED(x)
Definition SUMOTime.h:51
#define TS
Definition SUMOTime.h:42
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const long long int VEHPARS_COLOR_SET
@ SUMO_TAG_PARKING_AREA
A parking area.
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
MSStop & getNextStop()
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
virtual void setMaxAccel(double accel)
Sets a new value for maximum acceleration [m/s^2].
Definition MSCFModel.h:528
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:256
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition MSCFModel.h:311
The ToC Device controls transition of control between automated and manual driving.
SUMOTime MRMExecutionStep(SUMOTime t)
Continue the MRM for one time step.
std::string myAutomatedTypeID
vehicle type ID for automated driving
void requestMRM()
Request an MRM to be initiated immediately. No downward ToC will be scheduled.
static double getDynamicMRMProbability(const SUMOVehicle &v)
std::string myManualTypeID
vehicle type ID for manual driving
static void cleanup()
Closes root tags of output files.
double myRecoveryRate
Recovery rate for the driver's awareness after a ToC.
bool myDynamicToCActive
Switch for considering dynamic ToCs,.
double myMRMDecel
Deceleration rate applied during MRM.
WrappingCommand< MSDevice_ToC > * myTriggerToCCommand
static double interpolateVariance(double leadTime, double pMRM)
Two-dimensional interpolation of variance from lookup table assumes pMRM >= 0, leadTime >= 0.
static int LCModeMRM
LC mode operational during an MRM.
double myInitialAwareness
Average awareness the driver has initially after a ToC.
bool myUseColorScheme
Whether a coloring scheme shall by applied to indicate the different toc stages,.
OpenGapParams myOpenGapParams
Parameters for the openGap mechanism applied during ToC preparation phase.
static std::vector< std::vector< double > > lookupResponseTimeVariances
Variances of the response time distribution. Given the lead time and the MRM probability the variance...
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed) override
Return value indicates whether the device still wants to be notified about the vehicle movement.
SUMOTime myMRMSafeSpotDuration
duration at stop vehicle tries to reach during MRM
void resetDeliberateLCs()
Resets the holder's LC mode to the last differing to LCModeMRM.
double myOriginalMaxAccel
Storage for original maximal acceleration of vehicle.
const std::string deviceName() const override
return the name for this type of device
static std::vector< double > lookupResponseTimeLeadTimes
WrappingCommand< MSDevice_ToC > * myExecuteMRMCommand
static std::set< std::string > createdOutputFiles
SUMOTime ToCPreparationStep(SUMOTime t)
Continue the ToC preparation for one time step.
~MSDevice_ToC()
Destructor.
bool myIssuedDynamicToC
Flag to indicate that a dynamically triggered ToC is in preparation.
double myMRMProbability
Probability of an MRM to occur after a dynamically triggered ToC.
static std::set< MSDevice_ToC *, ComparatorNumericalIdLess > myInstances
void descheduleRecovery()
Remove ongoing awareness recovery process from the event-queue.
int myPreviousLCMode
LC mode overridden during MRM, stored for restoration.
void requestToC(SUMOTime timeTillMRM, SUMOTime responseTime=-1000)
Request a ToC. If the device is in AUTOMATED or MRM state, a driver response time is sampled and the ...
double sampleResponseTime(double leadTime) const
Samples a random driver response time from a truncated Gaussian with parameters according to the look...
std::queue< std::pair< std::string, double > > myEventLanes
Storage for events to be written to the output.
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_ToC-options.
bool myMRMKeepRight
Whether vehicle tries to change to the right during an MRM.
bool isManuallyDriven()
Whether the current operation mode is manual.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
void setVehicleColor()
ToCState myState
Current state of the device.
double myMaxPreparationAccel
Maximal acceleration that may be applied during the ToC preparation phase TODO: Make effective.
static ToCState _2ToCState(const std::string &)
MSDevice_ToC(SUMOVehicle &holder, const std::string &id, const std::string &outputFilename, const std::string &manualType, const std::string &automatedType, SUMOTime responseTime, double recoveryRate, double lcAbstinence, double initialAwareness, double mrmDecel, double dynamicToCThreshold, double dynamicMRMProbability, double maxPreparationAccel, bool mrmKeepRight, const std::string &mrmSafeSpot, SUMOTime mrmSafeSpotDuration, bool useColorScheme, OpenGapParams ogp)
Constructor.
int myDynamicToCLane
Lane, on which the ongoing dynamic ToC was issued. It can only be aborted if the lane was changed.
bool isAutomated()
Whether the current operation mode is automated.
std::map< ToCState, RGBColor > myColorScheme
Coloring scheme,.
static std::string _2string(ToCState state)
static SumoRNG myResponseTimeRNG
Random generator for ToC devices.
void setState(ToCState state)
Set the ToC device's state.
SUMOTime myResponseTime
Average response time needed by the driver to take back control.
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter for this device. Throw exception for unsupported key
bool generatesOutput()
Whether this device requested to write output.
double myLCAbstinence
Level of the awareness below which no lane-changes are performed.
SUMOTime triggerDownwardToC(SUMOTime t)
Trigger execution of a ToC X-->MANUAL ("downwards")
void initColorScheme()
Initialize vehicle colors for different states.
MSVehicle * myHolderMS
The holder vehicle casted to MSVehicle*.
WrappingCommand< MSDevice_ToC > * myPrepareToCCommand
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
void descheduleMRM()
Break MRM Process or remove MRM-Trigger command from the event-queue.
static double responseTimeMean(double leadTime)
Mean of the response time distribution. (Only depends on given lead time)
void descheduleToC()
Remove scheduled ToC-Trigger command from the event-queue.
void descheduleToCPreparation()
Remove ongoing ToC-Preparation process from the event-queue.
void deactivateDeliberateLCs()
Resets the holder's LC mode to the operational LC-mode of the ToC Device (.
WrappingCommand< MSDevice_ToC > * myRecoverAwarenessCommand
void setAwareness(double value)
Set the awareness to the given value.
WrappingCommand< MSDevice_ToC > * myTriggerMRMCommand
double myDynamicToCThreshold
Duration in s. for which the vehicle needs to be able to follow its route without a lane change to co...
bool checkDynamicToC()
Check if the vehicle should induce a ToC due to internal reasons. That is, if the route cannot be fol...
ToCState
Enum describing the different regimes for the device,.
void writeOutput()
Write output to file given by option device.toc.file.
std::queue< std::pair< double, double > > myEventXY
Storage for events to be written to the output.
OutputDevice * myOutputFile
The file the devices output goes to.
double myCurrentAwareness
Current awareness-level of the driver in [0,1].
SUMOTime triggerMRM(SUMOTime t)
Trigger execution of an MRM.
SUMOTime triggerUpwardToC(SUMOTime t)
Trigger execution of a ToC X-->AUTOMATED ("upwards")
std::queue< std::pair< SUMOTime, std::string > > myEvents
Storage for events to be written to the output.
SUMOTime awarenessRecoveryStep(SUMOTime t)
Continue the awareness recovery for one time step.
std::string myMRMSafeSpot
stop vehicle tries to reach during MRM
static OpenGapParams getOpenGapParams(const SUMOVehicle &v)
static std::vector< double > lookupResponseTimeMRMProbs
Grid of the response time distribution.
void switchHolderType(const std::string &targetTypeID)
Switch the device holder's vehicle type.
static void insertDefaultAssignmentOptions(const std::string &deviceName, const std::string &optionsTopic, OptionsCont &oc, const bool isPerson=false)
Adds common command options that allow to assign devices to vehicles.
Definition MSDevice.cpp:155
static bool equippedByDefaultAssignmentOptions(const OptionsCont &oc, const std::string &deviceName, DEVICEHOLDER &v, bool outputOptionSet, const bool isPerson=false)
Determines whether a vehicle should get a certain device.
Definition MSDevice.h:195
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
static bool gUseMesoSim
Definition MSGlobals.h:106
Representation of a lane in the micro simulation.
Definition MSLane.h:84
bool isInternal() const
Definition MSLane.cpp:2546
int getNumericalID() const
Returns this lane's numerical id.
Definition MSLane.h:525
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition MSNet.h:471
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition MSNet.cpp:1381
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:378
static SumoRNG * getParsingRNG()
get parsing RNG
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
const MSLane & getLane() const
Returns the lane this stop is located at.
void setLaneChangeMode(int value)
Sets lane changing behavior.
void deactivateGapController()
Deactivates the gap control.
void setLaneTimeLine(const std::vector< std::pair< SUMOTime, int > > &laneTimeLine)
Sets a new lane timeline.
int getLaneChangeMode() const
return the current lane change mode
void setSpeedTimeLine(const std::vector< std::pair< SUMOTime, double > > &speedTimeLine)
Sets a new velocity timeline.
void activateGapController(double originalTau, double newTimeHeadway, double newSpaceHeadway, double duration, double changeRate, double maxDecel, MSVehicle *refVeh=nullptr)
Activates the gap control with the given parameters,.
The class responsible for building and deletion of vehicles.
bool hasVType(const std::string &id) const
Asks for existence of a vehicle type.
bool hasVTypeDistribution(const std::string &id) const
Asks for a vehicle type distribution.
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
const std::set< std::string > getVTypeDistributionMembership(const std::string &id) const
Return the distribution IDs the vehicle type is a member of.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
std::shared_ptr< MSSimpleDriverState > getDriverState() const
Returns the vehicle driver's state.
void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
Influencer & getInfluencer()
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
The car-following model and parameter.
const std::string & getID() const
Returns the name of the vehicle type.
void setDecel(double decel)
Set a new value for this type's deceleration.
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
const RGBColor & getColor() const
Returns this type's color.
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
void doRegister(const std::string &name, Option *o)
Adds an option under the given name.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
double x() const
Returns the x-position.
Definition Position.h:55
double y() const
Returns the y-position.
Definition Position.h:60
static double randNorm(double mean, double variance, SumoRNG *rng=nullptr)
Access to a random number from a normal distribution.
Representation of a vehicle, person, or container.
bool getBoolParam(const std::string &paramName, const bool required=false, const bool deflt=false) const
Retrieve a boolean parameter for the traffic object.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
double getFloatParam(const std::string &paramName, const bool required=false, const double deflt=INVALID_DOUBLE) const
Retrieve a floating point parameter for the traffic object.
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:62
virtual bool addStop(const SUMOVehicleParameter::Stop &stopPar, std::string &errorMsg, SUMOTime untilOffset=0, ConstMSEdgeVector::const_iterator *searchStart=0)=0
Adds a stop.
Definition of vehicle stop (position and duration)
ParkingType parking
whether the vehicle is removed from the net while stopping
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
double startPos
The stopping position start.
double endPos
The stopping position end.
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
RGBColor color
The vehicle's color, TraCI may change this.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
A wrapper for a Command function.
void deschedule()
Marks this Command as being descheduled.
static double fn[10]
Definition odrSpiral.cpp:87