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