Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 : // Copyright (C) 2017-2017 German Aerospace Center (DLR) and others.
4 : /****************************************************************************/
5 : //
6 : // This program and the accompanying materials
7 : // are made available under the terms of the Eclipse Public License v2.0
8 : // which accompanies this distribution, and is available at
9 : // http://www.eclipse.org/legal/epl-v20.html
10 : //
11 : /****************************************************************************/
12 : /// @file TraCI_Person.cpp
13 : /// @author Leonhard Luecken
14 : /// @date 15.09.2017
15 : /// @version $Id$
16 : ///
17 : // C++ TraCI client API implementation
18 : /****************************************************************************/
19 :
20 :
21 : // ===========================================================================
22 : // included modules
23 : // ===========================================================================
24 : #ifdef _MSC_VER
25 : #include <windows_config.h>
26 : #else
27 : #include <config.h>
28 : #endif
29 :
30 : #include <microsim/MSTransportableControl.h>
31 : #include <microsim/MSVehicleControl.h>
32 : #include <microsim/MSEdge.h>
33 : #include <microsim/MSNet.h>
34 : #include <microsim/pedestrians/MSPerson.h>
35 : #include <utils/geom/GeomHelper.h>
36 : #include <utils/common/StringTokenizer.h>
37 : #include "TraCI_VehicleType.h"
38 : #include "TraCI_Person.h"
39 :
40 :
41 : // ===========================================================================
42 : // member definitions
43 : // ===========================================================================
44 :
45 : std::vector<std::string>
46 43281 : TraCI_Person::getIDList() {
47 43281 : MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
48 43281 : std::vector<std::string> ids;
49 122652 : for (MSTransportableControl::constVehIt i = c.loadedBegin(); i != c.loadedEnd(); ++i) {
50 79371 : if (i->second->getCurrentStageType() != MSTransportable::WAITING_FOR_DEPART) {
51 79371 : ids.push_back(i->first);
52 : }
53 : }
54 43281 : return std::move(ids);
55 : }
56 :
57 :
58 : int
59 11 : TraCI_Person::getIDCount() {
60 11 : return MSNet::getInstance()->getPersonControl().size();
61 : }
62 :
63 :
64 : TraCIPosition
65 101533 : TraCI_Person::getPosition(const std::string& personID) {
66 101533 : MSTransportable* p = getPerson(personID);
67 : TraCIPosition pos;
68 101533 : pos.x = p->getPosition().x();
69 101533 : pos.y = p->getPosition().y();
70 101533 : pos.z = p->getPosition().z();
71 101533 : return pos;
72 : }
73 :
74 :
75 : double
76 8 : TraCI_Person::getAngle(const std::string& personID){
77 8 : return GeomHelper::naviDegree(getPerson(personID)->getAngle());
78 : }
79 :
80 :
81 : double
82 14 : TraCI_Person::getSpeed(const std::string& personID){
83 14 : return getPerson(personID)->getSpeed();
84 : }
85 :
86 :
87 : std::string
88 24 : TraCI_Person::getRoadID(const std::string& personID){
89 24 : return getPerson(personID)->getEdge()->getID();
90 : }
91 :
92 :
93 : double
94 11 : TraCI_Person::getLanePosition(const std::string& personID) {
95 11 : return getPerson(personID)->getEdgePos();
96 : }
97 :
98 :
99 : TraCIColor
100 8 : TraCI_Person::getColor(const std::string& personID){
101 8 : const RGBColor& col = getPerson(personID)->getParameter().color;
102 : TraCIColor tcol;
103 8 : tcol.r = col.red();
104 8 : tcol.g = col.green();
105 8 : tcol.b = col.blue();
106 8 : tcol.a = col.alpha();
107 8 : return tcol;
108 : }
109 :
110 :
111 : std::string
112 30 : TraCI_Person::getTypeID(const std::string& personID) {
113 30 : return getPerson(personID)->getVehicleType().getID();
114 : }
115 :
116 :
117 : double
118 1778 : TraCI_Person::getWaitingTime(const std::string& personID) {
119 1778 : return getPerson(personID)->getWaitingSeconds();
120 : }
121 :
122 :
123 : std::string
124 210 : TraCI_Person::getNextEdge(const std::string& personID) {
125 210 : return dynamic_cast<MSPerson*>(getPerson(personID))->getNextEdge();
126 : }
127 :
128 :
129 : std::vector<std::string>
130 23 : TraCI_Person::getEdges(const std::string& personID, int nextStageIndex) {
131 23 : MSTransportable* p = getPerson(personID);
132 23 : if (nextStageIndex >= p->getNumRemainingStages()) {
133 0 : throw TraCIException("The stage index must be lower than the number of remaining stages.");
134 : }
135 23 : if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
136 0 : throw TraCIException("The negative stage index must refer to a valid previous stage.");
137 : }
138 23 : std::vector<std::string> edgeIDs;
139 100 : for(auto& e : p->getEdges(nextStageIndex)) {
140 77 : edgeIDs.push_back(e->getID());
141 23 : }
142 23 : return edgeIDs;
143 : }
144 :
145 :
146 : int
147 14 : TraCI_Person::getStage(const std::string& personID, int nextStageIndex) {
148 14 : MSTransportable* p = getPerson(personID);
149 14 : if (nextStageIndex >= p->getNumRemainingStages()) {
150 3 : throw TraCIException("The stage index must be lower than the number of remaining stages.");
151 : }
152 11 : if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
153 3 : throw TraCIException("The negative stage index must refer to a valid previous stage.");
154 : }
155 8 : return p->getStageType(nextStageIndex);
156 : }
157 :
158 :
159 : int
160 31 : TraCI_Person::getRemainingStages(const std::string& personID) {
161 31 : return getPerson(personID)->getNumRemainingStages();
162 : }
163 :
164 :
165 : std::string
166 7 : TraCI_Person::getVehicle(const std::string& personID) {
167 7 : const SUMOVehicle* veh = getPerson(personID)->getVehicle();
168 7 : if (veh == nullptr) {
169 7 : return "";
170 : } else {
171 0 : return veh->getID();
172 : }
173 : }
174 :
175 :
176 : std::string
177 6 : TraCI_Person::getParameter(const std::string& personID, const std::string& param) {
178 6 : return getPerson(personID)->getParameter().getParameter(param, "");
179 : }
180 :
181 :
182 :
183 :
184 : void
185 4 : TraCI_Person::setSpeed(const std::string& personID, double speed) {
186 4 : getPerson(personID)->setSpeed(speed);
187 4 : }
188 :
189 :
190 : void
191 4 : TraCI_Person::setType(const std::string& personID, const std::string& typeID) {
192 4 : MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
193 4 : if (vehicleType == 0) {
194 0 : throw TraCIException("The vehicle type '" + typeID + "' is not known.");
195 : }
196 4 : getPerson(personID)->replaceVehicleType(vehicleType);
197 4 : }
198 :
199 :
200 : void
201 7 : TraCI_Person::add(const std::string& personID, const std::string& edgeID, double pos, double departInSecs, const std::string typeID) {
202 : MSTransportable* p;
203 : try {
204 7 : p = getPerson(personID);
205 14 : } catch (TraCIException&) {
206 7 : p = nullptr;
207 : }
208 :
209 7 : if (p != nullptr) {
210 0 : throw TraCIException("The person " + personID + " to add already exists.");
211 : }
212 :
213 7 : SUMOTime depart = TIME2STEPS(departInSecs);
214 7 : SUMOVehicleParameter vehicleParams;
215 7 : vehicleParams.id = personID;
216 :
217 7 : MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
218 7 : if (!vehicleType) {
219 0 : throw TraCIException("Invalid type '" + typeID + "' for person '" + personID + "'");
220 : }
221 :
222 7 : const MSEdge* edge = MSEdge::dictionary(edgeID);
223 7 : if (!edge) {
224 0 : throw TraCIException("Invalid edge '" + edgeID + "' for person: '" + personID + "'");
225 : }
226 :
227 7 : if (depart < 0) {
228 7 : const int proc = (int)-depart;
229 7 : if (proc >= static_cast<int>(DEPART_DEF_MAX)) {
230 0 : throw TraCIException("Invalid departure time.");
231 : }
232 7 : vehicleParams.departProcedure = (DepartDefinition)proc;
233 7 : vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
234 0 : } else if (depart < MSNet::getInstance()->getCurrentTimeStep()) {
235 0 : vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
236 0 : WRITE_WARNING("Departure time " + toString(departInSecs) + " for person '" + personID
237 : + "' is in the past; using current time " + time2string(vehicleParams.depart) + " instead.");
238 : } else {
239 0 : vehicleParams.depart = depart;
240 : }
241 :
242 7 : vehicleParams.departPosProcedure = DEPART_POS_GIVEN;
243 7 : if (fabs(pos) > edge->getLength()) {
244 0 : throw TraCIException("Invalid departure position.");
245 : }
246 7 : if (pos < 0) {
247 6 : pos += edge->getLength();
248 : }
249 7 : vehicleParams.departPos = pos;
250 :
251 7 : SUMOVehicleParameter* params = new SUMOVehicleParameter(vehicleParams);
252 7 : MSTransportable::MSTransportablePlan* plan = new MSTransportable::MSTransportablePlan();
253 7 : plan->push_back(new MSTransportable::Stage_Waiting(*edge, 0, depart, pos, "awaiting departure", true));
254 :
255 : try {
256 7 : MSTransportable* person = MSNet::getInstance()->getPersonControl().buildPerson(params, vehicleType, plan, false);
257 7 : MSNet::getInstance()->getPersonControl().add(person);
258 0 : } catch (ProcessError& e) {
259 0 : delete params;
260 0 : delete plan;
261 0 : throw TraCIException(e.what());
262 7 : }
263 7 : }
264 :
265 :
266 : void
267 4 : TraCI_Person::appendDrivingStage(const std::string& personID, const std::string& toEdge, const std::string& lines, const std::string& stopID) {
268 4 : MSTransportable* p = getPerson(personID);
269 4 : const MSEdge* edge = MSEdge::dictionary(toEdge);
270 4 : if (!edge) {
271 0 : throw TraCIException("Invalid edge '" + toEdge + "' for person: '" + personID + "'");
272 : }
273 4 : if (lines.size() == 0) {
274 0 : return throw TraCIException("Empty lines parameter for person: '" + personID + "'");
275 : }
276 4 : MSStoppingPlace* bs = 0;
277 4 : if (stopID != "") {
278 0 : bs = MSNet::getInstance()->getBusStop(stopID);
279 0 : if (bs == 0) {
280 0 : throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
281 : }
282 : }
283 4 : p->appendStage(new MSPerson::MSPersonStage_Driving(*edge, bs, -NUMERICAL_EPS, StringTokenizer(lines).getVector()));
284 4 : }
285 :
286 :
287 : void
288 10 : TraCI_Person::appendWaitingStage(const std::string& personID, double duration, const std::string& description, const std::string& stopID) {
289 10 : MSTransportable* p = getPerson(personID);
290 10 : if (duration < 0) {
291 0 : throw TraCIException("Duration for person: '" + personID + "' must not be negative");
292 : }
293 10 : MSStoppingPlace* bs = 0;
294 10 : if (stopID != "") {
295 0 : bs = MSNet::getInstance()->getBusStop(stopID);
296 0 : if (bs == 0) {
297 0 : throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
298 : }
299 : }
300 10 : p->appendStage(new MSTransportable::Stage_Waiting(*p->getArrivalEdge(), TIME2STEPS(duration), 0, p->getArrivalPos(), description, false));
301 10 : }
302 :
303 :
304 : void
305 14 : TraCI_Person::appendWalkingStage(const std::string& personID, const std::vector<std::string>& edgeIDs, double arrivalPos, double duration, double speed, const std::string& stopID) {
306 14 : MSTransportable* p = getPerson(personID);
307 14 : ConstMSEdgeVector edges;
308 : try {
309 14 : MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
310 0 : } catch (ProcessError& e) {
311 0 : throw TraCIException(e.what());
312 : }
313 14 : if (edges.empty()) {
314 0 : throw TraCIException("Empty edge list for walking stage of person '" + personID+ "'.");
315 : }
316 14 : if (fabs(arrivalPos) > edges.back()->getLength()) {
317 0 : throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
318 : }
319 14 : if (arrivalPos < 0) {
320 11 : arrivalPos += edges.back()->getLength();
321 : }
322 14 : if (speed < 0) {
323 14 : speed = p->getVehicleType().getMaxSpeed();
324 : }
325 14 : MSStoppingPlace* bs = 0;
326 14 : if (stopID != "") {
327 0 : bs = MSNet::getInstance()->getBusStop(stopID);
328 0 : if (bs == 0) {
329 0 : throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
330 : }
331 : }
332 14 : p->appendStage(new MSPerson::MSPersonStage_Walking(edges, bs, TIME2STEPS(duration), speed, p->getArrivalPos(), arrivalPos, 0));
333 14 : }
334 :
335 :
336 : void
337 25 : TraCI_Person::removeStage(const std::string& personID, int nextStageIndex) {
338 25 : MSTransportable* p = getPerson(personID);
339 25 : if (nextStageIndex >= p->getNumRemainingStages()) {
340 0 : throw TraCIException("The stage index must be lower than the number of remaining stages.");
341 : }
342 25 : if (nextStageIndex < 0) {
343 0 : throw TraCIException("The stage index may not be negative.");
344 : }
345 25 : p->removeStage(nextStageIndex);
346 25 : }
347 :
348 :
349 : void
350 598 : TraCI_Person::rerouteTraveltime(const std::string& personID) {
351 598 : MSTransportable* p = getPerson(personID);
352 598 : if (p->getNumRemainingStages() == 0 || p->getCurrentStageType() != MSTransportable::MOVING_WITHOUT_VEHICLE) {
353 0 : throw TraCIException("Person '" + personID + "' is not currenlty walking.");
354 : }
355 598 : const MSEdge* from = p->getEdge();
356 598 : double departPos = p->getEdgePos();
357 598 : const MSEdge* to = p->getArrivalEdge();
358 598 : double arrivalPos = p->getArrivalPos();
359 598 : double speed = p->getVehicleType().getMaxSpeed();
360 598 : ConstMSEdgeVector newEdges;
361 598 : MSNet::getInstance()->getPedestrianRouter().compute(from, to, departPos, arrivalPos, speed, 0, 0, newEdges);
362 598 : if (newEdges.empty()) {
363 0 : throw TraCIException("Could not find new route for person '" + personID + "'.");
364 : }
365 608 : ConstMSEdgeVector oldEdges = p->getEdges(0);
366 : assert(!oldEdges.empty());
367 598 : if (oldEdges.front()->getFunction() != EDGEFUNC_NORMAL) {
368 588 : oldEdges.erase(oldEdges.begin());
369 : }
370 598 : if (newEdges == oldEdges) {
371 1186 : return;
372 : }
373 10 : if (newEdges.front() != from) {
374 : // @note: maybe this should be done automatically by the router
375 3 : newEdges.insert(newEdges.begin(), from);
376 : }
377 : //std::cout << " from=" << from->getID() << " to=" << to->getID() << " newEdges=" << toString(newEdges) << "\n";
378 10 : MSPerson::MSPersonStage_Walking* newStage = new MSPerson::MSPersonStage_Walking(newEdges, 0, -1, speed, departPos, arrivalPos, 0);
379 10 : if (p->getNumRemainingStages() == 1) {
380 : // Do not remove the last stage (a waiting stage would be added otherwise)
381 10 : p->appendStage(newStage);
382 : //std::cout << "case a: remaining=" << p->getNumRemainingStages() << "\n";
383 10 : p->removeStage(0);
384 : } else {
385 0 : p->removeStage(0);
386 0 : p->appendStage(newStage);
387 : //std::cout << "case b: remaining=" << p->getNumRemainingStages() << "\n";
388 10 : }
389 : }
390 :
391 :
392 : /** untested setter functions which alter the person's vtype ***/
393 :
394 : void
395 3 : TraCI_Person::setParameter(const std::string& personID, const std::string& key, const std::string& value) {
396 3 : MSTransportable* p = getPerson(personID);
397 3 : ((SUMOVehicleParameter&) p->getParameter()).setParameter(key, value);
398 3 : }
399 :
400 : void
401 0 : TraCI_Person::setLength(const std::string& personID, double length) {
402 0 : TraCI_VehicleType::getVType(getSingularVType(personID))->setLength(length);
403 0 : }
404 :
405 : void
406 0 : TraCI_Person::setWidth(const std::string& personID, double width) {
407 0 : TraCI_VehicleType::getVType(getSingularVType(personID))->setWidth(width);
408 0 : }
409 :
410 : void
411 0 : TraCI_Person::setHeight(const std::string& personID, double height) {
412 0 : TraCI_VehicleType::getVType(getSingularVType(personID))->setHeight(height);
413 0 : }
414 :
415 : void
416 0 : TraCI_Person::setMinGap(const std::string& personID, double minGap) {
417 0 : TraCI_VehicleType::getVType(getSingularVType(personID))->setMinGap(minGap);
418 0 : }
419 :
420 : void
421 0 : TraCI_Person::setColor(const std::string& personID, const TraCIColor& c) {
422 0 : TraCI_VehicleType::getVType(getSingularVType(personID))->setColor(RGBColor(c.r, c.g, c.b, c.a));
423 0 : }
424 :
425 :
426 :
427 : /******** private functions *************/
428 :
429 : MSTransportable*
430 104390 : TraCI_Person::getPerson(const std::string& personID) {
431 104390 : MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
432 104390 : MSTransportable* p = c.get(personID);
433 104390 : if (p == 0) {
434 12 : throw TraCIException("Person '" + personID + "' is not known");
435 : }
436 104378 : return p;
437 : }
438 :
439 : std::string
440 24 : TraCI_Person::getSingularVType(const std::string& personID) {
441 24 : return getPerson(personID)->getSingularType().getID();
442 43554 : }
443 :
444 :
445 : /****************************************************************************/
|