Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/libsumo/Person.cpp
169666 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 Person.cpp
15
/// @author Leonhard Luecken
16
/// @date 15.09.2017
17
///
18
// C++ TraCI client API implementation
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <microsim/transportables/MSTransportableControl.h>
23
#include <microsim/MSVehicleControl.h>
24
#include <microsim/MSEdge.h>
25
#include <microsim/MSLane.h>
26
#include <microsim/MSNet.h>
27
#include <microsim/MSStoppingPlace.h>
28
#include <microsim/transportables/MSPModel.h>
29
#include <microsim/transportables/MSPerson.h>
30
#include <microsim/transportables/MSStageDriving.h>
31
#include <microsim/transportables/MSStageWaiting.h>
32
#include <microsim/transportables/MSStageWalking.h>
33
#include <microsim/transportables/MSStageTrip.h>
34
#include <microsim/devices/MSDevice_Taxi.h>
35
#include <microsim/devices/MSDispatch_TraCI.h>
36
#include <libsumo/TraCIConstants.h>
37
#include <utils/geom/GeomHelper.h>
38
#include <utils/common/StringTokenizer.h>
39
#include <utils/common/SUMOTime.h>
40
#include <utils/emissions/PollutantsInterface.h>
41
#include <utils/router/PedestrianRouter.h>
42
#include <utils/vehicle/SUMOVehicleParserHelper.h>
43
#include "Helper.h"
44
#include "StorageHelper.h"
45
#include "VehicleType.h"
46
#include "Person.h"
47
48
#define FAR_AWAY 1000.0
49
50
//#define DEBUG_MOVEXY
51
//#define DEBUG_MOVEXY_ANGLE
52
53
namespace libsumo {
54
// ===========================================================================
55
// static member initializations
56
// ===========================================================================
57
SubscriptionResults Person::mySubscriptionResults;
58
ContextSubscriptionResults Person::myContextSubscriptionResults;
59
60
61
// ===========================================================================
62
// static member definitions
63
// ===========================================================================
64
std::vector<std::string>
65
Person::getIDList() {
66
MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
67
std::vector<std::string> ids;
68
for (MSTransportableControl::constVehIt i = c.loadedBegin(); i != c.loadedEnd(); ++i) {
69
if (i->second->getCurrentStageType() != MSStageType::WAITING_FOR_DEPART) {
70
ids.push_back(i->first);
71
}
72
}
73
return ids;
74
}
75
76
77
int
78
Person::getIDCount() {
79
return MSNet::getInstance()->getPersonControl().size();
80
}
81
82
83
TraCIPosition
84
Person::getPosition(const std::string& personID, const bool includeZ) {
85
return Helper::makeTraCIPosition(getPerson(personID)->getPosition(), includeZ);
86
}
87
88
89
TraCIPosition
90
Person::getPosition3D(const std::string& personID) {
91
return Helper::makeTraCIPosition(getPerson(personID)->getPosition(), true);
92
}
93
94
95
double
96
Person::getAngle(const std::string& personID) {
97
return GeomHelper::naviDegree(getPerson(personID)->getAngle());
98
}
99
100
101
double
102
Person::getSlope(const std::string& personID) {
103
MSPerson* person = getPerson(personID);
104
const double ep = person->getEdgePos();
105
const MSLane* lane = getSidewalk<MSEdge, MSLane>(person->getEdge());
106
if (lane == nullptr) {
107
lane = person->getEdge()->getLanes()[0];
108
}
109
const double gp = lane->interpolateLanePosToGeometryPos(ep);
110
return lane->getShape().slopeDegreeAtOffset(gp);
111
}
112
113
114
double
115
Person::getSpeed(const std::string& personID) {
116
return getPerson(personID)->getSpeed();
117
}
118
119
120
std::string
121
Person::getRoadID(const std::string& personID) {
122
return getPerson(personID)->getEdge()->getID();
123
}
124
125
126
std::string
127
Person::getLaneID(const std::string& personID) {
128
return Named::getIDSecure(getPerson(personID)->getLane(), "");
129
}
130
131
132
double
133
Person::getLanePosition(const std::string& personID) {
134
return getPerson(personID)->getEdgePos();
135
}
136
137
138
double
139
Person::getWalkingDistance(const std::string& personID, const std::string& edgeID, double pos, int laneIndex) {
140
MSPerson* p = getPerson(personID);
141
if (p->getCurrentStageType() == MSStageType::WALKING) {
142
const MSStageWalking* walk = dynamic_cast<const MSStageWalking*>(p->getCurrentStage());
143
ConstMSEdgeVector edges = walk->getEdges();
144
edges.erase(edges.begin(), edges.begin() + walk->getRoutePosition());
145
const MSLane* lane = Helper::getLaneChecking(edgeID, laneIndex, pos);
146
auto it = std::find(edges.begin(), edges.end(), &lane->getEdge());
147
if (it == edges.end()) {
148
// Vehicle would return INVALID_DOUBLE_VALUE;
149
throw TraCIException(TLF("Edge '%' does not occur within the remaining walk of person '%'.", edgeID, personID));
150
151
}
152
edges.erase(it + 1, edges.end());
153
double distance = 0;
154
MSPedestrianRouter& router = MSNet::getInstance()->getPedestrianRouter(0);
155
router.recomputeWalkCosts(edges, p->getMaxSpeed(), p->getEdgePos(), pos, SIMSTEP, distance);
156
if (distance == std::numeric_limits<double>::max()) {
157
return INVALID_DOUBLE_VALUE;
158
}
159
return distance;
160
} else {
161
// Vehicle would return INVALID_DOUBLE_VALUE;
162
throw TraCIException(TLF("Person '%' is not walking", personID));
163
}
164
}
165
166
167
double
168
Person::getWalkingDistance2D(const std::string& personID, double x, double y) {
169
MSPerson* p = getPerson(personID);
170
std::pair<MSLane*, double> roadPos = Helper::convertCartesianToRoadMap(Position(x, y), p->getVehicleType().getVehicleClass());
171
return getWalkingDistance(personID, roadPos.first->getEdge().getID(), roadPos.second, roadPos.first->getIndex());
172
}
173
174
175
176
std::vector<TraCIReservation>
177
Person::getTaxiReservations(int onlyNew) {
178
std::vector<TraCIReservation> result;
179
MSDispatch* dispatcher = MSDevice_Taxi::getDispatchAlgorithm();
180
if (dispatcher != nullptr) {
181
for (Reservation* res : dispatcher->getReservations()) {
182
if (filterReservation(onlyNew, res, result)) {
183
if (res->state == Reservation::NEW) {
184
res->state = Reservation::RETRIEVED;
185
}
186
}
187
}
188
const bool includeRunning = onlyNew == 0 || (onlyNew & (Reservation::ASSIGNED | Reservation::ONBOARD)) != 0;
189
if (includeRunning) {
190
for (const Reservation* res : dispatcher->getRunningReservations()) {
191
filterReservation(onlyNew, res, result);
192
}
193
}
194
}
195
std::sort(result.begin(), result.end(), reservation_by_id_sorter());
196
return result;
197
}
198
199
int
200
Person::reservation_by_id_sorter::operator()(const TraCIReservation& r1, const TraCIReservation& r2) const {
201
return r1.id < r2.id;
202
}
203
204
205
std::string
206
Person::splitTaxiReservation(std::string reservationID, const std::vector<std::string>& personIDs) {
207
MSDispatch* dispatcher = MSDevice_Taxi::getDispatchAlgorithm();
208
if (dispatcher != nullptr) {
209
MSDispatch_TraCI* traciDispatcher = dynamic_cast<MSDispatch_TraCI*>(dispatcher);
210
if (traciDispatcher != nullptr) {
211
return traciDispatcher->splitReservation(reservationID, personIDs);
212
}
213
}
214
throw TraCIException("device.taxi.dispatch-algorithm 'traci' has not been loaded");
215
}
216
217
bool
218
Person::filterReservation(int onlyNew, const Reservation* res, std::vector<libsumo::TraCIReservation>& reservations) {
219
if (onlyNew != 0 && (onlyNew & res->state) == 0) {
220
return false;
221
}
222
std::vector<std::string> personIDs;
223
for (const MSTransportable* p : res->persons) {
224
personIDs.push_back(p->getID());
225
}
226
std::sort(personIDs.begin(), personIDs.end());
227
reservations.push_back(TraCIReservation(res->id,
228
personIDs,
229
res->group,
230
res->from->getID(),
231
res->to->getID(),
232
res->fromPos,
233
res->toPos,
234
STEPS2TIME(res->pickupTime),
235
STEPS2TIME(res->reservationTime),
236
res->state
237
));
238
return true;
239
}
240
241
242
TraCIColor
243
Person::getColor(const std::string& personID) {
244
const RGBColor& col = getPerson(personID)->getParameter().color;
245
TraCIColor tcol;
246
tcol.r = col.red();
247
tcol.g = col.green();
248
tcol.b = col.blue();
249
tcol.a = col.alpha();
250
return tcol;
251
}
252
253
254
std::string
255
Person::getTypeID(const std::string& personID) {
256
return getPerson(personID)->getVehicleType().getID();
257
}
258
259
260
double
261
Person::getWaitingTime(const std::string& personID) {
262
return getPerson(personID)->getWaitingSeconds();
263
}
264
265
266
std::string
267
Person::getNextEdge(const std::string& personID) {
268
return getPerson(personID)->getNextEdge();
269
}
270
271
272
std::vector<std::string>
273
Person::getEdges(const std::string& personID, int nextStageIndex) {
274
MSTransportable* p = getPerson(personID);
275
if (nextStageIndex >= p->getNumRemainingStages()) {
276
throw TraCIException("The stage index must be lower than the number of remaining stages.");
277
}
278
if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
279
throw TraCIException("The negative stage index must refer to a valid previous stage.");
280
}
281
std::vector<std::string> edgeIDs;
282
for (auto& e : p->getNextStage(nextStageIndex)->getEdges()) {
283
if (e != nullptr) {
284
edgeIDs.push_back(e->getID());
285
}
286
}
287
return edgeIDs;
288
}
289
290
291
TraCIStage
292
Person::getStage(const std::string& personID, int nextStageIndex) {
293
MSTransportable* p = getPerson(personID);
294
TraCIStage result;
295
if (nextStageIndex >= p->getNumRemainingStages()) {
296
throw TraCIException("The stage index must be lower than the number of remaining stages.");
297
}
298
if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
299
throw TraCIException("The negative stage index " + toString(nextStageIndex) + " must refer to a valid previous stage.");
300
}
301
//stageType, arrivalPos, edges, destStop, vType, and description can be retrieved directly from the base Stage class.
302
MSStage* stage = p->getNextStage(nextStageIndex);
303
result.type = (int)stage->getStageType();
304
result.arrivalPos = stage->getArrivalPos();
305
for (auto e : stage->getEdges()) {
306
if (e != nullptr) {
307
result.edges.push_back(e->getID());
308
}
309
}
310
MSStoppingPlace* destinationStop = stage->getDestinationStop();
311
if (destinationStop != nullptr) {
312
result.destStop = destinationStop->getID();
313
}
314
result.description = stage->getStageDescription(p->isPerson());
315
result.length = stage->getDistance();
316
if (result.length == -1.) {
317
result.length = INVALID_DOUBLE_VALUE;
318
}
319
result.departPos = INVALID_DOUBLE_VALUE;
320
result.cost = INVALID_DOUBLE_VALUE;
321
result.depart = stage->getDeparted() >= 0 ? STEPS2TIME(stage->getDeparted()) : INVALID_DOUBLE_VALUE;
322
result.travelTime = INVALID_DOUBLE_VALUE;
323
if (stage->getArrived() >= 0) {
324
result.travelTime = STEPS2TIME(stage->getArrived() - stage->getDeparted());
325
} else if (stage->getDeparted() >= 0) {
326
result.travelTime = STEPS2TIME(SIMSTEP - stage->getDeparted());
327
}
328
329
// Some stage type dependant attributes
330
switch (stage->getStageType()) {
331
case MSStageType::DRIVING: {
332
MSStageDriving* const drivingStage = static_cast<MSStageDriving*>(stage);
333
result.vType = drivingStage->getVehicleType();
334
result.intended = drivingStage->getIntendedVehicleID();
335
if (result.depart < 0 && drivingStage->getIntendedDepart() >= 0) {
336
result.depart = STEPS2TIME(drivingStage->getIntendedDepart());
337
}
338
const std::set<std::string> lines = drivingStage->getLines();
339
for (auto line = lines.begin(); line != lines.end(); line++) {
340
if (line != lines.begin()) {
341
result.line += " ";
342
}
343
result.line += *line;
344
}
345
break;
346
}
347
case MSStageType::WALKING: {
348
auto* walkingStage = (MSStageWalking*) stage;
349
result.departPos = walkingStage->getDepartPos();
350
break;
351
}
352
case MSStageType::WAITING: {
353
auto* waitingStage = (MSStageWaiting*) stage;
354
if (waitingStage->getPlannedDuration() > 0) {
355
result.travelTime = STEPS2TIME(waitingStage->getPlannedDuration());
356
}
357
break;
358
}
359
default:
360
break;
361
}
362
return result;
363
}
364
365
366
int
367
Person::getRemainingStages(const std::string& personID) {
368
return getPerson(personID)->getNumRemainingStages();
369
}
370
371
372
std::string
373
Person::getVehicle(const std::string& personID) {
374
const SUMOVehicle* veh = getPerson(personID)->getVehicle();
375
if (veh == nullptr) {
376
return "";
377
} else {
378
return veh->getID();
379
}
380
}
381
382
383
std::string
384
Person::getParameter(const std::string& personID, const std::string& param) {
385
return getPerson(personID)->getParameter().getParameter(param, "");
386
}
387
388
389
LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Person)
390
391
392
std::string
393
Person::getEmissionClass(const std::string& personID) {
394
return PollutantsInterface::getName(getPerson(personID)->getVehicleType().getEmissionClass());
395
}
396
397
398
std::string
399
Person::getShapeClass(const std::string& personID) {
400
return getVehicleShapeName(getPerson(personID)->getVehicleType().getGuiShape());
401
}
402
403
404
double
405
Person::getLength(const std::string& personID) {
406
return getPerson(personID)->getVehicleType().getLength();
407
}
408
409
410
double
411
Person::getSpeedFactor(const std::string& personID) {
412
return getPerson(personID)->getChosenSpeedFactor();
413
}
414
415
416
double
417
Person::getAccel(const std::string& personID) {
418
return getPerson(personID)->getVehicleType().getCarFollowModel().getMaxAccel();
419
}
420
421
422
double
423
Person::getDecel(const std::string& personID) {
424
return getPerson(personID)->getVehicleType().getCarFollowModel().getMaxDecel();
425
}
426
427
428
double Person::getEmergencyDecel(const std::string& personID) {
429
return getPerson(personID)->getVehicleType().getCarFollowModel().getEmergencyDecel();
430
}
431
432
433
double Person::getApparentDecel(const std::string& personID) {
434
return getPerson(personID)->getVehicleType().getCarFollowModel().getApparentDecel();
435
}
436
437
438
double Person::getActionStepLength(const std::string& personID) {
439
return getPerson(personID)->getVehicleType().getActionStepLengthSecs();
440
}
441
442
443
double
444
Person::getTau(const std::string& personID) {
445
return getPerson(personID)->getVehicleType().getCarFollowModel().getHeadwayTime();
446
}
447
448
449
double
450
Person::getImperfection(const std::string& personID) {
451
return getPerson(personID)->getVehicleType().getCarFollowModel().getImperfection();
452
}
453
454
455
double
456
Person::getSpeedDeviation(const std::string& personID) {
457
return getPerson(personID)->getVehicleType().getSpeedFactor().getParameter(1);
458
}
459
460
461
std::string
462
Person::getVehicleClass(const std::string& personID) {
463
return toString(getPerson(personID)->getVehicleType().getVehicleClass());
464
}
465
466
467
double
468
Person::getMinGap(const std::string& personID) {
469
return getPerson(personID)->getVehicleType().getMinGap();
470
}
471
472
473
double
474
Person::getMinGapLat(const std::string& personID) {
475
return getPerson(personID)->getVehicleType().getMinGapLat();
476
}
477
478
479
double
480
Person::getMaxSpeed(const std::string& personID) {
481
return getPerson(personID)->getMaxSpeed();
482
}
483
484
485
double
486
Person::getMaxSpeedLat(const std::string& personID) {
487
return getPerson(personID)->getVehicleType().getMaxSpeedLat();
488
}
489
490
491
std::string
492
Person::getLateralAlignment(const std::string& personID) {
493
return toString(getPerson(personID)->getVehicleType().getPreferredLateralAlignment());
494
}
495
496
497
double
498
Person::getWidth(const std::string& personID) {
499
return getPerson(personID)->getVehicleType().getWidth();
500
}
501
502
503
double
504
Person::getHeight(const std::string& personID) {
505
return getPerson(personID)->getVehicleType().getHeight();
506
}
507
508
509
double
510
Person::getMass(const std::string& personID) {
511
return getPerson(personID)->getVehicleType().getMass();
512
}
513
514
515
int
516
Person::getPersonCapacity(const std::string& personID) {
517
return getPerson(personID)->getVehicleType().getPersonCapacity();
518
}
519
520
521
double
522
Person::getBoardingDuration(const std::string& personID) {
523
return STEPS2TIME(getPerson(personID)->getVehicleType().getBoardingDuration(true));
524
}
525
526
527
double
528
Person::getImpatience(const std::string& personID) {
529
return getPerson(personID)->getImpatience();
530
}
531
532
533
void
534
Person::setSpeed(const std::string& personID, double speed) {
535
getPerson(personID)->setSpeed(speed);
536
}
537
538
539
void
540
Person::setType(const std::string& personID, const std::string& typeID) {
541
MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
542
if (vehicleType == nullptr) {
543
throw TraCIException("The vehicle type '" + typeID + "' is not known.");
544
}
545
getPerson(personID)->replaceVehicleType(vehicleType);
546
}
547
548
549
void
550
Person::add(const std::string& personID, const std::string& edgeID, double pos, double departInSecs, const std::string typeID) {
551
MSTransportable* p;
552
try {
553
p = getPerson(personID);
554
} catch (TraCIException&) {
555
p = nullptr;
556
}
557
558
if (p != nullptr) {
559
throw TraCIException("The person " + personID + " to add already exists.");
560
}
561
562
SUMOTime depart = TIME2STEPS(departInSecs);
563
SUMOVehicleParameter vehicleParams;
564
vehicleParams.id = personID;
565
566
MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
567
if (!vehicleType) {
568
throw TraCIException("Invalid type '" + typeID + "' for person '" + personID + "'");
569
}
570
571
const MSEdge* edge = MSEdge::dictionary(edgeID);
572
if (!edge) {
573
throw TraCIException("Invalid edge '" + edgeID + "' for person: '" + personID + "'");
574
}
575
576
if (departInSecs < 0.) {
577
const int proc = (int) - departInSecs;
578
if (proc >= static_cast<int>(DepartDefinition::DEF_MAX)) {
579
throw TraCIException("Invalid departure time." + toString(depart) + " " + toString(proc));
580
}
581
vehicleParams.departProcedure = (DepartDefinition)proc;
582
vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
583
} else if (depart < MSNet::getInstance()->getCurrentTimeStep()) {
584
vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
585
WRITE_WARNINGF(TL("Departure time=% for person '%' is in the past; using current time=% instead."),
586
toString(departInSecs), personID, time2string(vehicleParams.depart));
587
} else {
588
vehicleParams.depart = depart;
589
}
590
591
vehicleParams.departPosProcedure = DepartPosDefinition::GIVEN;
592
if (fabs(pos) > edge->getLength()) {
593
throw TraCIException("Invalid departure position.");
594
}
595
if (pos < 0) {
596
pos += edge->getLength();
597
}
598
vehicleParams.departPos = pos;
599
600
SUMOVehicleParameter* params = new SUMOVehicleParameter(vehicleParams);
601
MSTransportable::MSTransportablePlan* plan = new MSTransportable::MSTransportablePlan();
602
plan->push_back(new MSStageWaiting(edge, nullptr, 0, depart, pos, "awaiting departure", true));
603
604
try {
605
MSTransportable* person = MSNet::getInstance()->getPersonControl().buildPerson(params, vehicleType, plan, nullptr);
606
MSNet::getInstance()->getPersonControl().add(person);
607
} catch (ProcessError& e) {
608
delete params;
609
delete plan;
610
throw TraCIException(e.what());
611
}
612
}
613
614
MSStage*
615
Person::convertTraCIStage(const TraCIStage& stage, const std::string personID) {
616
MSStoppingPlace* bs = nullptr;
617
if (!stage.destStop.empty()) {
618
bs = MSNet::getInstance()->getStoppingPlace(stage.destStop);
619
if (bs == nullptr) {
620
throw TraCIException("Invalid stopping place id '" + stage.destStop + "' for person: '" + personID + "'");
621
}
622
}
623
switch (stage.type) {
624
case STAGE_DRIVING: {
625
if (stage.edges.empty()) {
626
throw TraCIException("The stage should have at least one edge");
627
}
628
std::string toId = stage.edges.back();
629
MSEdge* to = MSEdge::dictionary(toId);
630
if (!to) {
631
throw TraCIException("Invalid edge '" + toId + "' for person: '" + personID + "'");
632
}
633
//std::string fromId = stage.edges.front();
634
//MSEdge* from = MSEdge::dictionary(fromId);
635
//if (!from) {
636
// throw TraCIException("Invalid edge '" + fromId + "' for person: '" + personID + "'");
637
//}
638
if (stage.line.empty()) {
639
throw TraCIException("Empty lines parameter for person: '" + personID + "'");
640
}
641
double arrivalPos = stage.arrivalPos;
642
if (arrivalPos == INVALID_DOUBLE_VALUE) {
643
if (bs != nullptr) {
644
arrivalPos = bs->getEndLanePosition();
645
} else {
646
arrivalPos = to->getLength();
647
}
648
}
649
return new MSStageDriving(nullptr, to, bs, arrivalPos, 0.0, StringTokenizer(stage.line).getVector());
650
}
651
652
case STAGE_WALKING: {
653
MSTransportable* p = getPerson(personID);
654
ConstMSEdgeVector edges;
655
try {
656
MSEdge::parseEdgesList(stage.edges, edges, "<unknown>");
657
} catch (ProcessError& e) {
658
throw TraCIException(e.what());
659
}
660
if (edges.empty()) {
661
throw TraCIException("Empty edge list for walking stage of person '" + personID + "'.");
662
}
663
double arrivalPos = stage.arrivalPos;
664
if (fabs(arrivalPos) > edges.back()->getLength()) {
665
throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
666
}
667
if (arrivalPos < 0) {
668
arrivalPos += edges.back()->getLength();
669
}
670
return new MSStageWalking(p->getID(), edges, bs, -1, -1, p->getArrivalPos(), arrivalPos, MSPModel::UNSPECIFIED_POS_LAT);
671
}
672
673
case STAGE_WAITING: {
674
MSTransportable* p = getPerson(personID);
675
if (stage.travelTime < 0) {
676
throw TraCIException("Duration for person: '" + personID + "' must not be negative");
677
}
678
return new MSStageWaiting(p->getArrivalEdge(), nullptr, TIME2STEPS(stage.travelTime), 0, p->getArrivalPos(), stage.description, false);
679
}
680
case STAGE_TRIP: {
681
MSTransportable* p = getPerson(personID);
682
ConstMSEdgeVector edges;
683
try {
684
MSEdge::parseEdgesList(stage.edges, edges, "<unknown>");
685
} catch (ProcessError& e) {
686
throw TraCIException(e.what());
687
}
688
if ((edges.size() == 0 && bs == nullptr) || edges.size() > 1) {
689
throw TraCIException("A trip should be defined with a destination edge or a destination stop for person '" + personID + "'.");
690
}
691
const MSEdge* to = nullptr;
692
if (bs != nullptr) {
693
to = &bs->getLane().getEdge();
694
if (edges.size() > 0 && to != edges.back()) {
695
throw TraCIException("Mismatching destination edge and destination stop edge for person '" + personID + "'.");
696
}
697
} else {
698
to = edges.back();
699
}
700
SVCPermissions modeSet = 0;
701
MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl();
702
for (std::string vtypeid : StringTokenizer(stage.vType).getVector()) {
703
const MSVehicleType* const vType = vehControl.getVType(vtypeid);
704
if (vType == nullptr) {
705
throw TraCIException("The vehicle type '" + vtypeid + "' in a trip for person '" + personID + "' is not known.");
706
}
707
modeSet |= (vType->getVehicleClass() == SVC_BICYCLE) ? SVC_BICYCLE : SVC_PASSENGER;
708
}
709
if (stage.line.empty()) {
710
modeSet = p->getParameter().modes;
711
} else {
712
std::string errorMsg;
713
if (!SUMOVehicleParameter::parsePersonModes(stage.line, "person", personID, modeSet, errorMsg)) {
714
throw TraCIException(errorMsg);
715
}
716
}
717
bool hasArrivalPos = stage.arrivalPos != INVALID_DOUBLE_VALUE;
718
double arrivalPos = stage.arrivalPos;
719
if (hasArrivalPos) {
720
if (fabs(arrivalPos) > to->getLength()) {
721
throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
722
}
723
if (arrivalPos < 0) {
724
arrivalPos += to->getLength();
725
}
726
}
727
const MSStage* cur = p->getCurrentStage();
728
double walkfactor = OptionsCont::getOptions().getFloat("persontrip.walkfactor");
729
std::string group = stage.intended; //OptionsCont::getOptions().getString("persontrip.default.group");
730
const SUMOTime duration = -1;
731
const double speed = -1;
732
return new MSStageTrip(cur->getDestination(), cur->getDestinationStop(), to, bs,
733
duration, modeSet, stage.vType, speed, walkfactor, group,
734
MSPModel::UNSPECIFIED_POS_LAT, hasArrivalPos, arrivalPos);
735
}
736
default:
737
return nullptr;
738
}
739
}
740
741
742
void
743
Person::appendStage(const std::string& personID, const TraCIStage& stage) {
744
MSTransportable* p = getPerson(personID);
745
MSStage* personStage = convertTraCIStage(stage, personID);
746
p->appendStage(personStage);
747
}
748
749
750
void
751
Person::replaceStage(const std::string& personID, const int stageIndex, const TraCIStage& stage) {
752
MSTransportable* p = getPerson(personID);
753
if (stageIndex >= p->getNumRemainingStages()) {
754
throw TraCIException("Specified stage index: is not valid for person " + personID);
755
}
756
MSStage* personStage = convertTraCIStage(stage, personID);
757
// removing the current stage triggers abort+proceed so the replacement
758
// stage must be ready beforehand
759
p->appendStage(personStage, stageIndex + 1);
760
p->removeStage(stageIndex);
761
}
762
763
764
void
765
Person::appendDrivingStage(const std::string& personID, const std::string& toEdge, const std::string& lines, const std::string& stopID) {
766
MSTransportable* p = getPerson(personID);
767
const MSEdge* edge = MSEdge::dictionary(toEdge);
768
if (!edge) {
769
throw TraCIException("Invalid edge '" + toEdge + "' for person: '" + personID + "'");
770
}
771
if (lines.size() == 0) {
772
throw TraCIException("Empty lines parameter for person: '" + personID + "'");
773
}
774
MSStoppingPlace* bs = nullptr;
775
if (stopID != "") {
776
bs = MSNet::getInstance()->getStoppingPlace(stopID);
777
if (bs == nullptr) {
778
throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
779
}
780
}
781
p->appendStage(new MSStageDriving(nullptr, edge, bs, edge->getLength() - NUMERICAL_EPS, 0.0, StringTokenizer(lines).getVector()));
782
}
783
784
785
void
786
Person::appendWaitingStage(const std::string& personID, double duration, const std::string& description, const std::string& stopID) {
787
MSTransportable* p = getPerson(personID);
788
if (duration < 0) {
789
throw TraCIException("Duration for person: '" + personID + "' must not be negative");
790
}
791
MSStoppingPlace* bs = nullptr;
792
if (stopID != "") {
793
bs = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
794
if (bs == nullptr) {
795
throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
796
}
797
}
798
p->appendStage(new MSStageWaiting(p->getArrivalEdge(), nullptr, TIME2STEPS(duration), 0, p->getArrivalPos(), description, false));
799
}
800
801
802
void
803
Person::appendWalkingStage(const std::string& personID, const std::vector<std::string>& edgeIDs, double arrivalPos, double duration, double speed, const std::string& stopID) {
804
MSTransportable* p = getPerson(personID);
805
ConstMSEdgeVector edges;
806
try {
807
MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
808
} catch (ProcessError& e) {
809
throw TraCIException(e.what());
810
}
811
if (edges.empty()) {
812
throw TraCIException("Empty edge list for walking stage of person '" + personID + "'.");
813
}
814
if (fabs(arrivalPos) > edges.back()->getLength()) {
815
throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
816
}
817
if (arrivalPos < 0) {
818
arrivalPos += edges.back()->getLength();
819
}
820
MSStoppingPlace* bs = nullptr;
821
if (stopID != "") {
822
bs = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
823
if (bs == nullptr) {
824
throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
825
}
826
}
827
p->appendStage(new MSStageWalking(p->getID(), edges, bs, TIME2STEPS(duration), speed, p->getArrivalPos(), arrivalPos, MSPModel::UNSPECIFIED_POS_LAT));
828
}
829
830
831
void
832
Person::removeStage(const std::string& personID, int nextStageIndex) {
833
MSTransportable* p = getPerson(personID);
834
if (nextStageIndex >= p->getNumRemainingStages()) {
835
throw TraCIException("The stage index must be lower than the number of remaining stages.");
836
}
837
if (nextStageIndex < 0) {
838
throw TraCIException("The stage index may not be negative.");
839
}
840
p->removeStage(nextStageIndex);
841
}
842
843
844
void
845
Person::rerouteTraveltime(const std::string& personID) {
846
MSPerson* p = getPerson(personID);
847
if (p->getNumRemainingStages() == 0) {
848
throw TraCIException("Person '" + personID + "' has no remaining stages.");
849
}
850
const MSEdge* from = p->getEdge();
851
double departPos = p->getEdgePos();
852
// reroute to the start of the next-non-walking stage
853
int firstIndex;
854
if (p->getCurrentStageType() == MSStageType::WALKING) {
855
firstIndex = 0;
856
} else if (p->getCurrentStageType() == MSStageType::WAITING) {
857
if (p->getNumRemainingStages() < 2 || p->getStageType(1) != MSStageType::WALKING) {
858
throw TraCIException("Person '" + personID + "' cannot reroute after the current stop.");
859
}
860
firstIndex = 1;
861
} else {
862
throw TraCIException("Person '" + personID + "' cannot reroute in stage type '" + toString((int)p->getCurrentStageType()) + "'.");
863
}
864
int nextIndex = firstIndex + 1;
865
for (; nextIndex < p->getNumRemainingStages(); nextIndex++) {
866
if (p->getStageType(nextIndex) != MSStageType::WALKING) {
867
break;
868
}
869
}
870
MSStage* destStage = p->getNextStage(nextIndex - 1);
871
const MSEdge* to = destStage->getEdges().back();
872
double arrivalPos = destStage->getArrivalPos();
873
double speed = p->getMaxSpeed();
874
ConstMSEdgeVector newEdges;
875
MSNet::getInstance()->getPedestrianRouter(0).compute(from, to, departPos, arrivalPos, speed, 0, nullptr, newEdges);
876
if (newEdges.empty()) {
877
throw TraCIException("Could not find new route for person '" + personID + "'.");
878
}
879
ConstMSEdgeVector oldEdges = p->getNextStage(firstIndex)->getEdges();
880
assert(!oldEdges.empty());
881
if (oldEdges.front()->getFunction() != SumoXMLEdgeFunc::NORMAL) {
882
oldEdges.erase(oldEdges.begin());
883
}
884
//std::cout << " remainingStages=" << p->getNumRemainingStages() << " oldEdges=" << toString(oldEdges) << " newEdges=" << toString(newEdges) << " firstIndex=" << firstIndex << " nextIndex=" << nextIndex << "\n";
885
if (newEdges == oldEdges && (firstIndex + 1 == nextIndex)) {
886
return;
887
}
888
if (newEdges.front() != from) {
889
// @note: maybe this should be done automatically by the router
890
newEdges.insert(newEdges.begin(), from);
891
}
892
p->replaceWalk(newEdges, departPos, firstIndex, nextIndex);
893
}
894
895
896
void
897
Person::moveTo(const std::string& personID, const std::string& laneID, double pos, double posLat) {
898
MSPerson* p = getPerson(personID);
899
MSLane* l = MSLane::dictionary(laneID);
900
if (l == nullptr) {
901
throw TraCIException("Unknown lane '" + laneID + "'.");
902
}
903
if (posLat == INVALID_DOUBLE_VALUE) {
904
posLat = 0;
905
} else if (fabs(posLat) >= (0.5 * (l->getWidth() + p->getVehicleType().getWidth()) + MSPModel::SIDEWALK_OFFSET)) {
906
// see MSPModel_Striping::moveToXY
907
throw TraCIException("Invalid lateral position " + toString(posLat) + " on lane '" + laneID + "'.");
908
}
909
switch (p->getStageType(0)) {
910
case MSStageType::WALKING: {
911
MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
912
assert(s != 0);
913
s->getPState()->moveTo(p, l, pos, posLat, SIMSTEP);
914
break;
915
}
916
default:
917
throw TraCIException("Command moveTo is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + ".");
918
}
919
}
920
921
922
void
923
Person::moveToXY(const std::string& personID, const std::string& edgeID, const double x, const double y, double angle, const int keepRoute, double matchThreshold) {
924
MSPerson* p = getPerson(personID);
925
const bool doKeepRoute = (keepRoute & 1) != 0;
926
const bool mayLeaveNetwork = (keepRoute & 2) != 0;
927
const bool ignorePermissions = (keepRoute & 4) != 0;
928
SUMOVehicleClass vClass = ignorePermissions ? SVC_IGNORING : p->getVClass();
929
Position pos(x, y);
930
#ifdef DEBUG_MOVEXY
931
const double origAngle = angle;
932
#endif
933
// angle must be in [0,360] because it will be compared against those returned by naviDegree()
934
// angle set to INVALID_DOUBLE_VALUE is ignored in the evaluated and later set to the angle of the matched lane
935
if (angle != INVALID_DOUBLE_VALUE) {
936
while (angle >= 360.) {
937
angle -= 360.;
938
}
939
while (angle < 0.) {
940
angle += 360.;
941
}
942
}
943
#ifdef DEBUG_MOVEXY
944
std::cout << std::endl << "begin person " << p->getID() << " lanePos:" << p->getEdgePos() << " edge:" << Named::getIDSecure(p->getEdge()) << "\n";
945
std::cout << " want pos:" << pos << " edgeID:" << edgeID << " origAngle:" << origAngle << " angle:" << angle << " keepRoute:" << keepRoute << std::endl;
946
#endif
947
948
ConstMSEdgeVector edges;
949
MSLane* lane = nullptr;
950
double lanePos;
951
double lanePosLat = 0;
952
double bestDistance = std::numeric_limits<double>::max();
953
int routeOffset = 0;
954
bool found = false;
955
double maxRouteDistance = matchThreshold;
956
957
ConstMSEdgeVector ev;
958
ev.push_back(p->getEdge());
959
int routeIndex = 0;
960
MSLane* currentLane = const_cast<MSLane*>(getSidewalk<MSEdge, MSLane>(p->getEdge()));
961
switch (p->getStageType(0)) {
962
case MSStageType::WALKING: {
963
MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
964
assert(s != 0);
965
ev = s->getEdges();
966
routeIndex = (int)(s->getRouteStep() - s->getRoute().begin());
967
}
968
break;
969
default:
970
break;
971
}
972
if (doKeepRoute) {
973
// case a): vehicle is on its earlier route
974
// we additionally assume it is moving forward (SUMO-limit);
975
// note that the route ("edges") is not changed in this case
976
found = Helper::moveToXYMap_matchingRoutePosition(pos, edgeID,
977
ev, routeIndex, vClass, true,
978
bestDistance, &lane, lanePos, routeOffset);
979
if (bestDistance > maxRouteDistance) {
980
found = false;
981
lane = nullptr;
982
}
983
} else {
984
double speed = pos.distanceTo2D(p->getPosition()); // !!!veh->getSpeed();
985
found = Helper::moveToXYMap(pos, maxRouteDistance, mayLeaveNetwork, edgeID, angle,
986
speed, ev, routeIndex, currentLane, p->getEdgePos(), currentLane != nullptr,
987
vClass, GeomHelper::naviDegree(p->getAngle()), true,
988
bestDistance, &lane, lanePos, routeOffset, edges);
989
if (edges.size() != 0 && ev.size() > 1) {
990
// try to rebuild the route
991
const MSEdge* origEdge = p->getEdge();
992
assert(lane != nullptr);
993
const MSJunction* originalTarget = nullptr;
994
if (origEdge->isNormal()) {
995
if (routeIndex == 0) {
996
if (origEdge->getToJunction() == ev[1]->getToJunction() || origEdge->getToJunction() == ev[1]->getFromJunction()) {
997
originalTarget = origEdge->getToJunction();
998
} else {
999
originalTarget = origEdge->getFromJunction();
1000
}
1001
} else {
1002
if (origEdge->getToJunction() == ev[routeIndex - 1]->getToJunction() || origEdge->getToJunction() == ev[routeIndex - 1]->getFromJunction()) {
1003
originalTarget = origEdge->getFromJunction();
1004
} else {
1005
originalTarget = origEdge->getToJunction();
1006
}
1007
}
1008
} else {
1009
originalTarget = origEdge->getToJunction();
1010
assert(originalTarget == origEdge->getFromJunction());
1011
}
1012
const MSEdge* newEdge = edges[0];
1013
if (edges[0]->getFromJunction() == originalTarget || edges[0]->getToJunction() == originalTarget) {
1014
edges = ev;
1015
edges[routeIndex] = newEdge;
1016
}
1017
}
1018
}
1019
if (found || mayLeaveNetwork) {
1020
// compute lateral offset
1021
if (found) {
1022
const double perpDist = lane->getShape().distance2D(pos, false);
1023
if (perpDist != GeomHelper::INVALID_OFFSET) {
1024
lanePosLat = perpDist;
1025
if (!mayLeaveNetwork) {
1026
lanePosLat = MIN2(lanePosLat, 0.5 * (lane->getWidth() + p->getVehicleType().getWidth()));
1027
}
1028
// figure out whether the offset is to the left or to the right
1029
PositionVector tmp = lane->getShape();
1030
try {
1031
tmp.move2side(-lanePosLat); // moved to left
1032
} catch (ProcessError&) {
1033
WRITE_WARNINGF(TL("Could not determine position on lane '%' at lateral position %."), lane->getID(), toString(-lanePosLat));
1034
}
1035
//std::cout << " lane=" << lane->getID() << " posLat=" << lanePosLat << " shape=" << lane->getShape() << " tmp=" << tmp << " tmpDist=" << tmp.distance2D(pos) << "\n";
1036
if (tmp.distance2D(pos) > perpDist) {
1037
lanePosLat = -lanePosLat;
1038
}
1039
}
1040
}
1041
if (found && !mayLeaveNetwork && MSGlobals::gLateralResolution < 0) {
1042
// mapped position may differ from pos
1043
pos = lane->geometryPositionAtOffset(lanePos, -lanePosLat);
1044
}
1045
assert((found && lane != nullptr) || (!found && lane == nullptr));
1046
switch (p->getStageType(0)) {
1047
case MSStageType::WALKING: {
1048
if (angle == INVALID_DOUBLE_VALUE) {
1049
// walking angle cannot be deduced from road angle so we always use the last pos
1050
angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
1051
}
1052
break;
1053
}
1054
case MSStageType::WAITING_FOR_DEPART:
1055
case MSStageType::WAITING: {
1056
if (p->getNumRemainingStages() <= 1 || p->getStageType(1) != MSStageType::WALKING) {
1057
// insert walking stage after the current stage
1058
ConstMSEdgeVector route({p->getEdge()});
1059
const double departPos = p->getCurrentStage()->getArrivalPos();
1060
p->appendStage(new MSStageWalking(p->getID(), route, nullptr, -1, -1, departPos, departPos, MSPModel::UNSPECIFIED_POS_LAT), 1);
1061
}
1062
// abort waiting stage and proceed to walking stage
1063
p->removeStage(0);
1064
assert(p->getStageType(0) == MSStageType::WALKING);
1065
if (angle == INVALID_DOUBLE_VALUE) {
1066
if (lane != nullptr && !lane->getEdge().isWalkingArea()) {
1067
angle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(lanePos));
1068
} else {
1069
// compute angle outside road network or on walkingarea from old and new position
1070
angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
1071
}
1072
}
1073
break;
1074
}
1075
default:
1076
throw TraCIException("Command moveToXY is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + ".");
1077
}
1078
Helper::setRemoteControlled(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, edges, MSNet::getInstance()->getCurrentTimeStep());
1079
} else {
1080
if (lane == nullptr) {
1081
throw TraCIException("Could not map person '" + personID + "' no road found within " + toString(maxRouteDistance) + "m.");
1082
} else {
1083
throw TraCIException("Could not map person '" + personID + "' distance to road is " + toString(bestDistance) + ".");
1084
}
1085
}
1086
}
1087
1088
1089
/** untested setter functions which alter the person's vtype ***/
1090
1091
void
1092
Person::setParameter(const std::string& personID, const std::string& key, const std::string& value) {
1093
MSTransportable* p = getPerson(personID);
1094
if (StringUtils::startsWith(key, "device.")) {
1095
throw TraCIException("Person '" + personID + "' does not support device parameters\n");
1096
} else if (StringUtils::startsWith(key, "laneChangeModel.")) {
1097
throw TraCIException("Person '" + personID + "' does not support laneChangeModel parameters\n");
1098
} else if (StringUtils::startsWith(key, "carFollowModel.")) {
1099
throw TraCIException("Person '" + personID + "' does not support carFollowModel parameters\n");
1100
} else if (StringUtils::startsWith(key, "junctionModel.")) {
1101
try {
1102
// use the whole key (including junctionModel prefix)
1103
p->setJunctionModelParameter(key, value);
1104
} catch (InvalidArgument& e) {
1105
// error message includes id since it is also used for xml input
1106
throw TraCIException(e.what());
1107
}
1108
} else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
1109
throw TraCIException("Person '" + personID + "' does not support chanigng device status\n");
1110
} else {
1111
((SUMOVehicleParameter&)p->getParameter()).setParameter(key, value);
1112
}
1113
}
1114
1115
1116
void
1117
Person::setLength(const std::string& personID, double length) {
1118
getPerson(personID)->getSingularType().setLength(length);
1119
}
1120
1121
1122
void
1123
Person::setMaxSpeed(const std::string& personID, double speed) {
1124
getPerson(personID)->getSingularType().setMaxSpeed(speed);
1125
}
1126
1127
1128
void
1129
Person::setVehicleClass(const std::string& personID, const std::string& clazz) {
1130
getPerson(personID)->getSingularType().setVClass(getVehicleClassID(clazz));
1131
}
1132
1133
1134
void
1135
Person::setShapeClass(const std::string& personID, const std::string& clazz) {
1136
getPerson(personID)->getSingularType().setShape(getVehicleShapeID(clazz));
1137
}
1138
1139
1140
void
1141
Person::setEmissionClass(const std::string& personID, const std::string& clazz) {
1142
getPerson(personID)->getSingularType().setEmissionClass(PollutantsInterface::getClassByName(clazz));
1143
}
1144
1145
1146
void
1147
Person::setWidth(const std::string& personID, double width) {
1148
getPerson(personID)->getSingularType().setWidth(width);
1149
}
1150
1151
1152
void
1153
Person::setHeight(const std::string& personID, double height) {
1154
getPerson(personID)->getSingularType().setHeight(height);
1155
}
1156
1157
1158
void
1159
Person::setMass(const std::string& personID, double mass) {
1160
getPerson(personID)->getSingularType().setMass(mass);
1161
}
1162
1163
1164
void
1165
Person::setMinGap(const std::string& personID, double minGap) {
1166
getPerson(personID)->getSingularType().setMinGap(minGap);
1167
}
1168
1169
1170
void
1171
Person::setAccel(const std::string& personID, double accel) {
1172
getPerson(personID)->getSingularType().setAccel(accel);
1173
}
1174
1175
1176
void
1177
Person::setDecel(const std::string& personID, double decel) {
1178
getPerson(personID)->getSingularType().setDecel(decel);
1179
}
1180
1181
1182
void
1183
Person::setEmergencyDecel(const std::string& personID, double decel) {
1184
getPerson(personID)->getSingularType().setEmergencyDecel(decel);
1185
}
1186
1187
1188
void
1189
Person::setApparentDecel(const std::string& personID, double decel) {
1190
getPerson(personID)->getSingularType().setApparentDecel(decel);
1191
}
1192
1193
1194
void
1195
Person::setImperfection(const std::string& personID, double imperfection) {
1196
getPerson(personID)->getSingularType().setImperfection(imperfection);
1197
}
1198
1199
1200
void
1201
Person::setBoardingDuration(const std::string& personID, double boardingDuration) {
1202
Helper::getPerson(personID)->getSingularType().setBoardingDuration(TIME2STEPS(boardingDuration));
1203
}
1204
1205
1206
void
1207
Person::setImpatience(const std::string& personID, double impatience) {
1208
Helper::getVehicle(personID)->getSingularType().setImpatience(impatience);
1209
}
1210
1211
1212
1213
void
1214
Person::setTau(const std::string& personID, double tau) {
1215
getPerson(personID)->getSingularType().setTau(tau);
1216
}
1217
1218
1219
void
1220
Person::setMinGapLat(const std::string& personID, double minGapLat) {
1221
getPerson(personID)->getSingularType().setMinGapLat(minGapLat);
1222
}
1223
1224
1225
void
1226
Person::setMaxSpeedLat(const std::string& personID, double speed) {
1227
getPerson(personID)->getSingularType().setMaxSpeedLat(speed);
1228
}
1229
1230
1231
void
1232
Person::setLateralAlignment(const std::string& personID, const std::string& latAlignment) {
1233
double lao;
1234
LatAlignmentDefinition lad;
1235
if (SUMOVTypeParameter::parseLatAlignment(latAlignment, lao, lad)) {
1236
getPerson(personID)->getSingularType().setPreferredLateralAlignment(lad, lao);
1237
} else {
1238
throw TraCIException("Unknown value '" + latAlignment + "' when setting latAlignment for person '" + personID + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
1239
}
1240
}
1241
1242
1243
void
1244
Person::setSpeedFactor(const std::string& personID, double factor) {
1245
getPerson(personID)->setChosenSpeedFactor(factor);
1246
}
1247
1248
1249
void
1250
Person::setActionStepLength(const std::string& personID, double actionStepLength, bool resetActionOffset) {
1251
getPerson(personID)->getSingularType().setActionStepLength(SUMOVehicleParserHelper::processActionStepLength(actionStepLength), resetActionOffset);
1252
}
1253
1254
void
1255
Person::remove(const std::string& personID, char /*reason*/) {
1256
MSPerson* person = getPerson(personID);
1257
// remove all stages after the current and then abort the current stage
1258
// (without adding a zero-length waiting stage)
1259
while (person->getNumRemainingStages() > 1) {
1260
person->removeStage(1);
1261
}
1262
person->removeStage(0, false);
1263
}
1264
1265
void
1266
Person::setColor(const std::string& personID, const TraCIColor& c) {
1267
const SUMOVehicleParameter& p = getPerson(personID)->getParameter();
1268
p.color.set((unsigned char)c.r, (unsigned char)c.g, (unsigned char)c.b, (unsigned char)c.a);
1269
p.parametersSet |= VEHPARS_COLOR_SET;
1270
}
1271
1272
1273
LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Person, PERSON)
1274
1275
1276
MSPerson*
1277
Person::getPerson(const std::string& personID) {
1278
return Helper::getPerson(personID);
1279
}
1280
1281
1282
void
1283
Person::storeShape(const std::string& id, PositionVector& shape) {
1284
shape.push_back(getPerson(id)->getPosition());
1285
}
1286
1287
1288
std::shared_ptr<VariableWrapper>
1289
Person::makeWrapper() {
1290
return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
1291
}
1292
1293
1294
bool
1295
Person::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
1296
switch (variable) {
1297
case TRACI_ID_LIST:
1298
return wrapper->wrapStringList(objID, variable, getIDList());
1299
case ID_COUNT:
1300
return wrapper->wrapInt(objID, variable, getIDCount());
1301
case VAR_POSITION:
1302
return wrapper->wrapPosition(objID, variable, getPosition(objID));
1303
case VAR_POSITION3D:
1304
return wrapper->wrapPosition(objID, variable, getPosition(objID, true));
1305
case VAR_ANGLE:
1306
return wrapper->wrapDouble(objID, variable, getAngle(objID));
1307
case VAR_SLOPE:
1308
return wrapper->wrapDouble(objID, variable, getSlope(objID));
1309
case VAR_SPEED:
1310
return wrapper->wrapDouble(objID, variable, getSpeed(objID));
1311
case VAR_ROAD_ID:
1312
return wrapper->wrapString(objID, variable, getRoadID(objID));
1313
case VAR_LANE_ID:
1314
return wrapper->wrapString(objID, variable, getLaneID(objID));
1315
case VAR_LANEPOSITION:
1316
return wrapper->wrapDouble(objID, variable, getLanePosition(objID));
1317
case VAR_COLOR:
1318
return wrapper->wrapColor(objID, variable, getColor(objID));
1319
case VAR_WAITING_TIME:
1320
return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
1321
case VAR_IMPATIENCE:
1322
return wrapper->wrapDouble(objID, variable, getImpatience(objID));
1323
case VAR_TYPE:
1324
return wrapper->wrapString(objID, variable, getTypeID(objID));
1325
case VAR_SPEED_FACTOR:
1326
return wrapper->wrapDouble(objID, variable, getSpeedFactor(objID));
1327
case VAR_NEXT_EDGE:
1328
return wrapper->wrapString(objID, variable, getNextEdge(objID));
1329
case VAR_EDGES:
1330
return wrapper->wrapStringList(objID, variable, getEdges(objID, StoHelp::readTypedInt(*paramData)));
1331
case VAR_STAGE:
1332
return wrapper->wrapStage(objID, variable, getStage(objID, StoHelp::readTypedInt(*paramData)));
1333
case VAR_STAGES_REMAINING:
1334
return wrapper->wrapInt(objID, variable, getRemainingStages(objID));
1335
case VAR_VEHICLE:
1336
return wrapper->wrapString(objID, variable, getVehicle(objID));
1337
case VAR_MAXSPEED:
1338
// integrate desiredMaxSpeed and individual speedFactor
1339
return wrapper->wrapDouble(objID, variable, getMaxSpeed(objID));
1340
case DISTANCE_REQUEST: {
1341
TraCIRoadPosition roadPos;
1342
Position pos;
1343
if (Helper::readDistanceRequest(*paramData, roadPos, pos) == libsumo::POSITION_ROADMAP) {
1344
return wrapper->wrapDouble(objID, variable, getWalkingDistance(objID, roadPos.edgeID, roadPos.pos, roadPos.laneIndex));
1345
}
1346
return wrapper->wrapDouble(objID, variable, getWalkingDistance2D(objID, pos.x(), pos.y()));
1347
}
1348
case VAR_PARAMETER:
1349
return wrapper->wrapString(objID, variable, getParameter(objID, StoHelp::readTypedString(*paramData)));
1350
case VAR_PARAMETER_WITH_KEY:
1351
return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, StoHelp::readTypedString(*paramData)));
1352
case VAR_TAXI_RESERVATIONS:
1353
return wrapper->wrapReservationVector(objID, variable, getTaxiReservations(StoHelp::readTypedInt(*paramData)));
1354
case SPLIT_TAXI_RESERVATIONS:
1355
return wrapper->wrapString(objID, variable, splitTaxiReservation(objID, StoHelp::readTypedStringList(*paramData)));
1356
default:
1357
return libsumo::VehicleType::handleVariable(getTypeID(objID), variable, wrapper, paramData);
1358
}
1359
}
1360
1361
1362
}
1363
1364
1365
/****************************************************************************/
1366
1367