Eclipse SUMO - Simulation of Urban MObility
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>
32 #include <utils/common/RGBColor.h>
33 #include <microsim/MSNet.h>
34 #include <microsim/MSLane.h>
35 #include <microsim/MSVehicle.h>
39 #include <microsim/MSDriverState.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
99 
100 
101 // ===========================================================================
102 // method definitions
103 // ===========================================================================
104 // ---------------------------------------------------------------------------
105 // static initialisation methods
106 // ---------------------------------------------------------------------------
107 void
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 
153 void
154 MSDevice_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 
188 double
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 // ---------------------------------------------------------------------------
245 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  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) {
302  myState = ToCState::MANUAL;
303  } else if (holderVTypeID == myAutomatedTypeID) {
304  myState = ToCState::AUTOMATED;
305  } else if (manualVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myManualTypeID) > 0) {
306  // Holder type id is from the given manual type distribution.
307  myState = ToCState::MANUAL;
308  myManualTypeID = holderVTypeID;
309  } else if (automatedVTypeIsDist && vehCtrl.getVTypeDistributionMembership(holderVTypeID).count(myAutomatedTypeID) > 0) {
310  // Holder type id is from the given automated type distribution.
311  myState = ToCState::AUTOMATED;
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);
337  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 }
359 
360 
361 
362 void
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 
396 void
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 
416 void
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) {
431  if (myOpenGapParams.active) {
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) {
459  setVehicleColor();
460  }
461 }
462 
463 void
468 }
469 
470 void
472  // Remove any preparatory process
474  // .. and any recovery process
476  // ... and any pending ToC to manual
477  descheduleToC();
478  // Immediately trigger the MRM process
479  triggerMRM(0);
480 }
481 
482 
483 void
484 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  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
513  if (myOpenGapParams.active) {
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 
538 SUMOTime
540 #ifdef DEBUG_TOC
541  std::cout << SIMTIME << " triggerMRM() for vehicle '" << myHolder.getID() << "'" << std::endl;
542 #endif
543  // Clear ongoing MRM
544  descheduleMRM();
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 {
553  stop.parkingarea = myMRMSafeSpot;
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 
586 SUMOTime
588 #ifdef DEBUG_TOC
589  std::cout << SIMTIME << " triggerUpwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
590 #endif
591  descheduleToC();
592  // Eventually stop ToC preparation process
594  // Eventually abort MRM
595  descheduleMRM();
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 
616 SUMOTime
618 #ifdef DEBUG_TOC
619  std::cout << SIMTIME << " triggerDownwardToC() for vehicle '" << myHolder.getID() << "'" << std::endl;
620 #endif
621  descheduleToC();
622  // Eventually stop ToC preparation process
624  // Eventually abort MRM
625  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
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 
651 void
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 
667 void
669  if (myTriggerToCCommand != nullptr) {
671  myTriggerToCCommand = nullptr;
672  }
673 }
674 
675 void
677  // Eventually stop ToC preparation process
678  if (myPrepareToCCommand != nullptr) {
680  if (myState != MRM) {
682  }
683  myPrepareToCCommand = nullptr;
684  }
685 }
686 
687 void
689  // Eventually stop ToC preparation process
690  if (myRecoverAwarenessCommand != nullptr) {
692  myRecoverAwarenessCommand = nullptr;
693  }
694 }
695 
696 
697 void
698 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  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 
711 SUMOTime
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 
728 SUMOTime
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));
748  myHolderMS->getInfluencer().setLaneTimeLine(laneTimeLine);
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 
764 SUMOTime
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
784  myRecoverAwarenessCommand = nullptr;
785  setState(MANUAL);
786  return 0;
787  }
788  return DELTA_T;
789 }
790 
791 bool
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;
810  } 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  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)
820  triggerUpwardToC(0);
821  }
822  return true;
823 }
824 
825 std::string
826 MSDevice_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") {
852  return toString(myMRMProbability);
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 
874 void
875 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  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);
954  myOpenGapParams.newTimeHeadway = newValue;
955  myOpenGapParams.active = true;
956  } else if (key == "ogNewSpaceHeadway") {
957  const double newValue = StringUtils::toDouble(value);
958  myOpenGapParams.newSpaceHeadway = newValue;
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 
975 MSDevice_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 
995 std::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 
1016 void
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 
1047 void
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 
1058 void
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 
1070 void
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 
1083 bool
1085  return (myState == MANUAL || myState == RECOVERING);
1086 }
1087 
1088 bool
1090  return (myState == AUTOMATED || myState == PREPARING_TOC || myState == MRM);
1091 }
1092 
1093 bool
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 
1181 double
1182 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  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 
1204 double
1205 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  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)
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 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#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 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.
Definition: MSDevice_ToC.h:52
SUMOTime MRMExecutionStep(SUMOTime t)
Continue the MRM for one time step.
std::string myAutomatedTypeID
vehicle type ID for automated driving
Definition: MSDevice_ToC.h:266
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
Definition: MSDevice_ToC.h:264
static void cleanup()
Closes root tags of output files.
double myRecoveryRate
Recovery rate for the driver's awareness after a ToC.
Definition: MSDevice_ToC.h:272
bool myDynamicToCActive
Switch for considering dynamic ToCs,.
Definition: MSDevice_ToC.h:336
double myMRMDecel
Deceleration rate applied during MRM.
Definition: MSDevice_ToC.h:279
WrappingCommand< MSDevice_ToC > * myTriggerToCCommand
Definition: MSDevice_ToC.h:302
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.
Definition: MSDevice_ToC.h:324
double myInitialAwareness
Average awareness the driver has initially after a ToC.
Definition: MSDevice_ToC.h:276
bool myUseColorScheme
Whether a coloring scheme shall by applied to indicate the different toc stages,.
Definition: MSDevice_ToC.h:288
OpenGapParams myOpenGapParams
Parameters for the openGap mechanism applied during ToC preparation phase.
Definition: MSDevice_ToC.h:327
static std::vector< std::vector< double > > lookupResponseTimeVariances
Variances of the response time distribution. Given the lead time and the MRM probability the variance...
Definition: MSDevice_ToC.h:364
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
Definition: MSDevice_ToC.h:349
void resetDeliberateLCs()
Resets the holder's LC mode to the last differing to LCModeMRM.
double myOriginalMaxAccel
Storage for original maximal acceleration of vehicle.
Definition: MSDevice_ToC.h:356
const std::string deviceName() const override
return the name for this type of device
Definition: MSDevice_ToC.h:132
static std::vector< double > lookupResponseTimeLeadTimes
Definition: MSDevice_ToC.h:360
WrappingCommand< MSDevice_ToC > * myExecuteMRMCommand
Definition: MSDevice_ToC.h:304
static std::set< std::string > createdOutputFiles
Definition: MSDevice_ToC.h:57
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.
Definition: MSDevice_ToC.h:338
double myMRMProbability
Probability of an MRM to occur after a dynamically triggered ToC.
Definition: MSDevice_ToC.h:334
static std::set< MSDevice_ToC *, ComparatorNumericalIdLess > myInstances
Definition: MSDevice_ToC.h:55
void descheduleRecovery()
Remove ongoing awareness recovery process from the event-queue.
int myPreviousLCMode
LC mode overridden during MRM, stored for restoration.
Definition: MSDevice_ToC.h:321
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.
Definition: MSDevice_ToC.h:315
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_ToC-options.
bool myMRMKeepRight
Whether vehicle tries to change to the right during an MRM.
Definition: MSDevice_ToC.h:343
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.
Definition: MSDevice_ToC.h:291
double myMaxPreparationAccel
Maximal acceleration that may be applied during the ToC preparation phase TODO: Make effective.
Definition: MSDevice_ToC.h:353
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.
Definition: MSDevice_ToC.h:340
bool isAutomated()
Whether the current operation mode is automated.
std::map< ToCState, RGBColor > myColorScheme
Coloring scheme,.
Definition: MSDevice_ToC.h:285
static std::string _2string(ToCState state)
static SumoRNG myResponseTimeRNG
Random generator for ToC devices.
Definition: MSDevice_ToC.h:371
void setState(ToCState state)
Set the ToC device's state.
SUMOTime myResponseTime
Average response time needed by the driver to take back control.
Definition: MSDevice_ToC.h:270
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.
Definition: MSDevice_ToC.h:171
double myLCAbstinence
Level of the awareness below which no lane-changes are performed.
Definition: MSDevice_ToC.h:274
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*.
Definition: MSDevice_ToC.h:296
WrappingCommand< MSDevice_ToC > * myPrepareToCCommand
Definition: MSDevice_ToC.h:305
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)
Definition: MSDevice_ToC.h:362
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
Definition: MSDevice_ToC.h:303
void setAwareness(double value)
Set the awareness to the given value.
WrappingCommand< MSDevice_ToC > * myTriggerMRMCommand
Definition: MSDevice_ToC.h:301
double myDynamicToCThreshold
Duration in s. for which the vehicle needs to be able to follow its route without a lane change to co...
Definition: MSDevice_ToC.h:331
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,.
Definition: MSDevice_ToC.h:108
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.
Definition: MSDevice_ToC.h:318
OutputDevice * myOutputFile
The file the devices output goes to.
Definition: MSDevice_ToC.h:309
double myCurrentAwareness
Current awareness-level of the driver in [0,1].
Definition: MSDevice_ToC.h:282
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.
Definition: MSDevice_ToC.h:312
SUMOTime awarenessRecoveryStep(SUMOTime t)
Continue the awareness recovery for one time step.
std::string myMRMSafeSpot
stop vehicle tries to reach during MRM
Definition: MSDevice_ToC.h:346
static OpenGapParams getOpenGapParams(const SUMOVehicle &v)
static std::vector< double > lookupResponseTimeMRMProbs
Grid of the response time distribution.
Definition: MSDevice_ToC.h:359
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:103
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
bool isInternal() const
Definition: MSLane.cpp:2526
int getNumericalID() const
Returns this lane's numerical id.
Definition: MSLane.h:517
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:184
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
MSStoppingPlace * getStoppingPlace(const std::string &id, const SumoXMLTag category) const
Returns the named stopping place of the given category.
Definition: MSNet.cpp:1373
MSEventControl * getBeginOfTimestepEvents()
Returns the event control for events executed at the begin of a time step.
Definition: MSNet.h:471
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.
Definition: MSVehicle.cpp:791
void deactivateGapController()
Deactivates the gap control.
Definition: MSVehicle.cpp:413
void setLaneTimeLine(const std::vector< std::pair< SUMOTime, int > > &laneTimeLine)
Sets a new lane timeline.
Definition: MSVehicle.cpp:420
int getLaneChangeMode() const
return the current lane change mode
Definition: MSVehicle.cpp:451
void setSpeedTimeLine(const std::vector< std::pair< SUMOTime, double > > &speedTimeLine)
Sets a new velocity timeline.
Definition: MSVehicle.cpp:399
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,.
Definition: MSVehicle.cpp:405
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.
Definition: MSVehicle.cpp:7667
void replaceVehicleType(MSVehicleType *type)
Replaces the current vehicle type by the one given.
Definition: MSVehicle.cpp:4865
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7251
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
Definition: MSVehicle.cpp:5792
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:977
The car-following model and parameter.
Definition: MSVehicleType.h:63
void setDecel(double decel)
Set a new value for this type's deceleration.
const RGBColor & getColor() const
Returns this type's color.
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
const MSCFModel & getCarFollowModel() const
Returns the vehicle type's car following model definition (const version)
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.
Definition: OptionsCont.cpp:76
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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.
Definition: RandHelper.cpp:137
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.
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 MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
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 const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual Position getPosition(const double offset=0) const =0
Return current position (x/y, cartesian)
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
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.
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
void deschedule()
Marks this Command as being descheduled.
static double fn[10]
Definition: odrSpiral.cpp:87