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