Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file TraCIServerAPI_Person.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @date 26.05.2014
17 : ///
18 : // APIs for getting/setting person values via TraCI
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <utils/common/StringTokenizer.h>
23 : #include <microsim/transportables/MSTransportableControl.h>
24 : #include <microsim/MSVehicleControl.h>
25 : #include <microsim/transportables/MSPerson.h>
26 : #include <microsim/MSNet.h>
27 : #include <microsim/MSEdge.h>
28 : #include <libsumo/Person.h>
29 : #include <libsumo/StorageHelper.h>
30 : #include <libsumo/TraCIConstants.h>
31 : #include <libsumo/VehicleType.h>
32 : #include "TraCIServer.h"
33 : #include "TraCIServerAPI_VehicleType.h"
34 : #include "TraCIServerAPI_Person.h"
35 : #include "TraCIServerAPI_Simulation.h"
36 :
37 :
38 : // ===========================================================================
39 : // method definitions
40 : // ===========================================================================
41 : bool
42 100492 : TraCIServerAPI_Person::processGet(TraCIServer& server, tcpip::Storage& inputStorage,
43 : tcpip::Storage& outputStorage) {
44 100492 : const int variable = inputStorage.readUnsignedByte();
45 100492 : const std::string id = inputStorage.readString();
46 100492 : server.initWrapper(libsumo::RESPONSE_GET_PERSON_VARIABLE, variable, id);
47 : try {
48 100492 : if (!libsumo::Person::handleVariable(id, variable, &server, &inputStorage)) {
49 15 : return server.writeErrorStatusCmd(libsumo::CMD_GET_PERSON_VARIABLE, "Get Person Variable: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
50 : }
51 52 : } catch (libsumo::TraCIException& e) {
52 52 : return server.writeErrorStatusCmd(libsumo::CMD_GET_PERSON_VARIABLE, e.what(), outputStorage);
53 52 : }
54 100435 : server.writeStatusCmd(libsumo::CMD_GET_PERSON_VARIABLE, libsumo::RTYPE_OK, "", outputStorage);
55 100435 : server.writeResponseWithLength(outputStorage, server.getWrapperStorage());
56 : return true;
57 : }
58 :
59 :
60 : bool
61 2668 : TraCIServerAPI_Person::processSet(TraCIServer& server, tcpip::Storage& inputStorage,
62 : tcpip::Storage& outputStorage) {
63 2668 : std::string warning = ""; // additional description for response
64 : // variable
65 2668 : int variable = inputStorage.readUnsignedByte();
66 2668 : if (variable != libsumo::VAR_PARAMETER
67 2668 : && variable != libsumo::ADD
68 2484 : && variable != libsumo::REMOVE
69 2484 : && variable != libsumo::APPEND_STAGE
70 2308 : && variable != libsumo::REPLACE_STAGE
71 2308 : && variable != libsumo::REMOVE_STAGE
72 2195 : && variable != libsumo::CMD_REROUTE_TRAVELTIME
73 2195 : && variable != libsumo::VAR_MOVE_TO
74 1603 : && variable != libsumo::MOVE_TO_XY
75 1603 : && variable != libsumo::VAR_SPEED
76 48 : && variable != libsumo::VAR_TYPE
77 48 : && variable != libsumo::VAR_SPEED_FACTOR
78 20 : && variable != libsumo::VAR_LENGTH
79 20 : && variable != libsumo::VAR_WIDTH
80 12 : && variable != libsumo::VAR_HEIGHT
81 12 : && variable != libsumo::VAR_MINGAP
82 4 : && variable != libsumo::VAR_COLOR
83 : ) {
84 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Change Person State: unsupported variable " + toHex(variable, 2) + " specified", outputStorage);
85 : }
86 :
87 : try {
88 : // TODO: remove declaration of c after completion
89 2668 : MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
90 : // id
91 2668 : std::string id = inputStorage.readString();
92 : // TODO: remove declaration of p after completion
93 : const bool shouldExist = variable != libsumo::ADD;
94 2668 : MSTransportable* p = c.get(id);
95 2668 : if (p == nullptr && shouldExist) {
96 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Person '" + id + "' is not known", outputStorage);
97 : }
98 : // process
99 2668 : switch (variable) {
100 10 : case libsumo::VAR_SPEED: {
101 10 : double speed = 0;
102 10 : if (!server.readTypeCheckingDouble(inputStorage, speed)) {
103 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Setting speed requires a double.", outputStorage);
104 : }
105 : // set the speed for all present and future (walking) stages and modify the vType so that stages added later are also affected
106 10 : libsumo::Person::setSpeed(id, speed);
107 : }
108 10 : break;
109 : case libsumo::VAR_TYPE: {
110 : std::string vTypeID;
111 10 : if (!server.readTypeCheckingString(inputStorage, vTypeID)) {
112 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The vehicle type id must be given as a string.", outputStorage);
113 : }
114 10 : libsumo::Person::setType(id, vTypeID);
115 : break;
116 : }
117 18 : case libsumo::VAR_SPEED_FACTOR: {
118 18 : double speedfactor = 0;
119 18 : if (!server.readTypeCheckingDouble(inputStorage, speedfactor)) {
120 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Setting SpeedFactor requires a double.", outputStorage);
121 : }
122 18 : libsumo::Person::setSpeedFactor(id, speedfactor);
123 : }
124 18 : break;
125 : case libsumo::VAR_COLOR: {
126 : libsumo::TraCIColor col;
127 4 : if (!server.readTypeCheckingColor(inputStorage, col)) {
128 6 : return server.writeErrorStatusCmd(libsumo::CMD_SET_VEHICLE_VARIABLE, "The color must be given using the according type.", outputStorage);
129 : }
130 4 : libsumo::Person::setColor(id, col);
131 : break;
132 : }
133 115 : case libsumo::ADD: {
134 115 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
135 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a person requires a compound object.", outputStorage);
136 : }
137 115 : if (inputStorage.readInt() != 4) {
138 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a person needs four parameters.", outputStorage);
139 : }
140 : std::string vTypeID;
141 115 : if (!server.readTypeCheckingString(inputStorage, vTypeID)) {
142 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "First parameter (type) requires a string.", outputStorage);
143 : }
144 : std::string edgeID;
145 115 : if (!server.readTypeCheckingString(inputStorage, edgeID)) {
146 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Second parameter (edge) requires a string.", outputStorage);
147 : }
148 : double depart;
149 115 : if (!server.readTypeCheckingDouble(inputStorage, depart)) {
150 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Third parameter (depart) requires a double.", outputStorage);
151 : }
152 : double pos;
153 115 : if (!server.readTypeCheckingDouble(inputStorage, pos)) {
154 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fourth parameter (position) requires a double.", outputStorage);
155 : }
156 230 : libsumo::Person::add(id, edgeID, pos, depart, vTypeID);
157 : }
158 : break;
159 15 : case libsumo::REMOVE: {
160 15 : int why = 0;
161 15 : if (!server.readTypeCheckingByte(inputStorage, why)) {
162 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_VEHICLE_VARIABLE, "Removing a person requires a byte.", outputStorage);
163 : }
164 15 : libsumo::Person::remove(id, (char)why);
165 : }
166 15 : break;
167 161 : case libsumo::APPEND_STAGE: {
168 161 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
169 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a person stage requires a compound object.", outputStorage);
170 : }
171 161 : int numParameters = inputStorage.readInt();
172 161 : if (numParameters == 13) {
173 44 : libsumo::TraCIStage stage;
174 22 : libsumo::StorageHelper::readStage(inputStorage, stage);
175 22 : libsumo::Person::appendStage(id, stage);
176 22 : } else {
177 139 : const int stageType = StoHelp::readTypedInt(inputStorage, "The first parameter for adding a stage must be the stage type given as int.");
178 139 : if (stageType == libsumo::STAGE_DRIVING) {
179 : // append driving stage
180 22 : if (numParameters != 4) {
181 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a driving stage needs four parameters.", outputStorage);
182 : }
183 : std::string edgeID;
184 22 : if (!server.readTypeCheckingString(inputStorage, edgeID)) {
185 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Second parameter (edge) requires a string.", outputStorage);
186 : }
187 : std::string lines;
188 22 : if (!server.readTypeCheckingString(inputStorage, lines)) {
189 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Third parameter (lines) requires a string.", outputStorage);
190 : }
191 : std::string stopID;
192 22 : if (!server.readTypeCheckingString(inputStorage, stopID)) {
193 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fourth parameter (stopID) requires a string.", outputStorage);
194 : }
195 22 : libsumo::Person::appendDrivingStage(id, edgeID, lines, stopID);
196 117 : } else if (stageType == libsumo::STAGE_WAITING) {
197 : // append waiting stage
198 16 : if (numParameters != 4) {
199 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a waiting stage needs four parameters.", outputStorage);
200 : }
201 : double duration;
202 16 : if (!server.readTypeCheckingDouble(inputStorage, duration)) {
203 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Second parameter (duration) requires a double.", outputStorage);
204 : }
205 : std::string description;
206 16 : if (!server.readTypeCheckingString(inputStorage, description)) {
207 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Third parameter (description) requires a string.", outputStorage);
208 : }
209 : std::string stopID;
210 16 : if (!server.readTypeCheckingString(inputStorage, stopID)) {
211 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fourth parameter (stopID) requires a string.", outputStorage);
212 : }
213 16 : libsumo::Person::appendWaitingStage(id, duration, description, stopID);
214 101 : } else if (stageType == libsumo::STAGE_WALKING) {
215 : // append walking stage
216 101 : if (numParameters != 6) {
217 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Adding a walking stage needs six parameters.", outputStorage);
218 : }
219 : std::vector<std::string> edgeIDs;
220 101 : if (!server.readTypeCheckingStringList(inputStorage, edgeIDs)) {
221 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_VEHICLE_VARIABLE, "Second parameter (edges) route must be defined as a list of edge ids.", outputStorage);
222 : }
223 : double arrivalPos;
224 101 : if (!server.readTypeCheckingDouble(inputStorage, arrivalPos)) {
225 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Third parameter (arrivalPos) requires a double.", outputStorage);
226 : }
227 : double duration;
228 101 : if (!server.readTypeCheckingDouble(inputStorage, duration)) {
229 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fourth parameter (duration) requires a double.", outputStorage);
230 : }
231 : double speed;
232 101 : if (!server.readTypeCheckingDouble(inputStorage, speed)) {
233 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fifth parameter (speed) requires a double.", outputStorage);
234 : }
235 : std::string stopID;
236 101 : if (!server.readTypeCheckingString(inputStorage, stopID)) {
237 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Fourth parameter (stopID) requires a string.", outputStorage);
238 : }
239 101 : libsumo::Person::appendWalkingStage(id, edgeIDs, arrivalPos, duration, speed, stopID);
240 101 : } else {
241 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Invalid stage type for person '" + id + "'", outputStorage);
242 : }
243 : }
244 :
245 : }
246 : break;
247 :
248 6 : case libsumo::REPLACE_STAGE : {
249 6 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
250 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Replacing a person stage requires a compound object.", outputStorage);
251 : }
252 6 : if (inputStorage.readInt() != 2) {
253 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Replacing a person stage requires a compound object of size 2.", outputStorage);
254 : }
255 6 : const int nextStageIndex = StoHelp::readTypedInt(inputStorage, "First parameter of replace stage should be an integer");
256 6 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
257 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Second parameter of replace stage should be a compound object", outputStorage);
258 : }
259 6 : if (inputStorage.readInt() != 13) {
260 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Second parameter of replace stage should be a compound object of size 13", outputStorage);
261 : }
262 12 : libsumo::TraCIStage stage;
263 6 : libsumo::StorageHelper::readStage(inputStorage, stage);
264 6 : libsumo::Person::replaceStage(id, nextStageIndex, stage);
265 6 : }
266 6 : break;
267 :
268 : case libsumo::REMOVE_STAGE: {
269 107 : const int nextStageIndex = StoHelp::readTypedInt(inputStorage, "The message must contain the stage index.");
270 107 : libsumo::Person::removeStage(id, nextStageIndex);
271 : }
272 : break;
273 580 : case libsumo::CMD_REROUTE_TRAVELTIME: {
274 580 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
275 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Rerouting requires a compound object.", outputStorage);
276 : }
277 580 : if (inputStorage.readInt() != 0) {
278 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Rerouting should obtain an empty compound object.", outputStorage);
279 : }
280 580 : libsumo::Person::rerouteTraveltime(id);
281 : }
282 : break;
283 12 : case libsumo::VAR_MOVE_TO: {
284 12 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
285 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Setting position requires a compound object.", outputStorage);
286 : }
287 12 : const int numArgs = inputStorage.readInt();
288 12 : if (numArgs != 3) {
289 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "Setting position should obtain the edge id, the position and the lateral position.", outputStorage);
290 : }
291 : std::string laneID;
292 12 : if (!server.readTypeCheckingString(inputStorage, laneID)) {
293 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The first parameter for setting a position must be the laneID given as a string.", outputStorage);
294 : }
295 12 : double position = 0;
296 12 : if (!server.readTypeCheckingDouble(inputStorage, position)) {
297 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The second parameter for setting a position must be the position given as a double.", outputStorage);
298 : }
299 12 : double posLat = 0;
300 12 : if (!server.readTypeCheckingDouble(inputStorage, posLat)) {
301 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The third parameter for setting a position must be the lateral position given as a double.", outputStorage);
302 : }
303 : // process
304 12 : libsumo::Person::moveTo(id, laneID, position, posLat);
305 : }
306 : break;
307 1545 : case libsumo::MOVE_TO_XY: {
308 1545 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
309 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "MoveToXY person requires a compound object.", outputStorage);
310 : }
311 1545 : const int numArgs = inputStorage.readInt();
312 1545 : if (numArgs != 5 && numArgs != 6) {
313 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "MoveToXY person should obtain: edgeID, x, y, angle, keepRouteFlag and optionally matchThreshold.", outputStorage);
314 : }
315 : // edge ID
316 : std::string edgeID;
317 1545 : if (!server.readTypeCheckingString(inputStorage, edgeID)) {
318 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The first parameter for moveToXY must be the edge ID given as a string.", outputStorage);
319 : }
320 : // x
321 1545 : double x = 0;
322 1545 : if (!server.readTypeCheckingDouble(inputStorage, x)) {
323 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The second parameter for moveToXY must be the x-position given as a double.", outputStorage);
324 : }
325 : // y
326 1545 : double y = 0;
327 1545 : if (!server.readTypeCheckingDouble(inputStorage, y)) {
328 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The third parameter for moveToXY must be the y-position given as a double.", outputStorage);
329 : }
330 : // angle
331 1545 : double angle = 0;
332 1545 : if (!server.readTypeCheckingDouble(inputStorage, angle)) {
333 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The fourth parameter for moveToXY must be the angle given as a double.", outputStorage);
334 : }
335 1545 : int keepRouteFlag = 1;
336 1545 : if (!server.readTypeCheckingByte(inputStorage, keepRouteFlag)) {
337 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The fifth parameter for moveToXY must be the keepRouteFlag given as a byte.", outputStorage);
338 : }
339 1545 : double matchThreshold = 100;
340 1545 : if (numArgs == 6) {
341 1545 : if (!server.readTypeCheckingDouble(inputStorage, matchThreshold)) {
342 3 : return server.writeErrorStatusCmd(libsumo::CMD_SET_VEHICLE_VARIABLE, "The sixth parameter for moveToXY must be the matchThreshold given as a double.", outputStorage);
343 : }
344 : }
345 1545 : libsumo::Person::moveToXY(id, edgeID, x, y, angle, keepRouteFlag, matchThreshold);
346 : }
347 : break;
348 69 : case libsumo::VAR_PARAMETER: {
349 69 : if (inputStorage.readUnsignedByte() != libsumo::TYPE_COMPOUND) {
350 6 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "A compound object is needed for setting a parameter.", outputStorage);
351 : }
352 : //read itemNo
353 69 : inputStorage.readInt();
354 : std::string name;
355 69 : if (!server.readTypeCheckingString(inputStorage, name)) {
356 3 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The name of the parameter must be given as a string.", outputStorage);
357 : }
358 : std::string value;
359 69 : if (!server.readTypeCheckingString(inputStorage, value)) {
360 3 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, "The value of the parameter must be given as a string.", outputStorage);
361 : }
362 69 : libsumo::Person::setParameter(id, name, value);
363 : }
364 : break;
365 16 : default:
366 : try {
367 16 : if (!TraCIServerAPI_VehicleType::setVariable(libsumo::CMD_SET_PERSON_VARIABLE, variable, p->getSingularType().getID(), server, inputStorage, outputStorage)) {
368 : return false;
369 : }
370 0 : } catch (ProcessError& e) {
371 0 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, e.what(), outputStorage);
372 0 : }
373 : break;
374 : }
375 6 : } catch (libsumo::TraCIException& e) {
376 6 : return server.writeErrorStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, e.what(), outputStorage);
377 6 : }
378 2662 : server.writeStatusCmd(libsumo::CMD_SET_PERSON_VARIABLE, libsumo::RTYPE_OK, warning, outputStorage);
379 : return true;
380 : }
381 :
382 :
383 : /****************************************************************************/
|