Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/libsumo/Lane.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2017-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file Lane.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Mario Krumnow
17
/// @author Jakob Erdmann
18
/// @author Michael Behrisch
19
/// @author Robert Hilbrich
20
/// @author Leonhard Luecken
21
/// @date 30.05.2012
22
///
23
// C++ TraCI client API implementation
24
/****************************************************************************/
25
#include <config.h>
26
27
#include <microsim/MSNet.h>
28
#include <microsim/MSLane.h>
29
#include <microsim/MSEdge.h>
30
#include <microsim/MSVehicle.h>
31
#include <microsim/MSLink.h>
32
#include <microsim/MSInsertionControl.h>
33
#include <utils/geom/GeomHelper.h>
34
#include <libsumo/Helper.h>
35
#include <libsumo/StorageHelper.h>
36
#include <libsumo/TraCIConstants.h>
37
#include "Lane.h"
38
39
40
namespace libsumo {
41
// ===========================================================================
42
// static member initializations
43
// ===========================================================================
44
SubscriptionResults Lane::mySubscriptionResults;
45
ContextSubscriptionResults Lane::myContextSubscriptionResults;
46
47
48
// ===========================================================================
49
// static member definitions
50
// ===========================================================================
51
std::vector<std::string>
52
Lane::getIDList() {
53
MSNet::getInstance(); // just to check that we actually have a network
54
std::vector<std::string> ids;
55
MSLane::insertIDs(ids);
56
return ids;
57
}
58
59
60
int
61
Lane::getIDCount() {
62
return (int)getIDList().size();
63
}
64
65
66
std::string
67
Lane::getEdgeID(const std::string& laneID) {
68
return getLane(laneID)->getEdge().getID();
69
}
70
71
72
double
73
Lane::getLength(const std::string& laneID) {
74
return getLane(laneID)->getLength();
75
}
76
77
78
double
79
Lane::getMaxSpeed(const std::string& laneID) {
80
return getLane(laneID)->getSpeedLimit();
81
}
82
83
double
84
Lane::getFriction(const std::string& laneID) {
85
return getLane(laneID)->getFrictionCoefficient();
86
}
87
88
int
89
Lane::getLinkNumber(const std::string& laneID) {
90
return (int)getLane(laneID)->getLinkCont().size();
91
}
92
93
94
std::vector<TraCIConnection>
95
Lane::getLinks(const std::string& laneID) {
96
std::vector<TraCIConnection> v;
97
const MSLane* const lane = getLane(laneID);
98
const SUMOTime currTime = MSNet::getInstance()->getCurrentTimeStep();
99
for (const MSLink* const link : lane->getLinkCont()) {
100
const std::string approachedLane = link->getLane() != nullptr ? link->getLane()->getID() : "";
101
const bool hasPrio = link->havePriority();
102
const double speed = MIN2(lane->getSpeedLimit(), link->getLane()->getSpeedLimit());
103
const bool isOpen = link->opened(currTime, speed, speed, SUMOVTypeParameter::getDefault().length,
104
SUMOVTypeParameter::getDefault().impatience, SUMOVTypeParameter::getDefaultDecel(), 0);
105
const bool hasFoe = link->hasApproachingFoe(currTime, currTime, 0, SUMOVTypeParameter::getDefaultDecel());
106
const std::string approachedInternal = link->getViaLane() != nullptr ? link->getViaLane()->getID() : "";
107
const std::string state = SUMOXMLDefinitions::LinkStates.getString(link->getState());
108
const std::string direction = SUMOXMLDefinitions::LinkDirections.getString(link->getDirection());
109
const double length = link->getLength();
110
v.push_back(TraCIConnection(approachedLane, hasPrio, isOpen, hasFoe, approachedInternal, state, direction, length));
111
}
112
return v;
113
}
114
115
116
std::vector<std::string>
117
Lane::getAllowed(const std::string& laneID) {
118
SVCPermissions permissions = getLane(laneID)->getPermissions();
119
if (permissions == SVCAll) { // special case: write nothing
120
permissions = 0;
121
}
122
return getVehicleClassNamesList(permissions);
123
}
124
125
126
std::vector<std::string>
127
Lane::getDisallowed(const std::string& laneID) {
128
return getVehicleClassNamesList(invertPermissions((getLane(laneID)->getPermissions()))); // negation yields disallowed
129
}
130
131
132
std::vector<std::string>
133
Lane::getChangePermissions(const std::string& laneID, const int direction) {
134
if (direction == libsumo::LANECHANGE_LEFT) {
135
return getVehicleClassNamesList(getLane(laneID)->getChangeLeft());
136
} else if (direction == libsumo::LANECHANGE_RIGHT) {
137
return getVehicleClassNamesList(getLane(laneID)->getChangeRight());
138
} else {
139
throw TraCIException("Invalid direction for change permission (must be " + toString(libsumo::LANECHANGE_LEFT) + " or " + toString(libsumo::LANECHANGE_RIGHT));
140
}
141
}
142
143
144
TraCIPositionVector
145
Lane::getShape(const std::string& laneID) {
146
TraCIPositionVector pv;
147
const PositionVector& shp = getLane(laneID)->getShape();
148
for (PositionVector::const_iterator pi = shp.begin(); pi != shp.end(); ++pi) {
149
TraCIPosition p;
150
p.x = pi->x();
151
p.y = pi->y();
152
p.z = pi->z();
153
pv.value.push_back(p);
154
}
155
return pv;
156
}
157
158
159
double
160
Lane::getWidth(const std::string& laneID) {
161
return getLane(laneID)->getWidth();
162
}
163
164
165
double
166
Lane::getCO2Emission(const std::string& laneID) {
167
return getLane(laneID)->getEmissions<PollutantsInterface::CO2>();
168
}
169
170
171
double
172
Lane::getCOEmission(const std::string& laneID) {
173
return getLane(laneID)->getEmissions<PollutantsInterface::CO>();
174
}
175
176
177
double
178
Lane::getHCEmission(const std::string& laneID) {
179
return getLane(laneID)->getEmissions<PollutantsInterface::HC>();
180
}
181
182
183
double
184
Lane::getPMxEmission(const std::string& laneID) {
185
return getLane(laneID)->getEmissions<PollutantsInterface::PM_X>();
186
}
187
188
189
double
190
Lane::getNOxEmission(const std::string& laneID) {
191
return getLane(laneID)->getEmissions<PollutantsInterface::NO_X>();
192
}
193
194
double
195
Lane::getFuelConsumption(const std::string& laneID) {
196
return getLane(laneID)->getEmissions<PollutantsInterface::FUEL>();
197
}
198
199
200
double
201
Lane::getNoiseEmission(const std::string& laneID) {
202
return getLane(laneID)->getHarmonoise_NoiseEmissions();
203
}
204
205
206
double
207
Lane::getElectricityConsumption(const std::string& laneID) {
208
return getLane(laneID)->getEmissions<PollutantsInterface::ELEC>();
209
}
210
211
212
double
213
Lane::getLastStepMeanSpeed(const std::string& laneID) {
214
return getLane(laneID)->getMeanSpeed();
215
}
216
217
218
double
219
Lane::getLastStepOccupancy(const std::string& laneID) {
220
return getLane(laneID)->getNettoOccupancy();
221
}
222
223
224
double
225
Lane::getLastStepLength(const std::string& laneID) {
226
const MSLane* lane = getLane(laneID);
227
double length = 0;
228
const MSLane::VehCont& vehs = lane->getVehiclesSecure();
229
for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
230
length += (*j)->getVehicleType().getLength();
231
}
232
if (vehs.size() > 0) {
233
length = length / (double)vehs.size();
234
}
235
lane->releaseVehicles();
236
return length;
237
}
238
239
240
double
241
Lane::getWaitingTime(const std::string& laneID) {
242
return getLane(laneID)->getWaitingSeconds();
243
}
244
245
246
double
247
Lane::getTraveltime(const std::string& laneID) {
248
const MSLane* lane = getLane(laneID);
249
double meanSpeed = lane->getMeanSpeed();
250
if (meanSpeed != 0) {
251
return lane->getLength() / meanSpeed;
252
} else {
253
return 1000000.;
254
}
255
}
256
257
258
int
259
Lane::getLastStepVehicleNumber(const std::string& laneID) {
260
return (int)getLane(laneID)->getVehicleNumber();
261
}
262
263
264
int
265
Lane::getLastStepHaltingNumber(const std::string& laneID) {
266
const MSLane* lane = getLane(laneID);
267
int halting = 0;
268
const MSLane::VehCont& vehs = lane->getVehiclesSecure();
269
for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
270
if ((*j)->getSpeed() < SUMO_const_haltingSpeed) {
271
++halting;
272
}
273
}
274
lane->releaseVehicles();
275
return halting;
276
}
277
278
279
std::vector<std::string>
280
Lane::getLastStepVehicleIDs(const std::string& laneID) {
281
const MSLane* lane = getLane(laneID);
282
std::vector<std::string> vehIDs;
283
const MSLane::VehCont& vehs = lane->getVehiclesSecure();
284
for (MSLane::VehCont::const_iterator j = vehs.begin(); j != vehs.end(); ++j) {
285
vehIDs.push_back((*j)->getID());
286
}
287
lane->releaseVehicles();
288
return vehIDs;
289
}
290
291
292
std::vector<std::string>
293
Lane::getFoes(const std::string& laneID, const std::string& toLaneID) {
294
if (toLaneID == "") {
295
return getInternalFoes(laneID);
296
}
297
std::vector<std::string> foeIDs;
298
const MSLink* const link = getLane(laneID)->getLinkTo(getLane(toLaneID));
299
if (link == nullptr) {
300
throw TraCIException("No connection from lane '" + laneID + "' to lane '" + toLaneID + "'");
301
}
302
for (const MSLink* foe : link->getFoeLinks()) {
303
foeIDs.push_back(foe->getLaneBefore()->getID());
304
}
305
return foeIDs;
306
}
307
308
309
std::vector<std::string>
310
Lane::getInternalFoes(const std::string& laneID) {
311
const MSLane* lane = getLane(laneID);
312
const std::vector<const MSLane*>* foeLanes;
313
std::vector<const MSLane*>::const_iterator it;
314
std::vector<std::string> foeIDs;
315
316
if ((lane->isInternal() || lane->isCrossing()) && lane->getLinkCont().size() > 0) {
317
MSLink* link = lane->getLinkCont().front();
318
foeLanes = &link->getFoeLanes();
319
320
for (it = foeLanes->begin(); foeLanes->end() != it; ++it) {
321
foeIDs.push_back((*it)->getID());
322
}
323
}
324
return foeIDs;
325
}
326
327
328
const std::vector<std::string>
329
Lane::getPendingVehicles(const std::string& laneID) {
330
MSLane* const l = getLane(laneID); // validate laneID
331
std::vector<std::string> vehIDs;
332
for (const SUMOVehicle* veh : MSNet::getInstance()->getInsertionControl().getPendingVehicles()) {
333
if (veh->getLane() == l) {
334
vehIDs.push_back(veh->getID());
335
}
336
}
337
return vehIDs;
338
}
339
340
341
double
342
Lane::getAngle(const std::string& laneID, double relativePosition) {
343
double angle;
344
MSLane* lane = getLane(laneID);
345
if (relativePosition == libsumo::INVALID_DOUBLE_VALUE) {
346
Position start = lane->getShape().front();
347
Position end = lane->getShape().back();
348
angle = start.angleTo2D(end);
349
} else {
350
angle = lane->getShape().rotationAtOffset(lane->interpolateLanePosToGeometryPos(relativePosition));
351
}
352
353
return GeomHelper::naviDegree(angle);
354
}
355
356
357
std::string
358
Lane::getBidiLane(const std::string& laneID) {
359
const MSLane* bidi = getLane(laneID)->getBidiLane();
360
return bidi == nullptr ? "" : bidi->getID();
361
}
362
363
void
364
Lane::setAllowed(const std::string& laneID, std::string allowedClass) {
365
setAllowed(laneID, std::vector<std::string>({allowedClass}));
366
}
367
368
369
void
370
Lane::setAllowed(const std::string& laneID, std::vector<std::string> allowedClasses) {
371
MSLane* const l = getLane(laneID);
372
l->setPermissions(parseVehicleClasses(allowedClasses), MSLane::CHANGE_PERMISSIONS_PERMANENT);
373
l->getEdge().rebuildAllowedLanes(false, true);
374
}
375
376
377
void
378
Lane::setDisallowed(const std::string& laneID, std::string disallowedClasses) {
379
setDisallowed(laneID, std::vector<std::string>({disallowedClasses}));
380
}
381
382
383
void
384
Lane::setDisallowed(const std::string& laneID, std::vector<std::string> disallowedClasses) {
385
MSLane* const l = getLane(laneID);
386
l->setPermissions(invertPermissions(parseVehicleClasses(disallowedClasses)), MSLane::CHANGE_PERMISSIONS_PERMANENT); // negation yields allowed
387
l->getEdge().rebuildAllowedLanes(false, true);
388
}
389
390
391
void
392
Lane::setChangePermissions(const std::string& laneID, std::vector<std::string> allowedClasses, const int direction) {
393
MSLane* const l = getLane(laneID);
394
if (direction == libsumo::LANECHANGE_LEFT) {
395
l->setChangeLeft(parseVehicleClasses(allowedClasses));
396
} else if (direction == libsumo::LANECHANGE_RIGHT) {
397
l->setChangeRight(parseVehicleClasses(allowedClasses));
398
} else {
399
throw TraCIException("Invalid direction for change permission (must be " + toString(libsumo::LANECHANGE_LEFT) + " or " + toString(libsumo::LANECHANGE_RIGHT));
400
}
401
}
402
403
404
void
405
Lane::setMaxSpeed(const std::string& laneID, double speed) {
406
getLane(laneID)->setMaxSpeed(speed, false, true);
407
}
408
409
410
void
411
Lane::setLength(const std::string& laneID, double length) {
412
getLane(laneID)->setLength(length);
413
}
414
415
416
void
417
Lane::setFriction(const std::string& laneID, double friction) {
418
getLane(laneID)->setFrictionCoefficient(friction);
419
}
420
421
422
std::string
423
Lane::getParameter(const std::string& laneID, const std::string& param) {
424
return getLane(laneID)->getParameter(param, "");
425
}
426
427
428
LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Lane)
429
430
431
void
432
Lane::setParameter(const std::string& laneID, const std::string& key, const std::string& value) {
433
getLane(laneID)->setParameter(key, value);
434
}
435
436
437
LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Lane, LANE)
438
439
440
MSLane*
441
Lane::getLane(const std::string& id) {
442
MSLane* const lane = MSLane::dictionary(id);
443
if (lane == nullptr) {
444
throw TraCIException("Lane '" + id + "' is not known");
445
}
446
return lane;
447
}
448
449
450
void
451
Lane::storeShape(const std::string& id, PositionVector& shape) {
452
shape = getLane(id)->getShape();
453
}
454
455
456
std::shared_ptr<VariableWrapper>
457
Lane::makeWrapper() {
458
return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
459
}
460
461
462
bool
463
Lane::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
464
switch (variable) {
465
case TRACI_ID_LIST:
466
return wrapper->wrapStringList(objID, variable, getIDList());
467
case ID_COUNT:
468
return wrapper->wrapInt(objID, variable, getIDCount());
469
case LANE_LINK_NUMBER:
470
return wrapper->wrapInt(objID, variable, getLinkNumber(objID));
471
case LANE_EDGE_ID:
472
return wrapper->wrapString(objID, variable, getEdgeID(objID));
473
case VAR_LENGTH:
474
return wrapper->wrapDouble(objID, variable, getLength(objID));
475
case VAR_MAXSPEED:
476
return wrapper->wrapDouble(objID, variable, getMaxSpeed(objID));
477
case VAR_FRICTION:
478
return wrapper->wrapDouble(objID, variable, getFriction(objID));
479
case LANE_ALLOWED:
480
return wrapper->wrapStringList(objID, variable, getAllowed(objID));
481
case LANE_DISALLOWED:
482
return wrapper->wrapStringList(objID, variable, getDisallowed(objID));
483
case LANE_CHANGES:
484
return wrapper->wrapStringList(objID, variable, getChangePermissions(objID, StoHelp::readTypedByte(*paramData)));
485
case VAR_CO2EMISSION:
486
return wrapper->wrapDouble(objID, variable, getCO2Emission(objID));
487
case VAR_COEMISSION:
488
return wrapper->wrapDouble(objID, variable, getCOEmission(objID));
489
case VAR_HCEMISSION:
490
return wrapper->wrapDouble(objID, variable, getHCEmission(objID));
491
case VAR_PMXEMISSION:
492
return wrapper->wrapDouble(objID, variable, getPMxEmission(objID));
493
case VAR_NOXEMISSION:
494
return wrapper->wrapDouble(objID, variable, getNOxEmission(objID));
495
case VAR_FUELCONSUMPTION:
496
return wrapper->wrapDouble(objID, variable, getFuelConsumption(objID));
497
case VAR_NOISEEMISSION:
498
return wrapper->wrapDouble(objID, variable, getNoiseEmission(objID));
499
case VAR_ELECTRICITYCONSUMPTION:
500
return wrapper->wrapDouble(objID, variable, getElectricityConsumption(objID));
501
case LAST_STEP_VEHICLE_NUMBER:
502
return wrapper->wrapInt(objID, variable, getLastStepVehicleNumber(objID));
503
case LAST_STEP_MEAN_SPEED:
504
return wrapper->wrapDouble(objID, variable, getLastStepMeanSpeed(objID));
505
case LAST_STEP_VEHICLE_ID_LIST:
506
return wrapper->wrapStringList(objID, variable, getLastStepVehicleIDs(objID));
507
case LAST_STEP_OCCUPANCY:
508
return wrapper->wrapDouble(objID, variable, getLastStepOccupancy(objID));
509
case LAST_STEP_VEHICLE_HALTING_NUMBER:
510
return wrapper->wrapInt(objID, variable, getLastStepHaltingNumber(objID));
511
case LAST_STEP_LENGTH:
512
return wrapper->wrapDouble(objID, variable, getLastStepLength(objID));
513
case VAR_WAITING_TIME:
514
return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
515
case VAR_CURRENT_TRAVELTIME:
516
return wrapper->wrapDouble(objID, variable, getTraveltime(objID));
517
case VAR_WIDTH:
518
return wrapper->wrapDouble(objID, variable, getWidth(objID));
519
case VAR_SHAPE:
520
return wrapper->wrapPositionVector(objID, variable, getShape(objID));
521
case VAR_PENDING_VEHICLES:
522
return wrapper->wrapStringList(objID, variable, getPendingVehicles(objID));
523
case VAR_ANGLE:
524
return wrapper->wrapDouble(objID, variable, getAngle(objID, StoHelp::readTypedDouble(*paramData)));
525
case VAR_BIDI:
526
return wrapper->wrapString(objID, variable, getBidiLane(objID));
527
case VAR_FOES:
528
return wrapper->wrapStringList(objID, variable, getFoes(objID, StoHelp::readTypedString(*paramData)));
529
case LANE_LINKS:
530
return wrapper->wrapConnectionVector(objID, variable, getLinks(objID));
531
case VAR_PARAMETER:
532
return wrapper->wrapString(objID, variable, getParameter(objID, StoHelp::readTypedString(*paramData)));
533
case VAR_PARAMETER_WITH_KEY:
534
return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, StoHelp::readTypedString(*paramData)));
535
default:
536
return false;
537
}
538
}
539
}
540
541
542
/****************************************************************************/
543
544