Eclipse SUMO - Simulation of Urban MObility
MSCFModel_CC.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
18 // A series of automatic Cruise Controllers (CC, ACC, CACC)
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <algorithm>
24 #include <utils/common/SUMOTime.h>
26 #include <microsim/MSVehicle.h>
28 #include <microsim/MSNet.h>
29 #include <microsim/MSEdge.h>
30 #include <microsim/MSStop.h>
32 #include <libsumo/Vehicle.h>
33 #include <libsumo/TraCIDefs.h>
34 #include "MSCFModel_CC.h"
35 
36 #ifndef sgn
37 #define sgn(x) ((x > 0) - (x < 0))
38 #endif
39 
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
45  myCcDecel(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_CCDECEL, 1.5)),
46  myCcAccel(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_CCACCEL, 1.5)),
47  myConstantSpacing(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_CONSTSPACING, 5.0)),
48  myKp(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_KP, 1.0)),
49  myLambda(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_LAMBDA, 0.1)),
50  myC1(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_C1, 0.5)),
51  myXi(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_XI, 1.0)),
52  myOmegaN(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_OMEGAN, 0.2)),
53  myTau(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_TAU, 0.5)),
54  myLanesCount((int)vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_LANES_COUNT, -1)),
55  myPloegH(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_PLOEG_H, 0.5)),
56  myPloegKp(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_PLOEG_KP, 0.2)),
57  myPloegKd(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_PLOEG_KD, 0.7)),
58  myFlatbedKa(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_FLATBED_KA, 2.4)),
59  myFlatbedKv(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_FLATBED_KV, 0.6)),
60  myFlatbedKp(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_FLATBED_KP, 12.0)),
61  myFlatbedH(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_FLATBED_H, 4.0)),
62  myFlatbedD(vtype->getParameter().getCFParam(SUMO_ATTR_CF_CC_FLATBED_D, 5.0)) {
63 
64  //if the lanes count has not been specified in the attributes of the model, lane changing cannot properly work
65  if (myLanesCount == -1) {
66  throw ProcessError(TL("The number of lanes needs to be specified in the attributes of carFollowing-CC with the \"lanesCount\" attribute"));
67  }
68 
69  //instantiate the driver model. For now, use Krauss as default, then needs to be parameterized
70  myHumanDriver = new MSCFModel_Krauss(vtype);
71 
72 }
73 
75 
79  vars->ccKp = myKp;
80  vars->accLambda = myLambda;
82  vars->caccC1 = myC1;
83  vars->caccXi = myXi;
84  vars->caccOmegaN = myOmegaN;
85  vars->engineTau = myTau;
86  //we cannot invoke recomputeParameters() because we have no pointer to the MSVehicle class
87  vars->caccAlpha1 = 1 - vars->caccC1;
88  vars->caccAlpha2 = vars->caccC1;
89  vars->caccAlpha3 = -(2 * vars->caccXi - vars->caccC1 * (vars->caccXi + sqrt(vars->caccXi * vars->caccXi - 1))) * vars->caccOmegaN;
90  vars->caccAlpha4 = -(vars->caccXi + sqrt(vars->caccXi * vars->caccXi - 1)) * vars->caccOmegaN * vars->caccC1;
91  vars->caccAlpha5 = -vars->caccOmegaN * vars->caccOmegaN;
92 
93  vars->ploegH = myPloegH;
94  vars->ploegKp = myPloegKp;
95  vars->ploegKd = myPloegKd;
96  vars->flatbedKa = myFlatbedKa;
97  vars->flatbedKv = myFlatbedKv;
98  vars->flatbedKp = myFlatbedKp;
99  vars->flatbedD = myFlatbedD;
100  vars->flatbedH = myFlatbedH;
101  //by default use a first order lag model for the engine
102  vars->engine = new FirstOrderLagModel();
103  vars->engine->setParameter(FOLM_PAR_TAU, vars->engineTau);
108  return (VehicleVariables*)vars;
109 }
110 
111 void
112 MSCFModel_CC::setLeader(MSVehicle* veh, MSVehicle* const leader, std::string leaderId) const {
113  auto* vars = (CC_VehicleVariables*) veh->getCarFollowVariables();
114  vars->leaderVehicle = leader;
115  vars->leaderVehicleId = leaderId;
116  if (leader != nullptr) {
117  vars->isLeader = false;
118  } else
119  // if we are removing our leader, then this vehicle must become a leader of itself until being member of another platoon
120  {
121  vars->isLeader = true;
122  }
123 }
124 
125 int
126 MSCFModel_CC::isPlatoonLaneChangeSafe(const MSVehicle* veh, bool left) const {
128  if (!vars->isLeader) {
129  // before asking the leader, be sure it is still in the simulation
130  if (findVehicle(vars->leaderVehicleId)) {
131  return isPlatoonLaneChangeSafe(vars->leaderVehicle, left);
132  } else {
133  return LCA_BLOCKED;
134  }
135  }
136  int result = 0;
137  std::pair<int, int> state = libsumo::Vehicle::getLaneChangeState(veh->getID(), left ? +1 : -1);
138  // bit 1: query lateral direction (left:0, right:1)
139  // bit 2: query longitudinal direction (followers:0, leaders:1)
140  // bit 3: blocking (return all:0, return only blockers:1)
141  auto followers = libsumo::Vehicle::getNeighbors(veh->getID(), left ? 0b100 : 0b101);
142  auto leaders = libsumo::Vehicle::getNeighbors(veh->getID(), left ? 0b110 : 0b111);
143  bool noNeighbors = followers.empty() && leaders.empty();
144  if (!(state.second & LCA_BLOCKED) && noNeighbors) {
145  // leader is not blocked. check all the members
146  for (auto m = vars->members.begin(); m != vars->members.end(); m++) {
147  const std::pair<int, int> mState = libsumo::Vehicle::getLaneChangeState(m->second, left ? +1 : -1);
148  followers = libsumo::Vehicle::getNeighbors(m->second, left ? 0b100 : 0b101);
149  leaders = libsumo::Vehicle::getNeighbors(m->second, left ? 0b110 : 0b111);
150  noNeighbors = followers.empty() && leaders.empty();
151  if (mState.second & LCA_BLOCKED || !noNeighbors) {
152  if (mState.second & LCA_BLOCKED) {
153  result = mState.second;
154  } else {
155  if (!followers.empty()) {
157  }
158  if (!leaders.empty()) {
160  }
161  }
162  break;
163  }
164  }
165  } else {
166  if (state.second & LCA_BLOCKED) {
167  result = state.second;
168  } else {
169  if (!followers.empty()) {
171  }
172  if (!leaders.empty()) {
174  }
175  }
176  }
177  return result;
178 }
179 
180 void
181 MSCFModel_CC::changeWholePlatoonLane(MSVehicle* const veh, int direction) const {
183  libsumo::Vehicle::changeLane(veh->getID(), veh->getLaneIndex() + direction, 0);
184  for (auto& member : vars->members) {
185  libsumo::Vehicle::changeLane(member.second, veh->getLaneIndex() + direction, 0);
186  }
187 }
188 
189 void
191  // check for left lane change
192  std::pair<int, int> state = libsumo::Vehicle::getLaneChangeState(veh->getID(), +1);
193  int traciState = state.first;
194  if (traciState & LCA_LEFT && traciState & LCA_SPEEDGAIN) {
195  // we can gain by moving left. check that all vehicles can move left
196  if (isPlatoonLaneChangeSafe(veh, true) == 0) {
197  changeWholePlatoonLane(veh, +1);
198  }
199  }
200  // check for right lane change
201  state = libsumo::Vehicle::getLaneChangeState(veh->getID(), -1);
202  traciState = state.first;
203  if (traciState & LCA_RIGHT && traciState & LCA_KEEPRIGHT) {
204  // we should move back right. check that all vehicles can move right
205  if (isPlatoonLaneChangeSafe(veh, false) == 0) {
206  changeWholePlatoonLane(veh, -1);
207  }
208  }
209 }
210 
211 void
213  auto* vars = (CC_VehicleVariables*) veh->getCarFollowVariables();
214  int currentLane = veh->getLaneIndex();
215  if (currentLane == vars->platoonFixedLane) {
216  // platoon has already reached the desired lane
217  vars->platoonFixedLane = -1;
218  return;
219  }
220  bool left = currentLane < vars->platoonFixedLane;
221  if (isPlatoonLaneChangeSafe(veh, left) == 0) {
222  changeWholePlatoonLane(veh, left ? +1 : -1);
223  }
224 }
225 
226 double
227 MSCFModel_CC::getSecureGap(const MSVehicle* const veh, const MSVehicle* const pred, const double speed, const double leaderSpeed, const double leaderMaxDecel) const {
229 
230  const double tolerance = 0.8;
231  switch (vars->activeController) {
232  case Plexe::CACC:
233  case Plexe::FAKED_CACC:
234  return vars->caccSpacing * tolerance;
235  case Plexe::ACC:
236  return (vars->accHeadwayTime * speed + 2) * tolerance;
237  case Plexe::PLOEG:
238  return (vars->ploegH * speed + 2) * tolerance;
239  case Plexe::CONSENSUS:
240  return d_i_j(vars->vehicles, vars->h, 1, 0) * tolerance;
241  case Plexe::FLATBED:
242  return (vars->flatbedD - vars->flatbedH * (speed - leaderSpeed)) * tolerance;
243  case Plexe::DRIVER:
244  return myHumanDriver->getSecureGap(veh, pred, speed, leaderSpeed, leaderMaxDecel);
245  default:
246  throw InvalidArgument("Unsupported activeController" + toString(vars->activeController));
247  }
248 }
249 
250 int
251 MSCFModel_CC::commitToLaneChange(const MSVehicle* veh, bool left) const {
252  auto vars = (CC_VehicleVariables*)veh->getCarFollowVariables();
253  if (isLeader(veh)) {
255  if (vars->laneChangeCommitTime == timestep) {
256  if (vars->commitToLaneChange) {
257  return 0;
258  } else {
259  return vars->noCommitReason;
260  }
261  } else {
262  int blocked = isPlatoonLaneChangeSafe(veh, left);
263  if (blocked == 0) {
264  vars->commitToLaneChange = true;
265  vars->laneChangeCommitTime = timestep;
266  }
267  return blocked;
268  }
269  } else {
270  // before asking the leader, be sure it is still in the simulation
271  if (findVehicle(vars->leaderVehicleId)) {
272  return commitToLaneChange(vars->leaderVehicle, left);
273  } else {
274  return LCA_BLOCKED;
275  }
276  }
277 }
278 
279 MSVehicle*
280 MSCFModel_CC::findVehicle(std::string id) const {
281  return dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(id));
282 }
283 
284 double
285 MSCFModel_CC::finalizeSpeed(MSVehicle* const veh, double vPos) const {
286  double vNext;
287  //acceleration computed by the controller
288  double controllerAcceleration;
289  //acceleration after engine actuation
290  double engineAcceleration;
291 
293 
294  //call processNextStop() to ensure vehicle removal in case of crash
295  veh->processNextStop(vPos);
296 
297  //check whether the vehicle has collided and set the flag in case
298  if (!vars->crashed) {
299  for (const MSStop& s : veh->getStops()) {
300  if (s.pars.collision) {
301  vars->crashed = true;
302  }
303  }
304  }
305 
306  if (vars->activeController != Plexe::DRIVER && !vars->useFixedAcceleration) {
308  }
309 
310  if (vars->platoonFixedLane >= 0) {
312  }
313 
314  if (vars->autoLaneChange) {
316  }
317 
318  if (vars->activeController != Plexe::DRIVER) {
319  controllerAcceleration = SPEED2ACCEL(vPos - veh->getSpeed());
320  controllerAcceleration = std::min(vars->uMax, std::max(vars->uMin, controllerAcceleration));
321  //compute the actual acceleration applied by the engine
322  engineAcceleration = vars->engine->getRealAcceleration(veh->getSpeed(), veh->getAcceleration(), controllerAcceleration, MSNet::getInstance()->getCurrentTimeStep());
323  vNext = MAX2(double(0), veh->getSpeed() + ACCEL2SPEED(engineAcceleration));
324  vars->controllerAcceleration = controllerAcceleration;
325  } else {
326  vNext = myHumanDriver->finalizeSpeed(veh, vPos);
327  }
328 
329  return vNext;
330 }
331 
332 
333 double
334 MSCFModel_CC::followSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const pred, const CalcReason usage) const {
335 
336  UNUSED_PARAMETER(pred);
338 
339  if (vars->activeController != Plexe::DRIVER) {
340  return _v(veh, gap2pred, speed, predSpeed);
341  } else {
342  return myHumanDriver->followSpeed(veh, speed, gap2pred, predSpeed, predMaxDecel, pred, usage);
343  }
344 }
345 
346 double
347 MSCFModel_CC::insertionFollowSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const /*pred*/) const {
348  UNUSED_PARAMETER(veh);
349  UNUSED_PARAMETER(gap2pred);
350  UNUSED_PARAMETER(predSpeed);
351  UNUSED_PARAMETER(predMaxDecel);
352  //by returning speed + 1, we tell sumo that "speed" is always a safe speed
353  return speed + 1;
354 }
355 
356 double
357 MSCFModel_CC::stopSpeed(const MSVehicle* const veh, double speed, double gap2pred, double decel, const CalcReason usage) const {
358 
360  if (vars->activeController != Plexe::DRIVER) {
361  double relSpeed;
362  getRadarMeasurements(veh, gap2pred, relSpeed);
363  if (gap2pred == -1) {
364  gap2pred = std::numeric_limits<double>().max();
365  }
366  return _v(veh, gap2pred, speed, speed + relSpeed);
367  } else {
368  return myHumanDriver->stopSpeed(veh, speed, gap2pred, decel, usage);
369  }
370 }
371 
372 double MSCFModel_CC::freeSpeed(const MSVehicle* const veh, double speed, double seen, double maxSpeed, const bool onInsertion, const CalcReason usage) const {
374  if (vars->activeController != Plexe::DRIVER) {
375  double gap2pred, relSpeed;
376  getRadarMeasurements(veh, gap2pred, relSpeed);
377  if (gap2pred == -1) {
378  gap2pred = std::numeric_limits<double>().max();
379  }
380  return _v(veh, gap2pred, speed, speed + relSpeed);
381  } else {
382  return MSCFModel::freeSpeed(veh, speed, seen, maxSpeed, onInsertion, usage);
383  }
384 }
385 
386 double
387 MSCFModel_CC::interactionGap(const MSVehicle* const veh, double vL) const {
388 
390  if (vars->activeController != Plexe::DRIVER) {
391  //maximum radar range is CC is enabled
392  return 250;
393  } else {
394  return myHumanDriver->interactionGap(veh, vL);
395  }
396 
397 }
398 
399 double
400 MSCFModel_CC::maxNextSpeed(double speed, const MSVehicle* const veh) const {
402  if (vars->engineModel == CC_ENGINE_MODEL_FOLM) {
403  return speed + (double) ACCEL2SPEED(getMaxAccel());
404  } else {
405  return speed + (double) ACCEL2SPEED(20);
406  }
407 }
408 
409 double
410 MSCFModel_CC::minNextSpeed(double speed, const MSVehicle* const veh) const {
412  if (vars->engineModel == CC_ENGINE_MODEL_FOLM) {
413  return MSCFModel::minNextSpeed(speed, veh);
414  } else {
415  return MAX2((double)0, speed - (double) ACCEL2SPEED(20));
416  }
417 }
418 
419 double
420 MSCFModel_CC::_v(const MSVehicle* const veh, double gap2pred, double egoSpeed, double predSpeed) const {
421 
423 
424  //acceleration computed by the controller
425  double controllerAcceleration = vars->fixedAcceleration;
426  //speed computed by the model
427  double speed;
428  //acceleration computed by the Cruise Control
429  double ccAcceleration;
430  //acceleration computed by the Adaptive Cruise Control
431  double accAcceleration;
432  //acceleration computed by the Cooperative Adaptive Cruise Control
433  double caccAcceleration;
434  //variables needed by CACC
435  double predAcceleration, leaderAcceleration, leaderSpeed;
436  //dummy variables used for auto feeding
437  Position pos;
438  double time;
439  const double currentTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() + DELTA_T);
440 
441  if (vars->crashed) {
442  return 0;
443  }
444  if (vars->autoFeed) {
445  if (!findVehicle(vars->leaderVehicleId) || !findVehicle(vars->frontVehicleId)) {
446  // either the leader or the front vehicle have left the simulation. Disable auto feed
447  vars->autoFeed = false;
448  vars->leaderVehicle = nullptr;
449  vars->frontVehicle = nullptr;
450  }
451  }
452  if (vars->activeController == Plexe::DRIVER || !vars->useFixedAcceleration) {
453  switch (vars->activeController) {
454  case Plexe::ACC:
455  ccAcceleration = _cc(veh, egoSpeed, vars->ccDesiredSpeed);
456  accAcceleration = _acc(veh, egoSpeed, predSpeed, gap2pred, vars->accHeadwayTime);
457  if (gap2pred > 250 || ccAcceleration < accAcceleration) {
458  controllerAcceleration = ccAcceleration;
459  } else {
460  controllerAcceleration = accAcceleration;
461  }
462  break;
463 
464  case Plexe::CACC:
465  if (vars->autoFeed) {
468  }
469 
470  if (vars->useControllerAcceleration) {
471  predAcceleration = vars->frontControllerAcceleration;
472  leaderAcceleration = vars->leaderControllerAcceleration;
473  } else {
474  predAcceleration = vars->frontAcceleration;
475  leaderAcceleration = vars->leaderAcceleration;
476  }
477  //overwrite pred speed using data obtained through wireless communication
478  predSpeed = vars->frontSpeed;
479  leaderSpeed = vars->leaderSpeed;
480  if (vars->usePrediction) {
481  predSpeed += (currentTime - vars->frontDataReadTime) * vars->frontAcceleration;
482  leaderSpeed += (currentTime - vars->leaderDataReadTime) * vars->leaderAcceleration;
483  }
484 
485  if (vars->caccInitialized) {
486  controllerAcceleration = _cacc(veh, egoSpeed, predSpeed, predAcceleration, gap2pred, leaderSpeed, leaderAcceleration, vars->caccSpacing);
487  } else
488  //do not let CACC take decisions until at least one packet has been received
489  {
490  controllerAcceleration = 0;
491  }
492 
493  break;
494 
495  case Plexe::FAKED_CACC:
496 
497  if (vars->autoFeed) {
500  vars->fakeData.frontDistance = pos.distanceTo2D(veh->getPosition());
501  }
502 
503  if (vars->useControllerAcceleration) {
504  predAcceleration = vars->fakeData.frontControllerAcceleration;
505  leaderAcceleration = vars->fakeData.leaderControllerAcceleration;
506  } else {
507  predAcceleration = vars->fakeData.frontAcceleration;
508  leaderAcceleration = vars->fakeData.leaderAcceleration;
509  }
510  ccAcceleration = _cc(veh, egoSpeed, vars->ccDesiredSpeed);
511  caccAcceleration = _cacc(veh, egoSpeed, vars->fakeData.frontSpeed, predAcceleration, vars->fakeData.frontDistance, vars->fakeData.leaderSpeed, leaderAcceleration, vars->caccSpacing);
512  //faked CACC can be used to get closer to a platoon for joining
513  //using the minimum acceleration ensures that we do not exceed
514  //the CC desired speed
515  controllerAcceleration = std::min(ccAcceleration, caccAcceleration);
516 
517  break;
518 
519  case Plexe::PLOEG:
520 
521  if (vars->autoFeed) {
523  }
524 
525  if (vars->useControllerAcceleration) {
526  predAcceleration = vars->frontControllerAcceleration;
527  } else {
528  predAcceleration = vars->frontAcceleration;
529  }
530  //check if we received at least one packet
531  if (vars->frontInitialized)
532  //ploeg's controller computes \dot{u}_i, so we need to sum such value to the previously computed u_i
533  {
534  controllerAcceleration = vars->controllerAcceleration + _ploeg(veh, egoSpeed, predSpeed, predAcceleration, gap2pred);
535  } else {
536  controllerAcceleration = 0;
537  }
538 
539  break;
540 
541  case Plexe::CONSENSUS:
542  controllerAcceleration = _consensus(veh, egoSpeed, veh->getPosition(), currentTime);
543  break;
544 
545  case Plexe::FLATBED:
546 
547  if (vars->autoFeed) {
550  }
551 
552  //overwrite pred speed using data obtained through wireless communication
553  predSpeed = vars->frontSpeed;
554  leaderSpeed = vars->leaderSpeed;
555  if (vars->usePrediction) {
556  predSpeed += (currentTime - vars->frontDataReadTime) * vars->frontAcceleration;
557  leaderSpeed += (currentTime - vars->leaderDataReadTime) * vars->leaderAcceleration;
558  }
559 
560  if (vars->caccInitialized) {
561  controllerAcceleration = _flatbed(veh, veh->getAcceleration(), egoSpeed, predSpeed, gap2pred, leaderSpeed);
562  } else
563  //do not let CACC take decisions until at least one packet has been received
564  {
565  controllerAcceleration = 0;
566  }
567 
568  break;
569 
570  case Plexe::DRIVER:
571  std::cerr << "Switching to normal driver behavior still not implemented in MSCFModel_CC\n";
572  assert(false);
573  break;
574 
575  default:
576  std::cerr << "Invalid controller selected in MSCFModel_CC\n";
577  assert(false);
578  break;
579 
580  }
581 
582  }
583 
584  speed = MAX2(double(0), egoSpeed + ACCEL2SPEED(controllerAcceleration));
585 
586  return speed;
587 }
588 
589 double
590 MSCFModel_CC::_cc(const MSVehicle* veh, double egoSpeed, double desSpeed) const {
591 
593  //Eq. 5.5 of the Rajamani book, with Ki = 0 and bounds on max and min acceleration
594  return std::min(myCcAccel, std::max(-myCcDecel, -vars->ccKp * (egoSpeed - desSpeed)));
595 
596 }
597 
598 double
599 MSCFModel_CC::_acc(const MSVehicle* veh, double egoSpeed, double predSpeed, double gap2pred, double headwayTime) const {
600 
602  //Eq. 6.18 of the Rajamani book
603  return -1.0 / headwayTime * (egoSpeed - predSpeed + vars->accLambda * (-gap2pred + headwayTime * egoSpeed + 2));
604 
605 }
606 
607 double
608 MSCFModel_CC::_cacc(const MSVehicle* veh, double egoSpeed, double predSpeed, double predAcceleration, double gap2pred, double leaderSpeed, double leaderAcceleration, double spacing) const {
610  //compute epsilon, i.e., the desired distance error
611  double epsilon = -gap2pred + spacing; //NOTICE: error (if any) should already be included in gap2pred
612  //compute epsilon_dot, i.e., the desired speed error
613  double epsilon_dot = egoSpeed - predSpeed;
614  //Eq. 7.39 of the Rajamani book
615  return vars->caccAlpha1 * predAcceleration + vars->caccAlpha2 * leaderAcceleration +
616  vars->caccAlpha3 * epsilon_dot + vars->caccAlpha4 * (egoSpeed - leaderSpeed) + vars->caccAlpha5 * epsilon;
617 }
618 
619 
620 double
621 MSCFModel_CC::_ploeg(const MSVehicle* veh, double egoSpeed, double predSpeed, double predAcceleration, double gap2pred) const {
623  return (1 / vars->ploegH * (
624  -vars->controllerAcceleration +
625  vars->ploegKp * (gap2pred - (2 + vars->ploegH * egoSpeed)) +
626  vars->ploegKd * (predSpeed - egoSpeed - vars->ploegH * veh->getAcceleration()) +
627  predAcceleration
628  )) * TS ;
629 }
630 
631 double
632 MSCFModel_CC::d_i_j(const struct Plexe::VEHICLE_DATA* vehicles, const double h[MAX_N_CARS], int i, int j) const {
633 
634  int k, min_i, max_i;
635  double d = 0;
636  //compute indexes of the summation
637  if (j < i) {
638  min_i = j;
639  max_i = i - 1;
640  } else {
641  min_i = i;
642  max_i = j - 1;
643  }
644  //compute distance
645  for (k = min_i; k <= max_i; k++) {
646  d += h[k] * vehicles[0].speed + vehicles[k].length + 15;
647  }
648 
649  if (j < i) {
650  return d;
651  } else {
652  return -d;
653  }
654 
655 }
656 
657 double
658 MSCFModel_CC::_consensus(const MSVehicle* veh, double egoSpeed, Position egoPosition, double time) const {
659  //TODO: this controller, by using real GPS coordinates, does only work
660  //when vehicles are traveling west-to-east on a straight line, basically
661  //on the X axis. This needs to be fixed to consider direction as well
663  int index = vars->position;
664  int nCars = vars->nCars;
665  struct Plexe::VEHICLE_DATA* vehicles = vars->vehicles;
666 
667  //loop variable
668  int j;
669  //control input
670  double u_i = 0;
671  //actual distance term
672  double actualDistance = 0;
673  //desired distance term
674  double desiredDistance = 0;
675  //speed error term
676  double speedError = 0;
677  //degree of agent i
678  double d_i = 0;
679 
680  //compensate my position: compute prediction of what will be my position at time of actuation
681  Position egoVelocity = veh->getVelocityVector();
682  egoPosition.set(egoPosition.x() + egoVelocity.x() * STEPS2TIME(DELTA_T),
683  egoPosition.y() + egoVelocity.y() * STEPS2TIME(DELTA_T));
684  vehicles[index].speed = egoSpeed;
685  vehicles[index].positionX = egoPosition.x();
686  vehicles[index].positionY = egoPosition.y();
687 
688  //check that data from all vehicles have been received. the control
689  //law might actually need a subset of all the data, but d_i_j needs
690  //the lengths of all vehicles. uninitialized values might cause problems
691  if (vars->nInitialized != vars->nCars - 1) {
692  return 0;
693  }
694 
695  //compute speed error.
696  speedError = -vars->b[index] * (egoSpeed - vehicles[0].speed);
697 
698  //compute desired distance term
699  for (j = 0; j < nCars; j++) {
700  if (j == index) {
701  continue;
702  }
703  d_i += vars->L[index][j];
704  desiredDistance -= vars->K[index][j] * vars->L[index][j] * d_i_j(vehicles, vars->h, index, j);
705  }
706  desiredDistance = desiredDistance / d_i;
707 
708  //compute actual distance term
709  for (j = 0; j < nCars; j++) {
710  if (j == index) {
711  continue;
712  }
713  //distance error for consensus with GPS equipped
714  Position otherPosition;
715  double dt = time - vehicles[j].time;
716  //predict the position of the other vehicle
717  otherPosition.setx(vehicles[j].positionX + dt * vehicles[j].speedX);
718  otherPosition.sety(vehicles[j].positionY + dt * vehicles[j].speedY);
719  double distance = egoPosition.distanceTo2D(otherPosition) * sgn(j - index);
720  actualDistance -= vars->K[index][j] * vars->L[index][j] * distance;
721  }
722 
723  actualDistance = actualDistance / (d_i);
724 
725  //original paper formula
726  u_i = (speedError + desiredDistance + actualDistance) / 1000;
727 
728  return u_i;
729 }
730 
731 double
732 MSCFModel_CC::_flatbed(const MSVehicle* veh, double egoAcceleration, double egoSpeed, double predSpeed,
733  double gap2pred, double leaderSpeed) const {
735  return (
736  -vars->flatbedKa * egoAcceleration +
737  vars->flatbedKv * (predSpeed - egoSpeed) +
738  vars->flatbedKp * (gap2pred - vars->flatbedD - vars->flatbedH * (egoSpeed - leaderSpeed))
739  );
740 }
741 
742 double
745  return vars->caccSpacing;
746 }
747 
748 void
749 MSCFModel_CC::getVehicleInformation(const MSVehicle* veh, double& speed, double& acceleration, double& controllerAcceleration, Position& position, double& time) const {
751  speed = veh->getSpeed();
752  acceleration = veh->getAcceleration();
753  controllerAcceleration = vars->controllerAcceleration;
754  position = veh->getPosition();
755  time = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
756 }
757 
758 void MSCFModel_CC::setParameter(MSVehicle* veh, const std::string& key, const std::string& value) const {
759  // vehicle variables used to set the parameter
760  CC_VehicleVariables* vars;
761 
762  ParBuffer buf(value);
763 
765  try {
766  if (key.compare(PAR_LEADER_SPEED_AND_ACCELERATION) == 0) {
767  double x, y, vx, vy;
768  buf >> vars->leaderSpeed >> vars->leaderAcceleration >> x >> y >> vars->leaderDataReadTime
769  >> vars->leaderControllerAcceleration >> vx >> vy >> vars->leaderAngle;
770  vars->leaderPosition = Position(x, y);
771  vars->leaderVelocity = Position(vx, vy);
772  vars->leaderInitialized = true;
773  if (vars->frontInitialized) {
774  vars->caccInitialized = true;
775  }
776  return;
777  }
778  if (key.compare(PAR_PRECEDING_SPEED_AND_ACCELERATION) == 0) {
779  double x, y, vx, vy;
780  buf >> vars->frontSpeed >> vars->frontAcceleration >> x >> y >> vars->frontDataReadTime
781  >> vars->frontControllerAcceleration >> vx >> vy >> vars->frontAngle;
782  vars->frontPosition = Position(x, y);
783  vars->frontVelocity = Position(vx, vy);
784  vars->frontInitialized = true;
785  if (vars->leaderInitialized) {
786  vars->caccInitialized = true;
787  }
788  return;
789  }
790  if (key.compare(CC_PAR_VEHICLE_DATA) == 0) {
791  struct Plexe::VEHICLE_DATA vehicle;
792  buf >> vehicle.index >> vehicle.speed >> vehicle.acceleration >>
793  vehicle.positionX >> vehicle.positionY >> vehicle.time >>
794  vehicle.length >> vehicle.u >> vehicle.speedX >>
795  vehicle.speedY >> vehicle.angle;
796  //if the index is larger than the number of cars, simply ignore the data
797  if (vehicle.index >= vars->nCars || vehicle.index == -1) {
798  return;
799  }
800  vars->vehicles[vehicle.index] = vehicle;
801  if (!vars->initialized[vehicle.index] && vehicle.index != vars->position) {
802  vars->nInitialized++;
803  }
804  vars->initialized[vehicle.index] = true;
805  return;
806  }
807  if (key.compare(PAR_LEADER_FAKE_DATA) == 0) {
808  buf >> vars->fakeData.leaderSpeed >> vars->fakeData.leaderAcceleration
810  if (buf.last_empty()) {
811  vars->useControllerAcceleration = false;
812  }
813  return;
814  }
815  if (key.compare(PAR_FRONT_FAKE_DATA) == 0) {
816  buf >> vars->fakeData.frontSpeed >> vars->fakeData.frontAcceleration >> vars->fakeData.frontDistance
818  if (buf.last_empty()) {
819  vars->useControllerAcceleration = false;
820  }
821  return;
822  }
823  if (key.compare(CC_PAR_VEHICLE_POSITION) == 0) {
824  vars->position = StringUtils::toInt(value.c_str());
825  return;
826  }
827  if (key.compare(CC_PAR_PLATOON_SIZE) == 0) {
828  vars->nCars = StringUtils::toInt(value.c_str());
829  // given that we have a static matrix, check that we're not
830  // setting a number of cars larger than the size of that matrix
831  if (vars->nCars > MAX_N_CARS) {
832  vars->nCars = MAX_N_CARS;
833  std::stringstream warn;
834  warn << "MSCFModel_CC: setting a number of cars of " << vars->nCars << " out of a maximum of " << MAX_N_CARS <<
835  ". The CONSENSUS controller will not work properly if chosen. If you are using a different controller " <<
836  "you can ignore this warning";
837  WRITE_WARNING(warn.str());
838  }
839  return;
840  }
841  if (key.compare(PAR_ADD_MEMBER) == 0) {
842  std::string id;
843  int position;
844  buf >> id >> position;
845  vars->members[position] = id;
846 
847  auto vehicle = findVehicle(id);
848  if (!vehicle) {
849  throw libsumo::TraCIException("Adding " + id + " as member but " + id + " does not exists");
850  }
851  auto cfm = dynamic_cast<const MSCFModel_CC*>(&vehicle->getVehicleType().getCarFollowModel());
852  if (!cfm) {
853  throw libsumo::TraCIException("Adding " + id + " as member but " + id + " is not using MSCFModel_CC");
854  }
855  cfm->setLeader(vehicle, veh, veh->getID());
856  vars->isLeader = true;
857  return;
858  }
859  if (key.compare(PAR_REMOVE_MEMBER) == 0) {
860  for (auto item = vars->members.begin(); item != vars->members.end(); item++)
861  if (item->second.compare(value) == 0) {
862  auto vehicle = findVehicle(value);
863  if (!vehicle) {
864  throw libsumo::TraCIException("Removing " + value + " from members but " + value + " does not exist");
865  }
866  auto cfm = dynamic_cast<const MSCFModel_CC*>(&vehicle->getVehicleType().getCarFollowModel());
867  if (!cfm) {
868  throw libsumo::TraCIException("Removing " + value + " from members but " + value + " is not using MSCFModel_CC");
869  }
870  cfm->setLeader(vehicle, nullptr, "");
871  vars->members.erase(item);
872  break;
873  }
874  return;
875  }
876  if (key.compare(PAR_ENABLE_AUTO_LANE_CHANGE) == 0) {
877  vars->autoLaneChange = StringUtils::toInt(value.c_str()) == 1;
878  // if the user enables automatic lane changing, any request for a fixed lane is deleted
879  if (vars->autoLaneChange) {
880  vars->platoonFixedLane = -1;
881  }
882  return;
883  }
884  if (key.compare(PAR_PLATOON_FIXED_LANE) == 0) {
885  vars->platoonFixedLane = StringUtils::toInt(value.c_str());
886  // asking a leader to change the lane for the whole platoon automatically disables auto lane change
887  if (vars->platoonFixedLane >= 0) {
888  vars->autoLaneChange = false;
889  }
890  return;
891  }
892  if (key.compare(CC_PAR_CACC_XI) == 0) {
893  vars->caccXi = StringUtils::toDouble(value.c_str());
894  recomputeParameters(veh);
895  return;
896  }
897  if (key.compare(CC_PAR_CACC_OMEGA_N) == 0) {
898  vars->caccOmegaN = StringUtils::toDouble(value.c_str());
899  recomputeParameters(veh);
900  return;
901  }
902  if (key.compare(CC_PAR_CACC_C1) == 0) {
903  vars->caccC1 = StringUtils::toDouble(value.c_str());
904  recomputeParameters(veh);
905  return;
906  }
907  if (key.compare(CC_PAR_ENGINE_TAU) == 0) {
908  vars->engineTau = StringUtils::toDouble(value.c_str());
909  vars->engine->setParameter(FOLM_PAR_TAU, vars->engineTau);
910  recomputeParameters(veh);
911  vars->engine->setParameter(FOLM_PAR_TAU, vars->engineTau);
912  }
913  if (key.compare(CC_PAR_UMIN) == 0) {
914  vars->uMin = StringUtils::toDouble(value.c_str());
915  return;
916  }
917  if (key.compare(CC_PAR_UMAX) == 0) {
918  vars->uMax = StringUtils::toDouble(value.c_str());
919  return;
920  }
921  if (key.compare(CC_PAR_PLOEG_H) == 0) {
922  vars->ploegH = StringUtils::toDouble(value.c_str());
923  return;
924  }
925  if (key.compare(CC_PAR_PLOEG_KP) == 0) {
926  vars->ploegKp = StringUtils::toDouble(value.c_str());
927  return;
928  }
929  if (key.compare(CC_PAR_PLOEG_KD) == 0) {
930  vars->ploegKd = StringUtils::toDouble(value.c_str());
931  return;
932  }
933  if (key.compare(CC_PAR_FLATBED_KA) == 0) {
934  vars->flatbedKa = StringUtils::toDouble(value.c_str());
935  return;
936  }
937  if (key.compare(CC_PAR_FLATBED_KV) == 0) {
938  vars->flatbedKv = StringUtils::toDouble(value.c_str());
939  return;
940  }
941  if (key.compare(CC_PAR_FLATBED_KP) == 0) {
942  vars->flatbedKp = StringUtils::toDouble(value.c_str());
943  return;
944  }
945  if (key.compare(CC_PAR_FLATBED_H) == 0) {
946  vars->flatbedH = StringUtils::toDouble(value.c_str());
947  return;
948  }
949  if (key.compare(CC_PAR_FLATBED_D) == 0) {
950  vars->flatbedD = StringUtils::toDouble(value.c_str());
951  return;
952  }
953  if (key.compare(CC_PAR_VEHICLE_ENGINE_MODEL) == 0) {
954  if (vars->engine) {
955  delete vars->engine;
956  }
957  int engineModel = StringUtils::toInt(value.c_str());
958  switch (engineModel) {
960  vars->engine = new RealisticEngineModel();
962  veh->getInfluencer().setSpeedMode(0);
964  break;
965  }
967  default: {
968  vars->engine = new FirstOrderLagModel();
970  vars->engine->setParameter(FOLM_PAR_TAU, vars->engineTau);
972  break;
973  }
974  }
977  return;
978  }
979  if (key.compare(CC_PAR_VEHICLE_MODEL) == 0) {
980  vars->engine->setParameter(ENGINE_PAR_VEHICLE, value);
981  return;
982  }
983  if (key.compare(CC_PAR_VEHICLES_FILE) == 0) {
984  vars->engine->setParameter(ENGINE_PAR_XMLFILE, value);
985  return;
986  }
987  if (key.compare(PAR_CACC_SPACING) == 0) {
988  vars->caccSpacing = StringUtils::toDouble(value.c_str());
989  return;
990  }
991  if (key.compare(PAR_FIXED_ACCELERATION) == 0) {
992  buf >> vars->useFixedAcceleration >> vars->fixedAcceleration;
993  return;
994  }
995  if (key.compare(PAR_CC_DESIRED_SPEED) == 0) {
996  vars->ccDesiredSpeed = StringUtils::toDouble(value.c_str());
997  return;
998  }
999  if (key.compare(PAR_ACTIVE_CONTROLLER) == 0) {
1000  vars->activeController = (enum Plexe::ACTIVE_CONTROLLER) StringUtils::toInt(value.c_str());
1001  return;
1002  }
1003  if (key.compare(PAR_ACC_HEADWAY_TIME) == 0) {
1004  vars->accHeadwayTime = StringUtils::toDouble(value.c_str());
1005  return;
1006  }
1007  if (key.compare(PAR_USE_CONTROLLER_ACCELERATION) == 0) {
1008  vars->useControllerAcceleration = StringUtils::toInt(value.c_str()) != 0;
1009  return;
1010  }
1011  if (key.compare(PAR_USE_AUTO_FEEDING) == 0) {
1012  int af;
1013  std::string leaderId, frontId;
1014  buf >> af;
1015  vars->autoFeed = af == 1;
1016  if (vars->autoFeed) {
1017  vars->usePrediction = false;
1018  buf >> leaderId;
1019  if (buf.last_empty()) {
1020  throw InvalidArgument("Trying to enable auto feeding without providing leader vehicle id");
1021  }
1022  vars->leaderVehicleId = leaderId;
1023  vars->leaderVehicle = findVehicle(leaderId);
1024  if (!vars->leaderVehicle) {
1025  throw libsumo::TraCIException("Vehicle '" + leaderId + "' is not known");
1026  }
1027  buf >> frontId;
1028  if (buf.last_empty()) {
1029  throw InvalidArgument("Trying to enable auto feeding without providing front vehicle id");
1030  }
1031  vars->frontVehicleId = frontId;
1032  vars->frontVehicle = findVehicle(frontId);
1033  if (!vars->frontVehicle) {
1034  throw libsumo::TraCIException("Vehicle '" + frontId + "' is not known");
1035  }
1036  vars->leaderInitialized = true;
1037  vars->frontInitialized = true;
1038  vars->caccInitialized = true;
1039  }
1040  return;
1041  }
1042  if (key.compare(PAR_USE_PREDICTION) == 0) {
1043  vars->usePrediction = StringUtils::toInt(value.c_str()) == 1;
1044  return;
1045  }
1046  } catch (NumberFormatException&) {
1047  throw InvalidArgument("Invalid value '" + value + "' for parameter '" + key + "' for vehicle '" + veh->getID() + "'");
1048  }
1049 
1050 }
1051 
1052 std::string MSCFModel_CC::getParameter(const MSVehicle* veh, const std::string& key) const {
1053  // vehicle variables used to set the parameter
1054  CC_VehicleVariables* vars;
1055  ParBuffer buf;
1056 
1057  vars = (CC_VehicleVariables*) veh->getCarFollowVariables();
1058  if (key.compare(PAR_SPEED_AND_ACCELERATION) == 0) {
1059  Position velocity = veh->getVelocityVector();
1060  buf << veh->getSpeed() << veh->getAcceleration() <<
1061  vars->controllerAcceleration << veh->getPosition().x() <<
1062  veh->getPosition().y() <<
1063  STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) <<
1064  velocity.x() << velocity.y() << veh->getAngle();
1065  return buf.str();
1066  }
1067  if (key.compare(PAR_CRASHED) == 0) {
1068  return vars->crashed ? "1" : "0";
1069  }
1070  if (key.compare(PAR_RADAR_DATA) == 0) {
1071  double distance, relSpeed;
1072  getRadarMeasurements(veh, distance, relSpeed);
1073  buf << distance << relSpeed;
1074  return buf.str();
1075  }
1076  if (key.compare(PAR_LANES_COUNT) == 0) {
1077  buf << veh->getLane()->getEdge().getLanes().size();
1078  return buf.str();
1079  }
1080  if (key.compare(PAR_DISTANCE_TO_END) == 0) {
1081  //route of the vehicle
1082  ConstMSRoutePtr route = veh->getRoutePtr();
1083  //last lane of the route of this vehicle
1084  const MSLane* lastLane = route->getEdges().back()->getLanes()[0];
1085  //distance to trip end
1086  buf << route->getDistanceBetween(veh->getPositionOnLane(), lastLane->getLength(), veh->getLane(), lastLane);
1087  return buf.str();
1088  }
1089  if (key.compare(PAR_DISTANCE_FROM_BEGIN) == 0) {
1090  //route of the vehicle
1091  ConstMSRoutePtr route = veh->getRoutePtr();
1092  //first lane of the route of this vehicle
1093  const MSLane* firstLane = route->getEdges().front()->getLanes()[0];
1094  //distance to trip start
1095  buf << route->getDistanceBetween(0., veh->getPositionOnLane(), firstLane, veh->getLane());
1096  return buf.str();
1097  }
1098  if (key.compare(PAR_CC_DESIRED_SPEED) == 0) {
1099  buf << (double)vars->ccDesiredSpeed;
1100  return buf.str();
1101  }
1102  if (key.compare(PAR_ACTIVE_CONTROLLER) == 0) {
1103  buf << (int)vars->activeController;
1104  return buf.str();
1105  }
1106  if (key.compare(PAR_ACC_HEADWAY_TIME) == 0) {
1107  buf << (double)vars->accHeadwayTime;
1108  return buf.str();
1109  }
1110  if (key.compare(PAR_ACC_ACCELERATION) == 0) {
1111  buf << getACCAcceleration(veh);
1112  return buf.str();
1113  }
1114  if (key.compare(PAR_CACC_SPACING) == 0) {
1115  buf << vars->caccSpacing;
1116  return buf.str();
1117  }
1118  if (key.find(CC_PAR_VEHICLE_DATA) == 0) {
1119  ParBuffer inBuf(key);
1120  int index;
1121  inBuf >> index;
1122  struct Plexe::VEHICLE_DATA vehicle;
1123  if (index >= vars->nCars || index < 0) {
1124  vehicle.index = -1;
1125  } else {
1126  vehicle = vars->vehicles[index];
1127  }
1128  buf << vehicle.index << vehicle.speed << vehicle.acceleration <<
1129  vehicle.positionX << vehicle.positionY << vehicle.time <<
1130  vehicle.length << vehicle.u << vehicle.speedX <<
1131  vehicle.speedY << vehicle.angle;
1132  return buf.str();
1133  }
1134  if (key.compare(PAR_ENGINE_DATA) == 0) {
1135  int gear;
1136  double rpm;
1137  RealisticEngineModel* engine = dynamic_cast<RealisticEngineModel*>(vars->engine);
1138  if (engine) {
1139  engine->getEngineData(veh->getSpeed(), gear, rpm);
1140  } else {
1141  gear = -1;
1142  rpm = 0;
1143  }
1144  buf << (gear + 1) << rpm;
1145  return buf.str();
1146  }
1147  return "";
1148 }
1149 
1152  vars->caccAlpha1 = 1 - vars->caccC1;
1153  vars->caccAlpha2 = vars->caccC1;
1154  vars->caccAlpha3 = -(2 * vars->caccXi - vars->caccC1 * (vars->caccXi + sqrt(vars->caccXi * vars->caccXi - 1))) * vars->caccOmegaN;
1155  vars->caccAlpha4 = -(vars->caccXi + sqrt(vars->caccXi * vars->caccXi - 1)) * vars->caccOmegaN * vars->caccC1;
1156  vars->caccAlpha5 = -vars->caccOmegaN * vars->caccOmegaN;
1157 }
1158 
1159 void MSCFModel_CC::resetConsensus(const MSVehicle* veh) const {
1161  for (int i = 0; i < MAX_N_CARS; i++) {
1162  vars->initialized[i] = false;
1163  vars->nInitialized = 0;
1164  }
1165 }
1166 
1167 void MSCFModel_CC::switchOnACC(const MSVehicle* veh, double ccDesiredSpeed) const {
1169  vars->ccDesiredSpeed = ccDesiredSpeed;
1170  vars->activeController = Plexe::ACC;
1171 }
1172 
1175  return vars->activeController;
1176 }
1177 
1178 void MSCFModel_CC::getRadarMeasurements(const MSVehicle* veh, double& distance, double& relativeSpeed) const {
1179  std::pair<std::string, double> l = libsumo::Vehicle::getLeader(veh->getID(), 250);
1180  if (l.second < 0) {
1181  distance = -1;
1182  relativeSpeed = 0;
1183  } else {
1184  distance = l.second;
1185  SUMOVehicle* leader = findVehicle(l.first);
1186  relativeSpeed = leader->getSpeed() - veh->getSpeed();
1187  }
1188 }
1189 
1192  double distance, relSpeed;
1193  getRadarMeasurements(veh, distance, relSpeed);
1194  if (distance < 0) {
1195  return 0;
1196  } else {
1197  return _acc(veh, veh->getSpeed(), relSpeed + veh->getSpeed(), distance, vars->accHeadwayTime);
1198  }
1199 }
1200 
1202  return myLanesCount;
1203 }
1204 
1205 MSCFModel*
1207  return new MSCFModel_CC(vtype);
1208 }
1209 
1210 bool
1212  auto vars = (CC_VehicleVariables*)veh->getCarFollowVariables();
1213  return vars->isLeader;
1214 }
#define ENGINE_PAR_XMLFILE
Definition: CC_Const.h:87
#define PAR_RADAR_DATA
Definition: CC_Const.h:149
#define PAR_FIXED_ACCELERATION
Definition: CC_Const.h:128
#define PAR_REMOVE_MEMBER
Definition: CC_Const.h:180
#define CC_PAR_CACC_OMEGA_N
Definition: CC_Const.h:96
#define CC_PAR_FLATBED_KP
Definition: CC_Const.h:109
#define PAR_CACC_SPACING
Definition: CC_Const.h:119
#define CC_PAR_PLOEG_KP
Definition: CC_Const.h:104
#define PAR_FRONT_FAKE_DATA
Definition: CC_Const.h:155
#define PAR_SPEED_AND_ACCELERATION
Definition: CC_Const.h:131
#define CC_ENGINE_MODEL_REALISTIC
Definition: CC_Const.h:80
#define MAX_N_CARS
Definition: CC_Const.h:77
#define PAR_PLATOON_FIXED_LANE
Definition: CC_Const.h:186
#define CC_PAR_FLATBED_KV
Definition: CC_Const.h:108
#define PAR_USE_PREDICTION
Definition: CC_Const.h:176
#define PAR_DISTANCE_TO_END
Definition: CC_Const.h:158
#define CC_ENGINE_MODEL_FOLM
Definition: CC_Const.h:79
#define CC_PAR_VEHICLE_MODEL
Definition: CC_Const.h:115
#define CC_PAR_PLOEG_H
Definition: CC_Const.h:103
#define PAR_PRECEDING_SPEED_AND_ACCELERATION
Definition: CC_Const.h:164
#define PAR_ACTIVE_CONTROLLER
Definition: CC_Const.h:146
#define CC_PAR_CACC_XI
Definition: CC_Const.h:95
#define PAR_LEADER_SPEED_AND_ACCELERATION
Definition: CC_Const.h:134
#define CC_PAR_PLATOON_SIZE
Definition: CC_Const.h:92
#define CC_PAR_UMIN
Definition: CC_Const.h:100
#define CC_PAR_VEHICLE_POSITION
Definition: CC_Const.h:91
#define CC_PAR_FLATBED_KA
Definition: CC_Const.h:107
#define PAR_LANES_COUNT
Definition: CC_Const.h:140
#define CC_PAR_VEHICLE_ENGINE_MODEL
Definition: CC_Const.h:113
#define PAR_USE_AUTO_FEEDING
Definition: CC_Const.h:173
#define CC_PAR_FLATBED_D
Definition: CC_Const.h:111
#define PAR_CC_DESIRED_SPEED
Definition: CC_Const.h:143
#define CC_PAR_PLOEG_KD
Definition: CC_Const.h:105
#define CC_PAR_VEHICLES_FILE
Definition: CC_Const.h:116
#define CC_PAR_UMAX
Definition: CC_Const.h:101
#define CC_PAR_CACC_C1
Definition: CC_Const.h:97
#define FOLM_PAR_DT
Definition: CC_Const.h:84
#define PAR_LEADER_FAKE_DATA
Definition: CC_Const.h:154
#define FOLM_PAR_TAU
Definition: CC_Const.h:83
#define CC_PAR_FLATBED_H
Definition: CC_Const.h:110
#define PAR_ADD_MEMBER
Definition: CC_Const.h:179
#define PAR_ACC_HEADWAY_TIME
Definition: CC_Const.h:167
#define PAR_DISTANCE_FROM_BEGIN
Definition: CC_Const.h:161
#define ENGINE_PAR_VEHICLE
Definition: CC_Const.h:86
#define CC_PAR_ENGINE_TAU
Definition: CC_Const.h:98
#define ENGINE_PAR_DT
Definition: CC_Const.h:88
#define PAR_USE_CONTROLLER_ACCELERATION
Definition: CC_Const.h:137
#define PAR_ACC_ACCELERATION
Definition: CC_Const.h:122
#define PAR_ENGINE_DATA
Definition: CC_Const.h:170
#define CC_PAR_VEHICLE_DATA
Definition: CC_Const.h:90
#define PAR_ENABLE_AUTO_LANE_CHANGE
Definition: CC_Const.h:183
#define PAR_CRASHED
Definition: CC_Const.h:125
long long int SUMOTime
Definition: GUI.h:35
#define sgn(x)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
std::shared_ptr< const MSRoute > ConstMSRoutePtr
Definition: Route.h:31
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:51
#define TS
Definition: SUMOTime.h:42
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:53
@ LCA_KEEPRIGHT
The action is due to the default of keeping right "Rechtsfahrgebot".
@ LCA_BLOCKED
blocked in all directions
@ LCA_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_LEFT_LEADER
@ SUMO_ATTR_CF_CC_FLATBED_KP
@ SUMO_ATTR_CF_CC_LAMBDA
@ SUMO_ATTR_CF_CC_FLATBED_D
@ SUMO_ATTR_CF_CC_FLATBED_KA
@ SUMO_ATTR_CF_CC_PLOEG_KP
@ SUMO_ATTR_CF_CC_PLOEG_H
@ SUMO_ATTR_CF_CC_OMEGAN
@ SUMO_ATTR_CF_CC_C1
@ SUMO_ATTR_CF_CC_CCACCEL
@ SUMO_ATTR_CF_CC_PLOEG_KD
@ SUMO_ATTR_CF_CC_TAU
@ SUMO_ATTR_CF_CC_XI
@ SUMO_ATTR_CF_CC_CCDECEL
@ SUMO_ATTR_CF_CC_FLATBED_H
@ SUMO_ATTR_CF_CC_LANES_COUNT
@ SUMO_ATTR_CF_CC_CONSTSPACING
@ SUMO_ATTR_CF_CC_KP
@ SUMO_ATTR_CF_CC_FLATBED_KV
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
int nInitialized
count of initialized vehicles
int platoonFixedLane
whole platoon lane change (not automatic). -1 indicates no need to change lane (mechanism disabled)
bool autoFeed
determines whether CACC should automatically fetch data about other vehicles
struct FAKE_CONTROLLER_DATA fakeData
fake controller data.
MSVehicle * frontVehicle
front sumo id, used for auto feeding
double accHeadwayTime
headway time for ACC
bool initialized[MAX_N_CARS]
tells whether data about a certain vehicle has been initialized
double frontSpeed
current front vehicle speed
double K[MAX_N_CARS][MAX_N_CARS]
K matrix.
struct Plexe::VEHICLE_DATA vehicles[MAX_N_CARS]
data about vehicles in the platoon
int position
my position within the platoon (0 = first car)
double frontAcceleration
current front vehicle acceleration (used by CACC)
bool frontInitialized
@did we receive at least one packet?
double leaderDataReadTime
when leader data has been readed from GPS
bool usePrediction
enable/disable data prediction (interpolation) for missing data
std::map< int, std::string > members
list of members belonging to my platoon
double leaderControllerAcceleration
platoon's leader controller acceleration (used by CACC)
double controllerAcceleration
acceleration as computed by the controller, to be sent to other vehicles
int L[MAX_N_CARS][MAX_N_CARS]
L matrix.
double caccXi
controller related parameters
double frontControllerAcceleration
front vehicle controller acceleration (used by CACC)
double b[MAX_N_CARS]
vector of damping ratios b
GenericEngineModel * engine
engine model employed by this car
int nCars
number of cars in the platoon
double leaderSpeed
platoon's leader speed (used by CACC)
double leaderAngle
platoon's leader angle in radians
enum Plexe::ACTIVE_CONTROLLER activeController
currently active controller
bool leaderInitialized
@did we receive at least one packet?
double caccSpacing
fixed spacing for CACC
Position frontVelocity
front vehicle velocity vector
double uMin
limits for u
double ccDesiredSpeed
CC desired speed.
double h[MAX_N_CARS]
vector of time headways h
std::string frontVehicleId
sumo id of the front vehicle
Position frontPosition
current front vehicle position
bool isLeader
whether this vehicle is leader of a platoon or not. This is mainly used by the lane change logic....
double leaderAcceleration
platoon's leader acceleration (used by CACC)
std::string leaderVehicleId
sumo id of the leader vehicle
bool autoLaneChange
automatic whole platoon lane change
Position leaderVelocity
platoon's leader velocity vector
double frontAngle
front vehicle angle in radians
double frontDataReadTime
when front vehicle data has been readed from GPS
int engineModel
numeric value indicating the employed model
MSVehicle * leaderVehicle
leader vehicle, used for auto feeding
Position leaderPosition
platoon's leader position
bool useControllerAcceleration
determines whether PATH's CACC should use the real vehicle acceleration or the controller computed on...
void setMaximumAcceleration(double maxAcc)
virtual double getRealAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime timeStep=0)=0
void setMaximumDeceleration(double maxDec)
virtual void setParameter(const std::string parameter, const std::string &value)=0
ConstMSRoutePtr getRoutePtr() const
Returns the current route.
void setChosenSpeedFactor(const double factor)
Returns the precomputed factor by which the driver wants to be faster than the speed limit.
const std::list< MSStop > & getStops() const
A set of automatic Cruise Controllers, including classic Cruise Control (CC), Adaptive Cruise Control...
Definition: MSCFModel_CC.h:57
double _v(const MSVehicle *const veh, double gap2pred, double egoSpeed, double predSpeed) const
MSCFModel_CC(const MSVehicleType *vtype)
Constructor.
virtual std::string getParameter(const MSVehicle *veh, const std::string &key) const
set the information about a generic car. This method should be invoked by TraCI when a wireless messa...
virtual double insertionFollowSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0) const
Overload base MSCFModel::insertionFollowSpeed method to inject automated vehicles as soon as they are...
const double myPloegKd
Definition: MSCFModel_CC.h:463
const double myFlatbedH
Definition: MSCFModel_CC.h:469
const double myFlatbedKp
Definition: MSCFModel_CC.h:468
const double myPloegH
Ploeg's CACC parameters.
Definition: MSCFModel_CC.h:461
double getACCAcceleration(const MSVehicle *veh) const
returns the ACC computed acceleration when the faked CACC is controlling the car. This can be used to...
bool isLeader(const MSVehicle *veh) const
Returns whether a vehicle is a leader of a platoon or not. By default, a vehicle on its own using an ...
int getMyLanesCount() const
returns the number of lanes set in the configuration file
double _flatbed(const MSVehicle *veh, double egoAcceleration, double egoSpeed, double predSpeed, double gap2pred, double leaderSpeed) const
flatbed platoon towing model
void getVehicleInformation(const MSVehicle *veh, double &speed, double &acceleration, double &controllerAcceleration, Position &position, double &time) const
get the information about a vehicle. This can be used by TraCI in order to get speed and acceleration...
MSCFModel * duplicate(const MSVehicleType *vtype) const
Duplicates the car-following model.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
VehicleVariables * createVehicleVariables() const
Returns model specific values which are stored inside a vehicle and must be used with casting.
MSVehicle * findVehicle(std::string id) const
void getRadarMeasurements(const MSVehicle *veh, double &distance, double &relativeSpeed) const
return the data that is currently being measured by the radar
double _consensus(const MSVehicle *veh, double egoSpeed, Position egoPosition, double time) const
controller based on consensus strategy
const double myPloegKp
Definition: MSCFModel_CC.h:462
double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed (no dawdling)
double _ploeg(const MSVehicle *veh, double egoSpeed, double predSpeed, double predAcceleration, double gap2pred) const
controller for the Ploeg's CACC which computes the control input variation. Opposed to other controll...
void performPlatoonLaneChange(MSVehicle *const veh) const
If safe to do so, moves a platoon to a user-desired lane. If not safe, this method continues to try a...
void changeWholePlatoonLane(MSVehicle *const veh, int direction) const
Moves an entire platoon on an adjacent lane, calling changeLane() on all members.
const double myTau
engine time constant used for actuation lag
Definition: MSCFModel_CC.h:454
double d_i_j(const struct Plexe::VEHICLE_DATA *vehicles, const double h[MAX_N_CARS], int i, int j) const
computes the desired distance between vehicle i and vehicle j
const double myOmegaN
design constant for CACC
Definition: MSCFModel_CC.h:451
double stopSpeed(const MSVehicle *const veh, const double speed, double gap2pred, double decel, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
const double myC1
design constant for CACC
Definition: MSCFModel_CC.h:445
const int myLanesCount
number of lanes in the highway, in the absence of on-/off-ramps. This is used to move to the correct ...
Definition: MSCFModel_CC.h:458
virtual double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences.
double _cacc(const MSVehicle *veh, double egoSpeed, double predSpeed, double predAcceleration, double gap2pred, double leaderSpeed, double leaderAcceleration, double spacing) const
controller for the CACC which computes the acceleration to be applied. the value needs to be passed t...
virtual void setParameter(MSVehicle *veh, const std::string &key, const std::string &value) const
try to set the given parameter for this carFollowingModel
const double myConstantSpacing
the constant gap for CACC
Definition: MSCFModel_CC.h:436
double getCACCConstantSpacing(const MSVehicle *veh) const
returns CACC desired constant spacing
~MSCFModel_CC()
Destructor.
const double myFlatbedKv
Definition: MSCFModel_CC.h:467
void recomputeParameters(const MSVehicle *veh) const
Recomputes controller related parameters after setting them.
const double myXi
design constant for CACC
Definition: MSCFModel_CC.h:448
const double myFlatbedKa
flatbed CACC parameters
Definition: MSCFModel_CC.h:466
void switchOnACC(const MSVehicle *veh, double ccDesiredSpeed) const
switch on the ACC, so disabling the human driver car control
int commitToLaneChange(const MSVehicle *veh, bool left) const
MSCFModel * myHumanDriver
the car following model which drives the car when automated cruising is disabled, i....
Definition: MSCFModel_CC.h:427
const double myLambda
design constant for ACC
Definition: MSCFModel_CC.h:442
void performAutoLaneChange(MSVehicle *const veh) const
Check whether a platoon would gain speed by moving to the left or whether it should move to the right...
void setLeader(MSVehicle *veh, MSVehicle *const leader, std::string leaderId) const
Sets the leader for a member of the platoon.
const double myKp
design constant for CC
Definition: MSCFModel_CC.h:439
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
const double myCcAccel
The maximum acceleration that the CC can output.
Definition: MSCFModel_CC.h:433
int isPlatoonLaneChangeSafe(const MSVehicle *veh, bool left) const
computes whether a lane change for a whole platoon is safe or not. This is done by checking the lane ...
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed without a leader.
const double myCcDecel
The maximum deceleration that the CC can output.
Definition: MSCFModel_CC.h:430
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
const double myFlatbedD
Definition: MSCFModel_CC.h:470
void resetConsensus(const MSVehicle *veh) const
Resets the consensus controller. In particular, sets the "initialized" vector all to false....
double interactionGap(const MSVehicle *const, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
enum Plexe::ACTIVE_CONTROLLER getActiveController(const MSVehicle *veh) const
return the currently active controller
double _cc(const MSVehicle *veh, double egoSpeed, double desSpeed) const
controller for the CC which computes the acceleration to be applied. the value needs to be passed to ...
double _acc(const MSVehicle *veh, double egoSpeed, double predSpeed, double gap2pred, double headwayTime) const
controller for the ACC which computes the acceleration to be applied. the value needs to be passed to...
Krauss car-following model, with acceleration decrease and faster start.
The car-following model abstraction.
Definition: MSCFModel.h:55
virtual double interactionGap(const MSVehicle *const veh, double vL) const
Returns the maximum gap at which an interaction between both vehicles occurs.
Definition: MSCFModel.cpp:277
virtual double freeSpeed(const MSVehicle *const veh, double speed, double seen, double maxSpeed, const bool onInsertion=false, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed without a leader.
Definition: MSCFModel.cpp:321
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
Definition: MSCFModel.cpp:298
virtual double finalizeSpeed(MSVehicle *const veh, double vPos) const
Applies interaction with stops and lane changing model influences. Called at most once per simulation...
Definition: MSCFModel.cpp:187
CalcReason
What the return value of stop/follow/free-Speed is used for.
Definition: MSCFModel.h:77
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
Definition: MSCFModel.cpp:166
double myDecel
The vehicle's maximum deceleration [m/s^2].
Definition: MSCFModel.h:701
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition: MSCFModel.h:256
double myAccel
The vehicle's maximum acceleration [m/s^2].
Definition: MSCFModel.h:698
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition: MSCFModel.h:168
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition: MSEdge.h:168
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition: MSLane.h:584
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
Definition: MSStop.h:44
void setSpeedMode(int speedMode)
Sets speed-constraining behaviors.
Definition: MSVehicle.cpp:779
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition: MSVehicle.h:517
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
Definition: MSVehicle.cpp:1242
bool isLeader(const MSLink *link, const MSVehicle *veh, const double gap) const
whether the given vehicle must be followed at the given junction
Definition: MSVehicle.cpp:7372
Influencer & getInfluencer()
Definition: MSVehicle.cpp:7217
MSCFModel::VehicleVariables * getCarFollowVariables() const
Returns the vehicle's car following model variables.
Definition: MSVehicle.h:998
double getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:493
double processNextStop(double currentVelocity)
Processes stops, returns the velocity needed to reach the stop.
Definition: MSVehicle.cpp:1619
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
double getAngle() const
Returns the vehicle's direction in radians.
Definition: MSVehicle.h:734
int getLaneIndex() const
Definition: MSVehicle.cpp:6642
Position getVelocityVector() const
Returns the vehicle's direction in radians.
Definition: MSVehicle.h:742
The car-following model and parameter.
Definition: MSVehicleType.h:63
const std::string & getID() const
Returns the id.
Definition: Named.h:74
std::string str() const
Definition: ParBuffer.h:148
bool last_empty()
Definition: ParBuffer.h:138
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
void setx(double x)
set position x
Definition: Position.h:70
void set(double x, double y)
set positions x and y
Definition: Position.h:85
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:271
double x() const
Returns the x-position.
Definition: Position.h:55
void sety(double y)
set position y
Definition: Position.h:75
double y() const
Returns the y-position.
Definition: Position.h:60
void getEngineData(double speed_mps, int &gear, double &rpm)
virtual double getSpeed() const =0
Returns the object's current speed.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
An error which allows to continue.
Definition: TraCIDefs.h:144
ACTIVE_CONTROLLER
Determines the currently active controller, i.e., ACC, CACC, or the driver. In future we might need t...
Definition: CC_Const.h:49
@ DRIVER
Definition: CC_Const.h:49
@ CONSENSUS
Definition: CC_Const.h:49
@ FAKED_CACC
Definition: CC_Const.h:49
@ CACC
Definition: CC_Const.h:49
@ PLOEG
Definition: CC_Const.h:49
@ ACC
Definition: CC_Const.h:49
@ FLATBED
Definition: CC_Const.h:49
double acceleration
Definition: CC_Const.h:66