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