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