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