Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/traci-server/TraCIServer.cpp
193972 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2007-2026 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 TraCIServer.cpp
15
/// @author Axel Wegener
16
/// @author Friedemann Wesner
17
/// @author Christoph Sommer
18
/// @author Jakob Erdmann
19
/// @author Daniel Krajzewicz
20
/// @author Thimor Bohn
21
/// @author Tino Morenz
22
/// @author Laura Bieker
23
/// @author Michael Behrisch
24
/// @author Mario Krumnow
25
/// @author Leonhard Luecken
26
/// @date 2007/10/24
27
///
28
// TraCI server used to control sumo by a remote TraCI client (e.g., ns2)
29
/****************************************************************************/
30
#include <config.h>
31
32
#ifdef HAVE_VERSION_H
33
#include <version.h>
34
#endif
35
36
#include <string>
37
#include <cmath>
38
#include <map>
39
#include <iostream>
40
#include <algorithm>
41
#include <foreign/tcpip/socket.h>
42
#include <foreign/tcpip/storage.h>
43
#include <utils/common/SUMOTime.h>
44
#include <utils/router/DijkstraRouter.h>
45
#include <utils/common/NamedObjectCont.h>
46
#include <utils/common/RandHelper.h>
47
#include <utils/common/MsgHandler.h>
48
#include <utils/vehicle/SUMOVehicleParameter.h>
49
#include <utils/shapes/PointOfInterest.h>
50
#include <utils/shapes/ShapeContainer.h>
51
#include <utils/xml/XMLSubSys.h>
52
#include <microsim/MSNet.h>
53
#include <microsim/MSVehicle.h>
54
#include <microsim/MSEdge.h>
55
#include <microsim/MSJunctionControl.h>
56
#include <microsim/transportables/MSTransportableControl.h>
57
#include <microsim/MSJunction.h>
58
#include <microsim/MSEdgeControl.h>
59
#include <microsim/MSLane.h>
60
#include <microsim/MSGlobals.h>
61
#include <microsim/traffic_lights/MSTLLogicControl.h>
62
#include <libsumo/Helper.h>
63
#include <libsumo/StorageHelper.h>
64
#include <libsumo/libsumo.h>
65
#include <libsumo/Subscription.h>
66
#include <libsumo/TraCIConstants.h>
67
#include "TraCIServer.h"
68
#include "TraCIServerAPI_InductionLoop.h"
69
#include "TraCIServerAPI_Junction.h"
70
#include "TraCIServerAPI_Lane.h"
71
#include "TraCIServerAPI_MultiEntryExit.h"
72
#include "TraCIServerAPI_LaneArea.h"
73
#include "TraCIServerAPI_TrafficLight.h"
74
#include "TraCIServerAPI_Vehicle.h"
75
#include "TraCIServerAPI_VehicleType.h"
76
#include "TraCIServerAPI_Route.h"
77
#include "TraCIServerAPI_POI.h"
78
#include "TraCIServerAPI_Polygon.h"
79
#include "TraCIServerAPI_Edge.h"
80
#include "TraCIServerAPI_Simulation.h"
81
#include "TraCIServerAPI_Person.h"
82
#include "TraCIServerAPI_Calibrator.h"
83
#include "TraCIServerAPI_BusStop.h"
84
#include "TraCIServerAPI_ParkingArea.h"
85
#include "TraCIServerAPI_ChargingStation.h"
86
#include "TraCIServerAPI_RouteProbe.h"
87
#include "TraCIServerAPI_Rerouter.h"
88
#include "TraCIServerAPI_VariableSpeedSign.h"
89
#include "TraCIServerAPI_MeanData.h"
90
#include "TraCIServerAPI_OverheadWire.h"
91
92
93
// ===========================================================================
94
// debug constants
95
// ===========================================================================
96
//#define DEBUG_MULTI_CLIENTS
97
//#define DEBUG_SUBSCRIPTIONS
98
//#define DEBUG_SUBSCRIPTION_FILTERS
99
//#define DEBUG_RAW_INPUT
100
101
102
// ===========================================================================
103
// static member definitions
104
// ===========================================================================
105
TraCIServer* TraCIServer::myInstance = nullptr;
106
bool TraCIServer::myDoCloseConnection = false;
107
108
109
// ===========================================================================
110
// method definitions
111
// ===========================================================================
112
void
113
TraCIServer::initWrapper(const int domainID, const int variable, const std::string& objID) {
114
myWrapperStorage.reset();
115
myWrapperStorage.writeUnsignedByte(domainID);
116
myWrapperStorage.writeUnsignedByte(variable);
117
myWrapperStorage.writeString(objID);
118
}
119
120
121
bool
122
TraCIServer::wrapConnectionVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIConnection>& value) {
123
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 8);
124
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
125
for (const libsumo::TraCIConnection& c : value) {
126
StoHelp::writeTypedString(myWrapperStorage, c.approachedLane);
127
StoHelp::writeTypedString(myWrapperStorage, c.approachedInternal);
128
StoHelp::writeTypedUnsignedByte(myWrapperStorage, c.hasPrio);
129
StoHelp::writeTypedUnsignedByte(myWrapperStorage, c.isOpen);
130
StoHelp::writeTypedUnsignedByte(myWrapperStorage, c.hasFoe);
131
StoHelp::writeTypedString(myWrapperStorage, c.state);
132
StoHelp::writeTypedString(myWrapperStorage, c.direction);
133
StoHelp::writeTypedDouble(myWrapperStorage, c.length);
134
}
135
return true;
136
}
137
138
139
bool
140
TraCIServer::wrapDouble(const std::string& /* objID */, const int /* variable */, const double value) {
141
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_DOUBLE);
142
myWrapperStorage.writeDouble(value);
143
return true;
144
}
145
146
147
bool
148
TraCIServer::wrapInt(const std::string& /* objID */, const int /* variable */, const int value) {
149
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_INTEGER);
150
myWrapperStorage.writeInt(value);
151
return true;
152
}
153
154
155
bool
156
TraCIServer::wrapString(const std::string& /* objID */, const int /* variable */, const std::string& value) {
157
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_STRING);
158
myWrapperStorage.writeString(value);
159
return true;
160
}
161
162
163
bool
164
TraCIServer::wrapStringList(const std::string& /* objID */, const int /* variable */, const std::vector<std::string>& value) {
165
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_STRINGLIST);
166
myWrapperStorage.writeStringList(value);
167
return true;
168
}
169
170
171
bool
172
TraCIServer::wrapDoubleList(const std::string& /* objID */, const int /* variable */, const std::vector<double>& value) {
173
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_DOUBLELIST);
174
myWrapperStorage.writeDoubleList(value);
175
return true;
176
}
177
178
179
bool
180
TraCIServer::wrapPosition(const std::string& /* objID */, const int variable, const libsumo::TraCIPosition& value) {
181
const bool includeZ = variable == libsumo::VAR_POSITION3D;
182
myWrapperStorage.writeUnsignedByte(includeZ ? libsumo::POSITION_3D : libsumo::POSITION_2D);
183
myWrapperStorage.writeDouble(value.x);
184
myWrapperStorage.writeDouble(value.y);
185
if (includeZ) {
186
myWrapperStorage.writeDouble(value.z);
187
}
188
return true;
189
}
190
191
192
bool
193
TraCIServer::wrapPositionVector(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIPositionVector& shape) {
194
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_POLYGON);
195
if (shape.value.size() < 256) {
196
myWrapperStorage.writeUnsignedByte((int)shape.value.size());
197
} else {
198
myWrapperStorage.writeUnsignedByte(0);
199
myWrapperStorage.writeInt((int)shape.value.size());
200
}
201
for (const libsumo::TraCIPosition& pos : shape.value) {
202
myWrapperStorage.writeDouble(pos.x);
203
myWrapperStorage.writeDouble(pos.y);
204
}
205
return true;
206
}
207
208
209
bool
210
TraCIServer::wrapColor(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIColor& value) {
211
myWrapperStorage.writeUnsignedByte(libsumo::TYPE_COLOR);
212
myWrapperStorage.writeUnsignedByte(value.r);
213
myWrapperStorage.writeUnsignedByte(value.g);
214
myWrapperStorage.writeUnsignedByte(value.b);
215
myWrapperStorage.writeUnsignedByte(value.a);
216
return true;
217
}
218
219
220
bool
221
TraCIServer::wrapStringDoublePair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, double>& value) {
222
StoHelp::writeCompound(myWrapperStorage, 2);
223
StoHelp::writeTypedString(myWrapperStorage, value.first);
224
StoHelp::writeTypedDouble(myWrapperStorage, value.second);
225
return true;
226
}
227
228
229
bool
230
TraCIServer::wrapStringDoublePairList(const std::string& /* objID */, const int /* variable */, const std::vector<std::pair<std::string, double> >& value) {
231
StoHelp::writeCompound(myWrapperStorage, (int)value.size());
232
for (const auto& p : value) {
233
myWrapperStorage.writeString(p.first);
234
myWrapperStorage.writeDouble(p.second);
235
}
236
return true;
237
}
238
239
240
bool
241
TraCIServer::wrapStringPair(const std::string& /* objID */, const int /* variable */, const std::pair<std::string, std::string>& value) {
242
StoHelp::writeCompound(myWrapperStorage, 2);
243
StoHelp::writeTypedString(myWrapperStorage, value.first);
244
StoHelp::writeTypedString(myWrapperStorage, value.second);
245
return true;
246
}
247
248
249
bool
250
TraCIServer::wrapIntPair(const std::string& /* objID */, const int /* variable */, const std::pair<int, int>& value) {
251
StoHelp::writeCompound(myWrapperStorage, 2);
252
StoHelp::writeTypedInt(myWrapperStorage, value.first);
253
StoHelp::writeTypedInt(myWrapperStorage, value.second);
254
return true;
255
}
256
257
258
bool
259
TraCIServer::wrapStage(const std::string& /* objID */, const int /* variable */, const libsumo::TraCIStage& value) {
260
StoHelp::writeStage(myWrapperStorage, value);
261
return true;
262
}
263
264
265
bool
266
TraCIServer::wrapReservationVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIReservation>& value) {
267
StoHelp::writeCompound(myWrapperStorage, (int)value.size());
268
for (const libsumo::TraCIReservation& r : value) {
269
StoHelp::writeCompound(myWrapperStorage, 10);
270
StoHelp::writeTypedString(myWrapperStorage, r.id);
271
StoHelp::writeTypedStringList(myWrapperStorage, r.persons);
272
StoHelp::writeTypedString(myWrapperStorage, r.group);
273
StoHelp::writeTypedString(myWrapperStorage, r.fromEdge);
274
StoHelp::writeTypedString(myWrapperStorage, r.toEdge);
275
StoHelp::writeTypedDouble(myWrapperStorage, r.departPos);
276
StoHelp::writeTypedDouble(myWrapperStorage, r.arrivalPos);
277
StoHelp::writeTypedDouble(myWrapperStorage, r.depart);
278
StoHelp::writeTypedDouble(myWrapperStorage, r.reservationTime);
279
StoHelp::writeTypedInt(myWrapperStorage, r.state);
280
}
281
return true;
282
}
283
284
285
bool
286
TraCIServer::wrapLogicVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCILogic>& value) {
287
StoHelp::writeCompound(myWrapperStorage, (int)value.size());
288
for (const libsumo::TraCILogic& logic : value) {
289
StoHelp::writeCompound(myWrapperStorage, 5);
290
StoHelp::writeTypedString(myWrapperStorage, logic.programID);
291
StoHelp::writeTypedInt(myWrapperStorage, logic.type);
292
StoHelp::writeTypedInt(myWrapperStorage, logic.currentPhaseIndex);
293
StoHelp::writeCompound(myWrapperStorage, (int)logic.phases.size());
294
for (const std::shared_ptr<libsumo::TraCIPhase>& phase : logic.phases) {
295
StoHelp::writeCompound(myWrapperStorage, 6);
296
StoHelp::writeTypedDouble(myWrapperStorage, phase->duration);
297
StoHelp::writeTypedString(myWrapperStorage, phase->state);
298
StoHelp::writeTypedDouble(myWrapperStorage, phase->minDur);
299
StoHelp::writeTypedDouble(myWrapperStorage, phase->maxDur);
300
StoHelp::writeCompound(myWrapperStorage, (int)phase->next.size());
301
for (int n : phase->next) {
302
StoHelp::writeTypedInt(myWrapperStorage, n);
303
}
304
StoHelp::writeTypedString(myWrapperStorage, phase->name);
305
}
306
StoHelp::writeCompound(myWrapperStorage, (int)logic.subParameter.size());
307
for (const auto& item : logic.subParameter) {
308
StoHelp::writeTypedStringList(myWrapperStorage, std::vector<std::string> {item.first, item.second});
309
}
310
}
311
return true;
312
}
313
314
315
bool
316
TraCIServer::wrapLinkVectorVector(const std::string& /* objID */, const int /* variable */, const std::vector<std::vector<libsumo::TraCILink> >& value) {
317
int cnt = 1;
318
for (const std::vector<libsumo::TraCILink>& sublinks : value) {
319
cnt += (int)sublinks.size() + 1;
320
}
321
StoHelp::writeCompound(myWrapperStorage, cnt);
322
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
323
for (const std::vector<libsumo::TraCILink>& sublinks : value) {
324
StoHelp::writeTypedInt(myWrapperStorage, (int)sublinks.size());
325
for (const libsumo::TraCILink& link : sublinks) {
326
StoHelp::writeTypedStringList(myWrapperStorage, std::vector<std::string>({ link.fromLane, link.toLane, link.viaLane }));
327
}
328
}
329
return true;
330
}
331
332
333
bool
334
TraCIServer::wrapSignalConstraintVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCISignalConstraint>& value) {
335
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 5);
336
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
337
for (const auto& c : value) {
338
StoHelp::writeConstraint(myWrapperStorage, c);
339
}
340
return true;
341
}
342
343
344
bool
345
TraCIServer::wrapJunctionFoeVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIJunctionFoe>& value) {
346
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 9);
347
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
348
for (const auto& c : value) {
349
StoHelp::writeTypedString(myWrapperStorage, c.foeId);
350
StoHelp::writeTypedDouble(myWrapperStorage, c.egoDist);
351
StoHelp::writeTypedDouble(myWrapperStorage, c.foeDist);
352
StoHelp::writeTypedDouble(myWrapperStorage, c.egoExitDist);
353
StoHelp::writeTypedDouble(myWrapperStorage, c.foeExitDist);
354
StoHelp::writeTypedString(myWrapperStorage, c.egoLane);
355
StoHelp::writeTypedString(myWrapperStorage, c.foeLane);
356
StoHelp::writeTypedUnsignedByte(myWrapperStorage, c.egoResponse);
357
StoHelp::writeTypedUnsignedByte(myWrapperStorage, c.foeResponse);
358
}
359
return true;
360
}
361
362
363
bool
364
TraCIServer::wrapNextStopDataVector(const std::string& /* objID */, const int variable, const std::vector<libsumo::TraCINextStopData>& value) {
365
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 4);
366
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
367
const bool full = variable == libsumo::VAR_NEXT_STOPS2;
368
for (const auto& s : value) {
369
const int legacyStopFlags = (s.stopFlags << 1) + (s.arrival >= 0 ? 1 : 0);
370
StoHelp::writeTypedString(myWrapperStorage, s.lane);
371
StoHelp::writeTypedDouble(myWrapperStorage, s.endPos);
372
StoHelp::writeTypedString(myWrapperStorage, s.stoppingPlaceID);
373
StoHelp::writeTypedInt(myWrapperStorage, full ? s.stopFlags : legacyStopFlags);
374
StoHelp::writeTypedDouble(myWrapperStorage, s.duration);
375
StoHelp::writeTypedDouble(myWrapperStorage, s.until);
376
if (full) {
377
StoHelp::writeTypedDouble(myWrapperStorage, s.startPos);
378
StoHelp::writeTypedDouble(myWrapperStorage, s.intendedArrival);
379
StoHelp::writeTypedDouble(myWrapperStorage, s.arrival);
380
StoHelp::writeTypedDouble(myWrapperStorage, s.depart);
381
StoHelp::writeTypedString(myWrapperStorage, s.split);
382
StoHelp::writeTypedString(myWrapperStorage, s.join);
383
StoHelp::writeTypedString(myWrapperStorage, s.actType);
384
StoHelp::writeTypedString(myWrapperStorage, s.tripId);
385
StoHelp::writeTypedString(myWrapperStorage, s.line);
386
StoHelp::writeTypedDouble(myWrapperStorage, s.speed);
387
}
388
}
389
return true;
390
}
391
392
393
bool
394
TraCIServer::wrapVehicleDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIVehicleData>& value) {
395
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 5);
396
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
397
for (const libsumo::TraCIVehicleData& vd : value) {
398
StoHelp::writeTypedString(myWrapperStorage, vd.id);
399
StoHelp::writeTypedDouble(myWrapperStorage, vd.length);
400
StoHelp::writeTypedDouble(myWrapperStorage, vd.entryTime);
401
StoHelp::writeTypedDouble(myWrapperStorage, vd.leaveTime);
402
StoHelp::writeTypedString(myWrapperStorage, vd.typeID);
403
}
404
return true;
405
}
406
407
408
bool
409
TraCIServer::wrapBestLanesDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCIBestLanesData>& value) {
410
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 6);
411
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
412
for (const libsumo::TraCIBestLanesData& bld : value) {
413
StoHelp::writeTypedString(myWrapperStorage, bld.laneID);
414
StoHelp::writeTypedDouble(myWrapperStorage, bld.length);
415
StoHelp::writeTypedDouble(myWrapperStorage, bld.occupation);
416
StoHelp::writeTypedByte(myWrapperStorage, bld.bestLaneOffset);
417
StoHelp::writeTypedUnsignedByte(myWrapperStorage, bld.allowsContinuation ? 1 : 0);
418
StoHelp::writeTypedStringList(myWrapperStorage, bld.continuationLanes);
419
}
420
return true;
421
}
422
423
424
bool
425
TraCIServer::wrapNextTLSDataVector(const std::string& /* objID */, const int /* variable */, const std::vector<libsumo::TraCINextTLSData>& value) {
426
StoHelp::writeCompound(myWrapperStorage, 1 + (int)value.size() * 4);
427
StoHelp::writeTypedInt(myWrapperStorage, (int)value.size());
428
for (const libsumo::TraCINextTLSData& tlsd : value) {
429
StoHelp::writeTypedString(myWrapperStorage, tlsd.id);
430
StoHelp::writeTypedInt(myWrapperStorage, tlsd.tlIndex);
431
StoHelp::writeTypedDouble(myWrapperStorage, tlsd.dist);
432
StoHelp::writeTypedByte(myWrapperStorage, tlsd.state);
433
}
434
return true;
435
}
436
437
438
tcpip::Storage&
439
TraCIServer::getWrapperStorage() {
440
return myWrapperStorage;
441
}
442
443
444
445
TraCIServer::TraCIServer(const SUMOTime begin, const int port, const int numClients)
446
: myTargetTime(begin), myLastContextSubscription(nullptr) {
447
#ifdef DEBUG_MULTI_CLIENTS
448
std::cout << "Creating new TraCIServer for " << numClients << " clients on port " << port << "." << std::endl;
449
#endif
450
myVehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
451
myVehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
452
myVehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
453
myVehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
454
myVehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
455
myVehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
456
myVehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
457
myVehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
458
myVehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
459
myVehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
460
myVehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
461
myVehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
462
myVehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
463
464
myTransportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
465
myTransportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
466
myTransportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
467
myTransportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
468
469
myExecutors[libsumo::CMD_SET_INDUCTIONLOOP_VARIABLE] = &TraCIServerAPI_InductionLoop::processSet;
470
myExecutors[libsumo::CMD_SET_LANEAREA_VARIABLE] = &TraCIServerAPI_LaneArea::processSet;
471
myExecutors[libsumo::CMD_SET_MULTIENTRYEXIT_VARIABLE] = &TraCIServerAPI_MultiEntryExit::processSet;
472
473
myExecutors[libsumo::CMD_SET_TL_VARIABLE] = &TraCIServerAPI_TrafficLight::processSet;
474
myExecutors[libsumo::CMD_SET_LANE_VARIABLE] = &TraCIServerAPI_Lane::processSet;
475
myExecutors[libsumo::CMD_SET_VEHICLE_VARIABLE] = &TraCIServerAPI_Vehicle::processSet;
476
myExecutors[libsumo::CMD_SET_VEHICLETYPE_VARIABLE] = &TraCIServerAPI_VehicleType::processSet;
477
myExecutors[libsumo::CMD_SET_ROUTE_VARIABLE] = &TraCIServerAPI_Route::processSet;
478
myExecutors[libsumo::CMD_SET_POI_VARIABLE] = &TraCIServerAPI_POI::processSet;
479
myExecutors[libsumo::CMD_SET_POLYGON_VARIABLE] = &TraCIServerAPI_Polygon::processSet;
480
myExecutors[libsumo::CMD_SET_JUNCTION_VARIABLE] = &TraCIServerAPI_Junction::processSet;
481
myExecutors[libsumo::CMD_SET_EDGE_VARIABLE] = &TraCIServerAPI_Edge::processSet;
482
myExecutors[libsumo::CMD_SET_SIM_VARIABLE] = &TraCIServerAPI_Simulation::processSet;
483
myExecutors[libsumo::CMD_SET_PERSON_VARIABLE] = &TraCIServerAPI_Person::processSet;
484
myExecutors[libsumo::CMD_SET_CALIBRATOR_VARIABLE] = &TraCIServerAPI_Calibrator::processSet;
485
myExecutors[libsumo::CMD_SET_BUSSTOP_VARIABLE] = &TraCIServerAPI_BusStop::processSet;
486
myExecutors[libsumo::CMD_SET_PARKINGAREA_VARIABLE] = &TraCIServerAPI_ParkingArea::processSet;
487
myExecutors[libsumo::CMD_SET_CHARGINGSTATION_VARIABLE] = &TraCIServerAPI_ChargingStation::processSet;
488
myExecutors[libsumo::CMD_SET_ROUTEPROBE_VARIABLE] = &TraCIServerAPI_RouteProbe::processSet;
489
myExecutors[libsumo::CMD_SET_REROUTER_VARIABLE] = &TraCIServerAPI_Rerouter::processSet;
490
myExecutors[libsumo::CMD_SET_VARIABLESPEEDSIGN_VARIABLE] = &TraCIServerAPI_VariableSpeedSign::processSet;
491
//myExecutors[libsumo::CMD_SET_MEANDATA_VARIABLE] = &TraCIServerAPI_MeanData::processSet;
492
myExecutors[libsumo::CMD_SET_OVERHEADWIRE_VARIABLE] = &TraCIServerAPI_OverheadWire::processSet;
493
494
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_EDGE_VARIABLE, libsumo::VAR_EDGE_TRAVELTIME));
495
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_EDGE_VARIABLE, libsumo::VAR_EDGE_EFFORT));
496
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_EDGE_VARIABLE, libsumo::VAR_ANGLE));
497
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_LANE_VARIABLE, libsumo::VAR_ANGLE));
498
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_LANE_VARIABLE, libsumo::LANE_CHANGES));
499
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_LANE_VARIABLE, libsumo::VAR_FOES));
500
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE, libsumo::DISTANCE_REQUEST));
501
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE, libsumo::VAR_EDGES));
502
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE, libsumo::VAR_STAGE));
503
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE, libsumo::VAR_TAXI_RESERVATIONS));
504
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE, libsumo::SPLIT_TAXI_RESERVATIONS));
505
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::TL_BLOCKING_VEHICLES));
506
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::TL_RIVAL_VEHICLES));
507
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::TL_PRIORITY_VEHICLES));
508
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::TL_CONSTRAINT));
509
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::TL_CONSTRAINT_BYFOE));
510
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_TL_VARIABLE, libsumo::VAR_PERSON_NUMBER));
511
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::DISTANCE_REQUEST));
512
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_EDGE_TRAVELTIME));
513
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_EDGE_EFFORT));
514
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_FOLLOW_SPEED));
515
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_SECURE_GAP));
516
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_STOP_SPEED));
517
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_FOES));
518
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::CMD_CHANGELANE));
519
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_LEADER));
520
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_FOLLOWER));
521
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_NEIGHBORS));
522
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_STOP_PARAMETER));
523
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_NEXT_STOPS)); // this is just a dummy to trigger an error
524
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_NEXT_STOPS2));
525
myParameterized.insert(std::make_pair(libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE, libsumo::VAR_TAXI_FLEET));
526
myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER));
527
myParameterized.insert(std::make_pair(0, libsumo::VAR_PARAMETER_WITH_KEY));
528
529
myDoCloseConnection = false;
530
531
// display warning if internal lanes are not used
532
// TODO this may be redundant to the warning in NLBuilder::build
533
if (!MSGlobals::gUsingInternalLanes && !MSGlobals::gUseMesoSim) {
534
WRITE_WARNING(TL("Starting TraCI without using internal lanes!"));
535
MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false);
536
MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false);
537
}
538
539
try {
540
WRITE_MESSAGEF(TL("***Starting server on port % ***"), toString(port));
541
tcpip::Socket serverSocket(port);
542
if (numClients > 1) {
543
WRITE_MESSAGEF(TL(" waiting for % clients..."), toString(numClients));
544
}
545
while ((int)mySockets.size() < numClients) {
546
int index = (int)mySockets.size() + libsumo::MAX_ORDER + 1;
547
mySockets[index] = new SocketInfo(serverSocket.accept(true), begin);
548
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::BUILT] = std::vector<std::string>();
549
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::DEPARTED] = std::vector<std::string>();
550
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_TELEPORT] = std::vector<std::string>();
551
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_TELEPORT] = std::vector<std::string>();
552
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ARRIVED] = std::vector<std::string>();
553
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::NEWROUTE] = std::vector<std::string>();
554
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_PARKING] = std::vector<std::string>();
555
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::MANEUVERING] = std::vector<std::string>();
556
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_PARKING] = std::vector<std::string>();
557
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::STARTING_STOP] = std::vector<std::string>();
558
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::ENDING_STOP] = std::vector<std::string>();
559
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::COLLISION] = std::vector<std::string>();
560
mySockets[index]->vehicleStateChanges[MSNet::VehicleState::EMERGENCYSTOP] = std::vector<std::string>();
561
562
mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_DEPARTED] = std::vector<std::string>();
563
mySockets[index]->transportableStateChanges[MSNet::TransportableState::PERSON_ARRIVED] = std::vector<std::string>();
564
mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_DEPARTED] = std::vector<std::string>();
565
mySockets[index]->transportableStateChanges[MSNet::TransportableState::CONTAINER_ARRIVED] = std::vector<std::string>();
566
if (numClients > 1) {
567
WRITE_MESSAGE(TL(" client connected"));
568
}
569
}
570
// When got here, all clients have connected
571
if (numClients > 1) {
572
checkClientOrdering();
573
}
574
// set myCurrentSocket != mySockets.end() to indicate that this is the first step in processCommands()
575
myCurrentSocket = mySockets.begin();
576
} catch (tcpip::SocketException& e) {
577
throw ProcessError(e.what());
578
}
579
}
580
581
582
TraCIServer::~TraCIServer() {
583
for (const auto& socket : mySockets) {
584
delete socket.second;
585
}
586
// there is no point in calling cleanup() here, it does not free any pointers and will only modify members which get deleted anyway
587
}
588
589
590
// ---------- Initialisation and Shutdown
591
void
592
TraCIServer::openSocket(const std::map<int, CmdExecutor>& execs) {
593
if (myInstance == nullptr && !myDoCloseConnection && (OptionsCont::getOptions().getInt("remote-port") != 0)) {
594
myInstance = new TraCIServer(string2time(OptionsCont::getOptions().getString("begin")),
595
OptionsCont::getOptions().getInt("remote-port"),
596
OptionsCont::getOptions().getInt("num-clients"));
597
for (std::map<int, CmdExecutor>::const_iterator i = execs.begin(); i != execs.end(); ++i) {
598
myInstance->myExecutors[i->first] = i->second;
599
}
600
}
601
if (myInstance != nullptr) {
602
// maybe net was deleted and built again
603
MSNet::getInstance()->addVehicleStateListener(myInstance);
604
MSNet::getInstance()->addTransportableStateListener(myInstance);
605
myInstance->mySubscriptionCache.writeInt(0);
606
}
607
}
608
609
610
void
611
TraCIServer::close() {
612
if (myInstance == nullptr) {
613
return;
614
}
615
delete myInstance;
616
myInstance = nullptr;
617
myDoCloseConnection = true;
618
}
619
620
621
bool
622
TraCIServer::wasClosed() {
623
return myDoCloseConnection;
624
}
625
626
627
// ---------- Initialisation and Shutdown
628
629
630
void
631
TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
632
if (!myDoCloseConnection) {
633
myVehicleStateChanges[to].push_back(vehicle->getID());
634
for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
635
i->second->vehicleStateChanges[to].push_back(vehicle->getID());
636
}
637
}
638
}
639
640
641
void
642
TraCIServer::transportableStateChanged(const MSTransportable* const transportable, MSNet::TransportableState to, const std::string& /*info*/) {
643
if (!myDoCloseConnection) {
644
myTransportableStateChanges[to].push_back(transportable->getID());
645
for (std::map<int, SocketInfo*>::iterator i = mySockets.begin(); i != mySockets.end(); ++i) {
646
i->second->transportableStateChanges[to].push_back(transportable->getID());
647
}
648
}
649
}
650
651
652
void
653
TraCIServer::checkClientOrdering() {
654
#ifdef DEBUG_MULTI_CLIENTS
655
std::cout << "Checking client order requests." << std::endl;
656
#endif
657
// check for SET_ORDER commands queued by connected clients
658
// In multiclient cas it is mandatory that SET_ORDER is sent as the first command (or directly after GET_VERSION)
659
myCurrentSocket = mySockets.begin();
660
while (myCurrentSocket != mySockets.end()) {
661
#ifdef DEBUG_MULTI_CLIENTS
662
std::cout << " Socket " << myCurrentSocket->second->socket << ":" << std::endl;
663
#endif
664
// bool clientUnordered = true;
665
while (true) {
666
myInputStorage.reset();
667
myCurrentSocket->second->socket->receiveExact(myInputStorage);
668
int commandStart, commandLength;
669
int commandId = readCommandID(commandStart, commandLength);
670
#ifdef DEBUG_MULTI_CLIENTS
671
std::cout << " received command " << commandId << std::endl;
672
#endif
673
// Whether the received command is a permitted command for the initialization phase.
674
// Currently, getVersion and setOrder are permitted.
675
bool initCommand = commandId == libsumo::CMD_SETORDER || commandId == libsumo::CMD_GETVERSION;
676
if (initCommand) {
677
#ifdef DEBUG_MULTI_CLIENTS
678
std::cout << " Init command. Sending response." << std::endl;
679
#endif
680
// reset input storage to initial state before reading the commandId
681
// (ugly, but we can't just reset the store's iter_ from here)
682
// Giving the commandId to dispatch command didn't work either
683
tcpip::Storage tmp;
684
tmp.writeStorage(myInputStorage);
685
myInputStorage.reset();
686
// we don't know whether the command was set with extended
687
// length syntax or not so we hardcode the length here (#5037)
688
myInputStorage.writeUnsignedByte(commandId == libsumo::CMD_SETORDER ? 6 : 2);
689
myInputStorage.writeUnsignedByte(commandId);
690
myInputStorage.writeStorage(tmp);
691
692
// Handle initialization command completely
693
dispatchCommand();
694
myCurrentSocket->second->socket->sendExact(myOutputStorage);
695
myOutputStorage.reset();
696
} else {
697
#ifdef DEBUG_MULTI_CLIENTS
698
std::cout << " Client " << myCurrentSocket->second->socket << " did not set order initially." << std::endl;
699
#endif
700
throw ProcessError(TL("Execution order (libsumo::CMD_SETORDER) was not set for all TraCI clients in pre-execution phase."));
701
}
702
if (commandId == libsumo::CMD_SETORDER) {
703
// This is what we have waited for.
704
break;
705
}
706
}
707
++myCurrentSocket;
708
}
709
}
710
711
712
void
713
TraCIServer::processReorderingRequests() {
714
// Process reordering requests
715
if (mySocketReorderRequests.size() > 0) {
716
// process reordering requests
717
std::map<int, SocketInfo*>::const_iterator i = mySocketReorderRequests.begin();
718
std::map<int, SocketInfo*>::iterator j;
719
#ifdef DEBUG_MULTI_CLIENTS
720
std::cout << SIMTIME << " Current socket ordering:\n";
721
for (j = mySockets.begin(); j != mySockets.end(); ++j) {
722
std::cout << " " << j->first << ": " << j->second->socket << "\n";
723
}
724
std::cout << "Reordering requests:\n";
725
for (i = mySocketReorderRequests.begin(); i != mySocketReorderRequests.end(); ++i) {
726
std::cout << " Socket " << i->second->socket << " -> " << i->first << "\n";
727
}
728
i = mySocketReorderRequests.begin();
729
#endif
730
while (i != mySocketReorderRequests.end()) {
731
j = mySockets.begin();
732
while (j != mySockets.end()) {
733
if (j->second->socket == i->second->socket) {
734
break;
735
} else {
736
j++;
737
}
738
}
739
assert(j != mySockets.end());
740
mySockets.erase(j);
741
mySockets[i->first] = i->second;
742
++i;
743
}
744
mySocketReorderRequests.clear();
745
#ifdef DEBUG_MULTI_CLIENTS
746
std::cout << "New socket ordering:\n";
747
for (j = mySockets.begin(); j != mySockets.end(); ++j) {
748
std::cout << " " << j->first << ": " << j->second->socket << "\n";
749
}
750
std::cout << std::endl;
751
#endif
752
}
753
}
754
755
756
SUMOTime
757
TraCIServer::nextTargetTime() const {
758
#ifdef DEBUG_MULTI_CLIENTS
759
std::cout << "\n Determining new target time..." << std::endl;
760
if (mySockets.size() == 0) {
761
std::cout << " All clients have disconnected." << std::endl;
762
}
763
#endif
764
std::map<int, SocketInfo*>::const_iterator i;
765
SUMOTime targetTime = std::numeric_limits<SUMOTime>::max();
766
for (i = mySockets.begin(); i != mySockets.end(); ++i) {
767
#ifdef DEBUG_MULTI_CLIENTS
768
std::cout << " target time for client " << i->second->socket << ": " << i->second->targetTime << "\n";
769
#endif
770
targetTime = MIN2(targetTime, i->second->targetTime);
771
}
772
#ifdef DEBUG_MULTI_CLIENTS
773
std::cout << std::endl;
774
#endif
775
return targetTime;
776
}
777
778
779
// send out subscription results to clients which will act in this step (i.e. with client target time <= myTargetTime)
780
void
781
TraCIServer::sendOutputToAll() const {
782
#ifdef DEBUG_MULTI_CLIENTS
783
std::cout << "\n Sending subscription results to clients:\n";
784
#endif
785
std::map<int, SocketInfo*>::const_iterator i = mySockets.begin();
786
while (i != mySockets.end()) {
787
if (i->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
788
// this client will become active before the next SUMO step. Provide subscription results.
789
i->second->socket->sendExact(myOutputStorage);
790
#ifdef DEBUG_MULTI_CLIENTS
791
std::cout << i->second->socket << "\n";
792
#endif
793
}
794
++i;
795
}
796
#ifdef DEBUG_MULTI_CLIENTS
797
std::cout << std::endl;
798
#endif
799
}
800
801
802
int
803
TraCIServer::processCommands(const SUMOTime step, const bool afterMove) {
804
#ifdef DEBUG_MULTI_CLIENTS
805
std::cout << SIMTIME << " processCommands(step = " << step << "):\n" << std::endl;
806
#endif
807
try {
808
int finalCmd = 0;
809
const bool firstStep = myCurrentSocket != mySockets.end();
810
// update client order if requested
811
processReorderingRequests();
812
if (!firstStep && !afterMove) {
813
// This is the entry point after performing a SUMO step (block is skipped before first SUMO step since then no simulation results have to be sent)
814
// update subscription results
815
postProcessSimulationStep();
816
// Send out subscription results to clients which will act in this SUMO step (i.e. with client target time <= current sumo timestep end)
817
sendOutputToAll();
818
myOutputStorage.reset();
819
}
820
821
// determine minimal next target time among clients
822
myTargetTime = nextTargetTime();
823
824
if (step < myTargetTime) {
825
#ifdef DEBUG_MULTI_CLIENTS
826
std::cout << " next target time is larger than next SUMO simstep (" << step << "). Returning from processCommands()." << std::endl;
827
#endif
828
return finalCmd;
829
}
830
831
// Simulation should run until
832
// 1. end time reached or
833
// 2. got libsumo::CMD_CLOSE or
834
// 3. got libsumo::CMD_LOAD or
835
// 4. Client closes socket connection
836
while (!myDoCloseConnection && myTargetTime <= (MSNet::getInstance()->getCurrentTimeStep()) && finalCmd != libsumo::CMD_EXECUTEMOVE) {
837
#ifdef DEBUG_MULTI_CLIENTS
838
std::cout << " Next target time: " << myTargetTime << std::endl;
839
#endif
840
// Iterate over clients and process communication for the ones with target time == myTargetTime
841
myCurrentSocket = mySockets.begin();
842
while (myCurrentSocket != mySockets.end()) {
843
#ifdef DEBUG_MULTI_CLIENTS
844
std::cout << " current socket: " << myCurrentSocket->second->socket
845
<< " with target time=" << myCurrentSocket->second->targetTime
846
<< std::endl;
847
#endif
848
849
if (myCurrentSocket->second->targetTime > myTargetTime || (afterMove && !myCurrentSocket->second->executeMove)) {
850
// this client must wait
851
#ifdef DEBUG_MULTI_CLIENTS
852
std::cout << " skipping client " << myCurrentSocket->second->socket
853
<< " with target time=" << myCurrentSocket->second->targetTime << std::endl;
854
#endif
855
myCurrentSocket++;
856
continue;
857
}
858
finalCmd = 0;
859
while (finalCmd == 0) {
860
if (!myInputStorage.valid_pos()) {
861
// have read request completely, send response if adequate
862
if (myOutputStorage.size() > 0) {
863
// send response to previous query
864
myCurrentSocket->second->socket->sendExact(myOutputStorage);
865
myOutputStorage.reset();
866
}
867
#ifdef DEBUG_MULTI_CLIENTS
868
std::cout << " resetting input storage and reading next command..." << std::endl;
869
#endif
870
// Read next request
871
myInputStorage.reset();
872
myCurrentSocket->second->socket->receiveExact(myInputStorage);
873
}
874
875
while (myInputStorage.valid_pos() && !myDoCloseConnection) {
876
const int cmd = dispatchCommand();
877
if (cmd == libsumo::CMD_SIMSTEP || cmd == libsumo::CMD_LOAD || cmd == libsumo::CMD_EXECUTEMOVE || cmd == libsumo::CMD_CLOSE) {
878
finalCmd = cmd;
879
}
880
}
881
}
882
}
883
if (!myLoadArgs.empty()) {
884
#ifdef DEBUG_MULTI_CLIENTS
885
std::cout << " Breaking loop to load new simulation." << std::endl;
886
#endif
887
break;
888
} else if (myDoCloseConnection) {
889
#ifdef DEBUG_MULTI_CLIENTS
890
std::cout << " Breaking loop because last client closed connection." << std::endl;
891
#endif
892
break;
893
}
894
SUMOTime nextT = nextTargetTime();
895
// minimal target time among clients should have been increased during the last loop through mySockets
896
// XXX: The assert below is disabled since many tests do sth. like simulationStep(step). Such that for a first call step=0,
897
// leading to targetTime==1000 (increased by DELTA_T in dispatchCommand()),
898
// the next call is then usually simulationStep(step=1000) leading to no further increase
899
// and thus a failing assertion here.
900
//assert(myTargetTime < nextT || myDoCloseConnection);
901
myTargetTime = nextT;
902
}
903
// All clients are done with the current time step
904
// Reset myVehicleStateChanges and myTransportableStateChanges
905
for (auto& item : myVehicleStateChanges) {
906
item.second.clear();
907
}
908
for (auto& item : myTransportableStateChanges) {
909
item.second.clear();
910
}
911
return finalCmd;
912
} catch (std::invalid_argument& e) {
913
throw ProcessError(e.what());
914
} catch (libsumo::TraCIException& e) {
915
throw ProcessError(e.what());
916
} catch (tcpip::SocketException& e) {
917
throw ProcessError(e.what());
918
}
919
}
920
921
922
bool
923
TraCIServer::processGet(const int commandID, tcpip::Storage& inputStorage, tcpip::Storage& outputStorage) {
924
const int variable = inputStorage.readUnsignedByte();
925
const std::string id = inputStorage.readString();
926
initWrapper(commandID + 0x10, variable, id);
927
try {
928
switch (commandID) {
929
case libsumo::CMD_GET_INDUCTIONLOOP_VARIABLE:
930
if (!libsumo::InductionLoop::handleVariable(id, variable, this, &inputStorage)) {
931
throw libsumo::TraCIException("Get Induction Loop Variable: unsupported variable " + toHex(variable, 2) + " specified");
932
}
933
break;
934
case libsumo::CMD_GET_MULTIENTRYEXIT_VARIABLE:
935
if (!libsumo::MultiEntryExit::handleVariable(id, variable, this, &inputStorage)) {
936
throw libsumo::TraCIException("Get Multi Entry Exit Detector Variable: unsupported variable " + toHex(variable, 2) + " specified");
937
}
938
break;
939
case libsumo::CMD_GET_TL_VARIABLE:
940
if (!libsumo::TrafficLight::handleVariable(id, variable, this, &inputStorage)) {
941
switch (variable) {
942
case libsumo::TL_CONSTRAINT_SWAP: {
943
StoHelp::readCompound(inputStorage, 3, "A compound object of size 3 is needed for swapping constraints.");
944
const std::string tripId = StoHelp::readTypedString(inputStorage, "The tripId must be given as a string.");
945
const std::string foeSignal = StoHelp::readTypedString(inputStorage, "The foeSignal id must be given as a string.");
946
const std::string foeId = StoHelp::readTypedString(inputStorage, "The foe tripId must be given as a string.");
947
wrapSignalConstraintVector(id, variable, libsumo::TrafficLight::swapConstraints(id, tripId, foeSignal, foeId));
948
break;
949
}
950
default:
951
throw libsumo::TraCIException("Get TLS Variable: unsupported variable " + toHex(variable, 2) + " specified");
952
}
953
}
954
break;
955
case libsumo::CMD_GET_LANE_VARIABLE:
956
if (!libsumo::Lane::handleVariable(id, variable, this, &inputStorage)) {
957
throw libsumo::TraCIException("Get Lane Variable: unsupported variable " + toHex(variable, 2) + " specified");
958
}
959
break;
960
case libsumo::CMD_GET_VEHICLE_VARIABLE:
961
if (!libsumo::Vehicle::handleVariable(id, variable, this, &inputStorage)) {
962
throw libsumo::TraCIException("Get Vehicle Variable: unsupported variable " + toHex(variable, 2) + " specified");
963
}
964
break;
965
case libsumo::CMD_GET_VEHICLETYPE_VARIABLE:
966
if (!libsumo::VehicleType::handleVariable(id, variable, this, &inputStorage)) {
967
throw libsumo::TraCIException("Get Vehicle Type Variable: unsupported variable " + toHex(variable, 2) + " specified");
968
}
969
break;
970
case libsumo::CMD_GET_ROUTE_VARIABLE:
971
if (!libsumo::Route::handleVariable(id, variable, this, &inputStorage)) {
972
throw libsumo::TraCIException("Get Route Variable: unsupported variable " + toHex(variable, 2) + " specified");
973
}
974
break;
975
case libsumo::CMD_GET_POI_VARIABLE:
976
if (!libsumo::POI::handleVariable(id, variable, this, &inputStorage)) {
977
throw libsumo::TraCIException("Get PoI Variable: unsupported variable " + toHex(variable, 2) + " specified");
978
}
979
break;
980
case libsumo::CMD_GET_POLYGON_VARIABLE:
981
if (!libsumo::Polygon::handleVariable(id, variable, this, &inputStorage)) {
982
throw libsumo::TraCIException("Get Polygon Variable: unsupported variable " + toHex(variable, 2) + " specified");
983
}
984
break;
985
case libsumo::CMD_GET_JUNCTION_VARIABLE:
986
if (!libsumo::Junction::handleVariable(id, variable, this, &inputStorage)) {
987
throw libsumo::TraCIException("Get Junction Variable: unsupported variable " + toHex(variable, 2) + " specified");
988
}
989
break;
990
case libsumo::CMD_GET_EDGE_VARIABLE:
991
if (!libsumo::Edge::handleVariable(id, variable, this, &inputStorage)) {
992
throw libsumo::TraCIException("Get Edge Variable: unsupported variable " + toHex(variable, 2) + " specified");
993
}
994
break;
995
case libsumo::CMD_GET_SIM_VARIABLE:
996
if (!TraCIServerAPI_Simulation::processGet(*this, inputStorage, id, variable)) {
997
throw libsumo::TraCIException("Get Simulation Variable: unsupported variable " + toHex(variable, 2) + " specified");
998
}
999
break;
1000
case libsumo::CMD_GET_LANEAREA_VARIABLE:
1001
if (!libsumo::LaneArea::handleVariable(id, variable, this, &inputStorage)) {
1002
throw libsumo::TraCIException("Get Lane Area Detector Variable: unsupported variable " + toHex(variable, 2) + " specified");
1003
}
1004
break;
1005
case libsumo::CMD_GET_PERSON_VARIABLE:
1006
if (!libsumo::Person::handleVariable(id, variable, this, &inputStorage)) {
1007
throw libsumo::TraCIException("Get Person Variable: unsupported variable " + toHex(variable, 2) + " specified");
1008
}
1009
break;
1010
case libsumo::CMD_GET_BUSSTOP_VARIABLE:
1011
if (!libsumo::BusStop::handleVariable(id, variable, this, &inputStorage)) {
1012
throw libsumo::TraCIException("Get BusStop Variable: unsupported variable " + toHex(variable, 2) + " specified");
1013
}
1014
break;
1015
case libsumo::CMD_GET_PARKINGAREA_VARIABLE:
1016
if (!libsumo::ParkingArea::handleVariable(id, variable, this, &inputStorage)) {
1017
throw libsumo::TraCIException("Get ParkingArea Variable: unsupported variable " + toHex(variable, 2) + " specified");
1018
}
1019
break;
1020
case libsumo::CMD_GET_CHARGINGSTATION_VARIABLE:
1021
if (!libsumo::ChargingStation::handleVariable(id, variable, this, &inputStorage)) {
1022
throw libsumo::TraCIException("Get ChargingStation Variable: unsupported variable " + toHex(variable, 2) + " specified");
1023
}
1024
break;
1025
case libsumo::CMD_GET_ROUTEPROBE_VARIABLE:
1026
if (!libsumo::RouteProbe::handleVariable(id, variable, this, &inputStorage)) {
1027
throw libsumo::TraCIException("Get RouteProbe Variable: unsupported variable " + toHex(variable, 2) + " specified");
1028
}
1029
break;
1030
case libsumo::CMD_GET_CALIBRATOR_VARIABLE:
1031
if (!libsumo::Calibrator::handleVariable(id, variable, this, &inputStorage)) {
1032
throw libsumo::TraCIException("Get Calibrator Variable: unsupported variable " + toHex(variable, 2) + " specified");
1033
}
1034
break;
1035
case libsumo::CMD_GET_REROUTER_VARIABLE:
1036
if (!libsumo::Rerouter::handleVariable(id, variable, this, &inputStorage)) {
1037
throw libsumo::TraCIException("Get Rerouter Variable: unsupported variable " + toHex(variable, 2) + " specified");
1038
}
1039
break;
1040
case libsumo::CMD_GET_VARIABLESPEEDSIGN_VARIABLE:
1041
if (!libsumo::VariableSpeedSign::handleVariable(id, variable, this, &inputStorage)) {
1042
throw libsumo::TraCIException("Get VariableSpeedSign Variable: unsupported variable " + toHex(variable, 2) + " specified");
1043
}
1044
break;
1045
case libsumo::CMD_GET_MEANDATA_VARIABLE:
1046
if (!libsumo::MeanData::handleVariable(id, variable, this, &inputStorage)) {
1047
throw libsumo::TraCIException("Get MeanData Variable: unsupported variable " + toHex(variable, 2) + " specified");
1048
}
1049
break;
1050
case libsumo::CMD_GET_OVERHEADWIRE_VARIABLE:
1051
if (!libsumo::OverheadWire::handleVariable(id, variable, this, &inputStorage)) {
1052
throw libsumo::TraCIException("Get OverheadWire Variable: unsupported variable " + toHex(variable, 2) + " specified");
1053
}
1054
break;
1055
default:
1056
return false;
1057
}
1058
} catch (libsumo::TraCIException& e) {
1059
return writeErrorStatusCmd(commandID, e.what(), outputStorage);
1060
}
1061
writeStatusCmd(commandID, libsumo::RTYPE_OK, "", outputStorage);
1062
writeResponseWithLength(outputStorage, getWrapperStorage());
1063
return true;
1064
}
1065
1066
1067
void
1068
TraCIServer::cleanup() {
1069
mySubscriptions.clear();
1070
myTargetTime = string2time(OptionsCont::getOptions().getString("begin"));
1071
for (myCurrentSocket = mySockets.begin(); myCurrentSocket != mySockets.end(); ++myCurrentSocket) {
1072
myCurrentSocket->second->targetTime = myTargetTime;
1073
myCurrentSocket->second->executeMove = false;
1074
}
1075
myOutputStorage.reset();
1076
myInputStorage.reset();
1077
mySubscriptionCache.reset();
1078
for (auto& i : myVehicleStateChanges) {
1079
i.second.clear();
1080
}
1081
for (auto& i : myTransportableStateChanges) {
1082
i.second.clear();
1083
}
1084
myCurrentSocket = mySockets.begin();
1085
}
1086
1087
1088
std::map<int, TraCIServer::SocketInfo*>::iterator
1089
TraCIServer::removeCurrentSocket() {
1090
#ifdef DEBUG_MULTI_CLIENTS
1091
std::cout << " Removing socket " << myCurrentSocket->second->socket
1092
<< " (order " << myCurrentSocket->first << ")" << std::endl;
1093
#endif
1094
delete myCurrentSocket->second;
1095
myCurrentSocket = mySockets.erase(myCurrentSocket);
1096
return myCurrentSocket;
1097
}
1098
1099
1100
int
1101
TraCIServer::readCommandID(int& commandStart, int& commandLength) {
1102
commandStart = myInputStorage.position();
1103
commandLength = myInputStorage.readUnsignedByte();
1104
if (commandLength == 0) {
1105
commandLength = myInputStorage.readInt();
1106
}
1107
#ifdef DEBUG_RAW_INPUT
1108
std::cout << " commandStart=" << commandStart << " commandLength=" << commandLength << " pos=" << myInputStorage.position() << " raw=";
1109
for (auto it = myInputStorage.begin(); it != myInputStorage.end(); ++it) {
1110
std::cout << (int)*it << " ";
1111
}
1112
std::cout << "\n";
1113
#endif
1114
return myInputStorage.readUnsignedByte();
1115
}
1116
1117
1118
int
1119
TraCIServer::dispatchCommand() {
1120
int commandStart, commandLength;
1121
int commandId = readCommandID(commandStart, commandLength);
1122
#ifdef DEBUG_MULTI_CLIENTS
1123
std::cout << " dispatchCommand() called for client " << myCurrentSocket->second->socket
1124
<< ", commandId = " << commandId << std::endl;
1125
#endif
1126
bool success = false;
1127
// dispatch commands
1128
if (myExecutors.find(commandId) != myExecutors.end()) {
1129
success = myExecutors[commandId](*this, myInputStorage, myOutputStorage);
1130
} else if ((commandId >= libsumo::CMD_GET_INDUCTIONLOOP_VARIABLE && commandId <= libsumo::CMD_GET_BUSSTOP_VARIABLE)
1131
|| (commandId >= libsumo::CMD_GET_PARKINGAREA_VARIABLE && commandId <= libsumo::CMD_GET_OVERHEADWIRE_VARIABLE)) {
1132
if (commandId == libsumo::CMD_GET_GUI_VARIABLE) {
1133
writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1134
} else {
1135
success = processGet(commandId, myInputStorage, myOutputStorage);
1136
}
1137
} else {
1138
switch (commandId) {
1139
case libsumo::CMD_GETVERSION:
1140
success = commandGetVersion();
1141
break;
1142
case libsumo::CMD_LOAD: {
1143
try {
1144
const std::vector<std::string> args = StoHelp::readTypedStringList(myInputStorage, "A load command needs a list of string arguments.");
1145
#ifdef DEBUG_MULTI_CLIENTS
1146
std::cout << " commandId == libsumo::CMD_LOAD"
1147
<< ", args = " << toString(args) << std::endl;
1148
#endif
1149
myLoadArgs = args;
1150
success = true;
1151
writeStatusCmd(libsumo::CMD_LOAD, libsumo::RTYPE_OK, "");
1152
// XXX: This only cares for the client that issued the load command.
1153
// Multiclient-load functionality is still to be implemented. Refs #3146.
1154
myCurrentSocket->second->socket->sendExact(myOutputStorage);
1155
myCurrentSocket = mySockets.end();
1156
myOutputStorage.reset();
1157
} catch (libsumo::TraCIException& e) {
1158
return writeErrorStatusCmd(libsumo::CMD_LOAD, e.what(), myOutputStorage);
1159
}
1160
break;
1161
}
1162
case libsumo::CMD_EXECUTEMOVE:
1163
myCurrentSocket->second->executeMove = true;
1164
myCurrentSocket++;
1165
success = true;
1166
writeStatusCmd(libsumo::CMD_EXECUTEMOVE, libsumo::RTYPE_OK, "");
1167
break;
1168
case libsumo::CMD_SIMSTEP: {
1169
const double nextT = myInputStorage.readDouble();
1170
if (nextT == 0.) {
1171
myCurrentSocket->second->targetTime += DELTA_T;
1172
} else {
1173
myCurrentSocket->second->targetTime = TIME2STEPS(nextT);
1174
}
1175
myCurrentSocket->second->executeMove = false;
1176
#ifdef DEBUG_MULTI_CLIENTS
1177
std::cout << " commandId == libsumo::CMD_SIMSTEP"
1178
<< ", next target time for client is " << myCurrentSocket->second->targetTime << std::endl;
1179
#endif
1180
if (myCurrentSocket->second->targetTime <= MSNet::getInstance()->getCurrentTimeStep()) {
1181
// This is not the last TraCI simstep in the current SUMO simstep -> send single simstep response.
1182
// @note: In the other case the simstep results are sent to all after the SUMO step was performed, see entry point for processCommands()
1183
sendSingleSimStepResponse();
1184
}
1185
// Clear vehicleStateChanges and transportableStateChanges for this client
1186
// -> For subsequent TraCI stepping
1187
// that is performed within this SUMO step, no updates on vehicle states
1188
// belonging to the last SUMO simulation step will be received by this client.
1189
for (auto& item : myCurrentSocket->second->vehicleStateChanges) {
1190
item.second.clear();
1191
}
1192
for (auto& item : myCurrentSocket->second->transportableStateChanges) {
1193
item.second.clear();
1194
}
1195
myCurrentSocket++;
1196
return commandId;
1197
}
1198
case libsumo::CMD_CLOSE:
1199
writeStatusCmd(libsumo::CMD_CLOSE, libsumo::RTYPE_OK, "");
1200
myCurrentSocket->second->socket->sendExact(myOutputStorage);
1201
myOutputStorage.reset();
1202
if (mySockets.size() == 1) {
1203
// Last client has closed connection
1204
myDoCloseConnection = true;
1205
}
1206
// remove current socket and increment to next socket in ordering
1207
myCurrentSocket = removeCurrentSocket();
1208
success = true;
1209
break;
1210
case libsumo::CMD_SETORDER: {
1211
const int order = myInputStorage.readInt();
1212
#ifdef DEBUG_MULTI_CLIENTS
1213
std::cout << " commandId == libsumo::CMD_SETORDER"
1214
<< ", order index is " << order << std::endl;
1215
#endif
1216
if (order > libsumo::MAX_ORDER) {
1217
return writeErrorStatusCmd(libsumo::CMD_SETORDER, "A set order command needs an int argument below " + toString(libsumo::MAX_ORDER) + ".", myOutputStorage);
1218
}
1219
if (mySockets.count(order) > 0 || mySocketReorderRequests.count(order) > 0) {
1220
return writeErrorStatusCmd(libsumo::CMD_SETORDER, "Order '" + toString(order) + "' is already taken.", myOutputStorage);
1221
}
1222
// memorize reorder request (will only take effect in the next step)
1223
mySocketReorderRequests[order] = myCurrentSocket->second;
1224
success = true;
1225
writeStatusCmd(libsumo::CMD_SETORDER, libsumo::RTYPE_OK, "");
1226
break;
1227
}
1228
case libsumo::CMD_SUBSCRIBE_BUSSTOP_VARIABLE:
1229
case libsumo::CMD_SUBSCRIBE_CALIBRATOR_VARIABLE:
1230
case libsumo::CMD_SUBSCRIBE_CHARGINGSTATION_VARIABLE:
1231
case libsumo::CMD_SUBSCRIBE_EDGE_VARIABLE:
1232
case libsumo::CMD_SUBSCRIBE_GUI_VARIABLE:
1233
case libsumo::CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE:
1234
case libsumo::CMD_SUBSCRIBE_JUNCTION_VARIABLE:
1235
case libsumo::CMD_SUBSCRIBE_LANE_VARIABLE:
1236
case libsumo::CMD_SUBSCRIBE_LANEAREA_VARIABLE:
1237
case libsumo::CMD_SUBSCRIBE_MEANDATA_VARIABLE:
1238
case libsumo::CMD_SUBSCRIBE_MULTIENTRYEXIT_VARIABLE:
1239
case libsumo::CMD_SUBSCRIBE_OVERHEADWIRE_VARIABLE:
1240
case libsumo::CMD_SUBSCRIBE_PARKINGAREA_VARIABLE:
1241
case libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE:
1242
case libsumo::CMD_SUBSCRIBE_POI_VARIABLE:
1243
case libsumo::CMD_SUBSCRIBE_POLYGON_VARIABLE:
1244
case libsumo::CMD_SUBSCRIBE_REROUTER_VARIABLE:
1245
case libsumo::CMD_SUBSCRIBE_ROUTE_VARIABLE:
1246
case libsumo::CMD_SUBSCRIBE_ROUTEPROBE_VARIABLE:
1247
case libsumo::CMD_SUBSCRIBE_SIM_VARIABLE:
1248
case libsumo::CMD_SUBSCRIBE_TL_VARIABLE:
1249
case libsumo::CMD_SUBSCRIBE_VARIABLESPEEDSIGN_VARIABLE:
1250
case libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE:
1251
case libsumo::CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE:
1252
success = addObjectVariableSubscription(commandId, false);
1253
break;
1254
case libsumo::CMD_SUBSCRIBE_BUSSTOP_CONTEXT:
1255
case libsumo::CMD_SUBSCRIBE_CALIBRATOR_CONTEXT:
1256
case libsumo::CMD_SUBSCRIBE_CHARGINGSTATION_CONTEXT:
1257
case libsumo::CMD_SUBSCRIBE_EDGE_CONTEXT:
1258
case libsumo::CMD_SUBSCRIBE_GUI_CONTEXT:
1259
case libsumo::CMD_SUBSCRIBE_INDUCTIONLOOP_CONTEXT:
1260
case libsumo::CMD_SUBSCRIBE_JUNCTION_CONTEXT:
1261
case libsumo::CMD_SUBSCRIBE_LANE_CONTEXT:
1262
case libsumo::CMD_SUBSCRIBE_LANEAREA_CONTEXT:
1263
case libsumo::CMD_SUBSCRIBE_MEANDATA_CONTEXT:
1264
case libsumo::CMD_SUBSCRIBE_MULTIENTRYEXIT_CONTEXT:
1265
case libsumo::CMD_SUBSCRIBE_OVERHEADWIRE_CONTEXT:
1266
case libsumo::CMD_SUBSCRIBE_PARKINGAREA_CONTEXT:
1267
case libsumo::CMD_SUBSCRIBE_PERSON_CONTEXT:
1268
case libsumo::CMD_SUBSCRIBE_POI_CONTEXT:
1269
case libsumo::CMD_SUBSCRIBE_POLYGON_CONTEXT:
1270
case libsumo::CMD_SUBSCRIBE_REROUTER_CONTEXT:
1271
case libsumo::CMD_SUBSCRIBE_ROUTE_CONTEXT:
1272
case libsumo::CMD_SUBSCRIBE_ROUTEPROBE_CONTEXT:
1273
case libsumo::CMD_SUBSCRIBE_SIM_CONTEXT:
1274
case libsumo::CMD_SUBSCRIBE_TL_CONTEXT:
1275
case libsumo::CMD_SUBSCRIBE_VARIABLESPEEDSIGN_CONTEXT:
1276
case libsumo::CMD_SUBSCRIBE_VEHICLE_CONTEXT:
1277
case libsumo::CMD_SUBSCRIBE_VEHICLETYPE_CONTEXT:
1278
success = addObjectVariableSubscription(commandId, true);
1279
break;
1280
case libsumo::CMD_ADD_SUBSCRIPTION_FILTER:
1281
success = addSubscriptionFilter();
1282
break;
1283
case libsumo::CMD_SET_GUI_VARIABLE:
1284
writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo");
1285
break;
1286
default:
1287
writeStatusCmd(commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo");
1288
}
1289
}
1290
if (!success) {
1291
while (myInputStorage.valid_pos() && (int)myInputStorage.position() < commandStart + commandLength) {
1292
myInputStorage.readChar();
1293
}
1294
}
1295
if ((int)myInputStorage.position() != commandStart + commandLength) {
1296
std::ostringstream msg;
1297
msg << "Wrong position in requestMessage after dispatching command " << commandId << ".";
1298
msg << " Expected command length was " << commandLength;
1299
msg << " but " << myInputStorage.position() - commandStart << " Bytes were read.";
1300
writeStatusCmd(commandId, libsumo::RTYPE_ERR, msg.str());
1301
myDoCloseConnection = true;
1302
}
1303
return commandId;
1304
}
1305
1306
1307
// ---------- Server-internal command handling
1308
bool
1309
TraCIServer::commandGetVersion() {
1310
// Prepare response
1311
tcpip::Storage answerTmp;
1312
answerTmp.writeInt(libsumo::TRACI_VERSION);
1313
answerTmp.writeString("SUMO " VERSION_STRING);
1314
// When we get here, the response is stored in answerTmp -> put into myOutputStorage
1315
writeStatusCmd(libsumo::CMD_GETVERSION, libsumo::RTYPE_OK, "");
1316
// command length
1317
myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size()));
1318
// command type
1319
myOutputStorage.writeUnsignedByte(libsumo::CMD_GETVERSION);
1320
// and the parameter dependant part
1321
myOutputStorage.writeStorage(answerTmp);
1322
return true;
1323
}
1324
1325
1326
void
1327
TraCIServer::postProcessSimulationStep() {
1328
SUMOTime t = MSNet::getInstance()->getCurrentTimeStep();
1329
#ifdef DEBUG_MULTI_CLIENTS
1330
std::cout << " postProcessSimulationStep() at time=" << t << std::endl;
1331
#endif
1332
writeStatusCmd(libsumo::CMD_SIMSTEP, libsumo::RTYPE_OK, "");
1333
int noActive = 0;
1334
for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1335
const libsumo::Subscription& s = *i;
1336
bool isArrivedVehicle = (s.commandId == libsumo::CMD_SUBSCRIBE_VEHICLE_VARIABLE || s.commandId == libsumo::CMD_SUBSCRIBE_VEHICLE_CONTEXT)
1337
&& (find(myVehicleStateChanges[MSNet::VehicleState::ARRIVED].begin(), myVehicleStateChanges[MSNet::VehicleState::ARRIVED].end(), s.id) != myVehicleStateChanges[MSNet::VehicleState::ARRIVED].end());
1338
1339
bool isArrivedPerson = (s.commandId == libsumo::CMD_SUBSCRIBE_PERSON_VARIABLE || s.commandId == libsumo::CMD_SUBSCRIBE_PERSON_CONTEXT) && MSNet::getInstance()->getPersonControl().get(s.id) == nullptr;
1340
if ((s.endTime < t) || isArrivedVehicle || isArrivedPerson) {
1341
i = mySubscriptions.erase(i);
1342
continue;
1343
}
1344
++i;
1345
if (s.beginTime > t) {
1346
continue;
1347
}
1348
++noActive;
1349
}
1350
mySubscriptionCache.reset();
1351
#ifdef DEBUG_SUBSCRIPTIONS
1352
std::cout << " Initial size of mySubscriptionCache is " << mySubscriptionCache.size()
1353
<< "\n Nr. of active subscriptions = " << noActive << std::endl;
1354
#endif
1355
mySubscriptionCache.writeInt(noActive);
1356
#ifdef DEBUG_SUBSCRIPTIONS
1357
std::cout << " Size after writing an int is " << mySubscriptionCache.size() << std::endl;
1358
#endif
1359
for (std::vector<libsumo::Subscription>::iterator i = mySubscriptions.begin(); i != mySubscriptions.end();) {
1360
const libsumo::Subscription& s = *i;
1361
if (s.beginTime > t) {
1362
++i;
1363
continue;
1364
}
1365
tcpip::Storage into;
1366
std::string errors;
1367
bool ok = processSingleSubscription(s, into, errors);
1368
#ifdef DEBUG_SUBSCRIPTIONS
1369
std::cout << " Size of into-store for subscription " << s.id
1370
<< ": " << into.size() << std::endl;
1371
#endif
1372
mySubscriptionCache.writeStorage(into);
1373
if (ok) {
1374
++i;
1375
} else {
1376
i = mySubscriptions.erase(i);
1377
}
1378
}
1379
myOutputStorage.writeStorage(mySubscriptionCache);
1380
#ifdef DEBUG_SUBSCRIPTIONS
1381
std::cout << " Size after writing subscriptions is " << mySubscriptionCache.size() << std::endl;
1382
#endif
1383
}
1384
1385
1386
void
1387
TraCIServer::sendSingleSimStepResponse() {
1388
#ifdef DEBUG_MULTI_CLIENTS
1389
std::cout << " Sending cached simstep response to current client " << myCurrentSocket->second->socket
1390
<< " (-> intermediate TraCI step)."
1391
<< "\n Size of mySubscriptionCache is " << mySubscriptionCache.size()
1392
<< std::endl;
1393
#endif
1394
writeStatusCmd(libsumo::CMD_SIMSTEP, libsumo::RTYPE_OK, "");
1395
1396
// NOTE: the commented code would send an empty response
1397
// myOutputStorage.writeInt(0);
1398
// myCurrentSocket->second->socket->sendExact(myOutputStorage);
1399
// myOutputStorage.reset();
1400
myOutputStorage.writeStorage(mySubscriptionCache);
1401
// send results to active client
1402
myCurrentSocket->second->socket->sendExact(myOutputStorage);
1403
myOutputStorage.reset();
1404
}
1405
1406
1407
void
1408
TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) {
1409
writeStatusCmd(commandId, status, description, myOutputStorage);
1410
}
1411
1412
1413
void
1414
TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) {
1415
if (status == libsumo::RTYPE_ERR) {
1416
WRITE_ERROR("Answered with error to command " + toHex(commandId, 2) + ": " + description);
1417
} else if (status == libsumo::RTYPE_NOTIMPLEMENTED) {
1418
WRITE_ERROR("Requested command not implemented (" + toHex(commandId, 2) + "): " + description);
1419
}
1420
outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length
1421
outputStorage.writeUnsignedByte(commandId); // command type
1422
outputStorage.writeUnsignedByte(status); // status
1423
outputStorage.writeString(description); // description
1424
}
1425
1426
1427
bool
1428
TraCIServer::writeErrorStatusCmd(int commandId, const std::string& description, tcpip::Storage& outputStorage) {
1429
writeStatusCmd(commandId, libsumo::RTYPE_ERR, description, outputStorage);
1430
return false;
1431
}
1432
1433
1434
void
1435
TraCIServer::initialiseSubscription(libsumo::Subscription& s) {
1436
tcpip::Storage writeInto;
1437
std::string errors;
1438
libsumo::Subscription* modifiedSubscription = nullptr;
1439
try {
1440
if (processSingleSubscription(s, writeInto, errors)) {
1441
if (s.endTime < MSNet::getInstance()->getCurrentTimeStep()) {
1442
writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Subscription has ended.");
1443
} else {
1444
if (libsumo::Helper::needNewSubscription(s, mySubscriptions, modifiedSubscription)) {
1445
// Add new subscription to subscription cache (note: seems a bit inefficient)
1446
if (s.beginTime < MSNet::getInstance()->getCurrentTimeStep()) {
1447
// copy new subscription into cache
1448
int noActive = 1 + (mySubscriptionCache.size() > 0 ? mySubscriptionCache.readInt() : 0);
1449
tcpip::Storage tmp;
1450
tmp.writeInt(noActive);
1451
while (mySubscriptionCache.valid_pos()) {
1452
tmp.writeByte(mySubscriptionCache.readByte());
1453
}
1454
tmp.writeStorage(writeInto);
1455
mySubscriptionCache.reset();
1456
mySubscriptionCache.writeStorage(tmp);
1457
}
1458
}
1459
writeStatusCmd(s.commandId, libsumo::RTYPE_OK, "");
1460
}
1461
if (modifiedSubscription != nullptr && (
1462
modifiedSubscription->isVehicleToVehicleContextSubscription()
1463
|| modifiedSubscription->isVehicleToPersonContextSubscription())) {
1464
// Set last modified vehicle context subscription active for filter modifications
1465
myLastContextSubscription = modifiedSubscription;
1466
} else {
1467
// adding other subscriptions deactivates the activation for filter addition
1468
myLastContextSubscription = nullptr;
1469
}
1470
} else {
1471
writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, "Could not add subscription. " + errors);
1472
}
1473
} catch (libsumo::TraCIException& e) {
1474
writeStatusCmd(s.commandId, libsumo::RTYPE_ERR, e.what());
1475
}
1476
myOutputStorage.writeStorage(writeInto);
1477
}
1478
1479
1480
void
1481
TraCIServer::removeSubscription(int commandId, const std::string& id, int domain) {
1482
bool found = false;
1483
std::vector<libsumo::Subscription>::iterator j;
1484
for (j = mySubscriptions.begin(); j != mySubscriptions.end();) {
1485
if (j->id == id && j->commandId == commandId && j->contextDomain == domain) {
1486
j = mySubscriptions.erase(j);
1487
if (j != mySubscriptions.end() && myLastContextSubscription == &(*j)) {
1488
// Remove also reference for filter additions
1489
myLastContextSubscription = nullptr;
1490
}
1491
found = true;
1492
continue;
1493
}
1494
++j;
1495
}
1496
// try unsubscribe
1497
if (found) {
1498
writeStatusCmd(commandId, libsumo::RTYPE_OK, "");
1499
} else {
1500
writeStatusCmd(commandId, libsumo::RTYPE_ERR, "The subscription to remove was not found.");
1501
}
1502
}
1503
1504
1505
bool
1506
TraCIServer::processSingleSubscription(const libsumo::Subscription& s, tcpip::Storage& writeInto,
1507
std::string& errors) {
1508
bool ok = true;
1509
tcpip::Storage outputStorage;
1510
const int getCommandId = s.contextDomain > 0 ? s.contextDomain : s.commandId - 0x30;
1511
std::set<std::string> objIDs;
1512
if (s.contextDomain > 0) {
1513
if ((s.activeFilters & libsumo::SUBS_FILTER_NO_RTREE) == 0) {
1514
PositionVector shape;
1515
libsumo::Helper::findObjectShape(s.commandId, s.id, shape);
1516
libsumo::Helper::collectObjectIDsInRange(s.contextDomain, shape, s.range, objIDs);
1517
}
1518
libsumo::Helper::applySubscriptionFilters(s, objIDs);
1519
} else {
1520
objIDs.insert(s.id);
1521
}
1522
const int numVars = s.contextDomain > 0 && s.variables.size() == 1 && s.variables[0] == libsumo::TRACI_ID_LIST ? 0 : (int)s.variables.size();
1523
int skipped = 0;
1524
for (std::set<std::string>::iterator j = objIDs.begin(); j != objIDs.end(); ++j) {
1525
if (s.contextDomain > 0) {
1526
//if (centralObject(s, *j)) {
1527
// skipped++;
1528
// continue;
1529
//}
1530
outputStorage.writeString(*j);
1531
}
1532
if (numVars > 0) {
1533
std::vector<std::shared_ptr<tcpip::Storage> >::const_iterator k = s.parameters.begin();
1534
for (std::vector<int>::const_iterator i = s.variables.begin(); i != s.variables.end(); ++i, ++k) {
1535
tcpip::Storage message;
1536
message.writeUnsignedByte(*i);
1537
message.writeString(*j);
1538
// TODO check why writeStorage fails here (probably some kind of invalid iterator)
1539
for (const auto& v :** k) {
1540
message.writeChar(v);
1541
}
1542
tcpip::Storage tmpOutput;
1543
try {
1544
if (myExecutors.find(getCommandId) != myExecutors.end()) {
1545
ok &= myExecutors[getCommandId](*this, message, tmpOutput);
1546
} else if (!processGet(getCommandId, message, tmpOutput)) {
1547
if (getCommandId == libsumo::CMD_GET_GUI_VARIABLE) {
1548
writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "GUI is not running, command not implemented in command line sumo", tmpOutput);
1549
}
1550
ok = false;
1551
}
1552
} catch (const std::invalid_argument&) {
1553
writeStatusCmd(s.commandId, libsumo::RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput);
1554
ok = false;
1555
}
1556
// copy response part
1557
if (ok) {
1558
int length = tmpOutput.readUnsignedByte();
1559
while (--length > 0) {
1560
tmpOutput.readUnsignedByte();
1561
}
1562
int lengthLength = 1;
1563
length = tmpOutput.readUnsignedByte();
1564
if (length == 0) {
1565
lengthLength = 5;
1566
length = tmpOutput.readInt();
1567
}
1568
//read responseType
1569
tmpOutput.readUnsignedByte();
1570
int variable = tmpOutput.readUnsignedByte();
1571
std::string id = tmpOutput.readString();
1572
outputStorage.writeUnsignedByte(variable);
1573
outputStorage.writeUnsignedByte(libsumo::RTYPE_OK);
1574
length -= (lengthLength + 1 + 4 + (int)id.length());
1575
while (--length > 0) {
1576
outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte());
1577
}
1578
} else {
1579
//read length
1580
tmpOutput.readUnsignedByte();
1581
//read cmd
1582
tmpOutput.readUnsignedByte();
1583
//read status
1584
tmpOutput.readUnsignedByte();
1585
std::string msg = tmpOutput.readString();
1586
outputStorage.writeUnsignedByte(*i);
1587
outputStorage.writeUnsignedByte(libsumo::RTYPE_ERR);
1588
outputStorage.writeUnsignedByte(libsumo::TYPE_STRING);
1589
outputStorage.writeString(msg);
1590
errors = errors + msg;
1591
}
1592
}
1593
}
1594
}
1595
int length = (1 + 4) + 1 + (4 + (int)s.id.length()) + 1 + (int)outputStorage.size();
1596
if (s.contextDomain > 0) {
1597
length += 1 + 4; // context domain and number of objects
1598
}
1599
// we always write extended command length here for backward compatibility
1600
writeInto.writeUnsignedByte(0); // command length -> extended
1601
writeInto.writeInt(length);
1602
writeInto.writeUnsignedByte(s.commandId + 0x10);
1603
writeInto.writeString(s.id);
1604
if (s.contextDomain > 0) {
1605
writeInto.writeUnsignedByte(s.contextDomain);
1606
}
1607
writeInto.writeUnsignedByte(numVars);
1608
if (s.contextDomain > 0) {
1609
writeInto.writeInt((int)objIDs.size() - skipped);
1610
}
1611
if (s.contextDomain == 0 || objIDs.size() != 0) {
1612
writeInto.writeStorage(outputStorage);
1613
}
1614
return ok;
1615
}
1616
1617
1618
bool
1619
TraCIServer::addObjectVariableSubscription(const int commandId, const bool hasContext) {
1620
const double beginTime = myInputStorage.readDouble();
1621
const double endTime = myInputStorage.readDouble();
1622
const SUMOTime begin = beginTime == libsumo::INVALID_DOUBLE_VALUE ? 0 : TIME2STEPS(beginTime);
1623
const SUMOTime end = endTime == libsumo::INVALID_DOUBLE_VALUE || endTime > STEPS2TIME(SUMOTime_MAX) ? SUMOTime_MAX : TIME2STEPS(endTime);
1624
const std::string id = myInputStorage.readString();
1625
const int domain = hasContext ? myInputStorage.readUnsignedByte() : 0;
1626
double range = hasContext ? myInputStorage.readDouble() : 0.;
1627
if (commandId == libsumo::CMD_SUBSCRIBE_SIM_CONTEXT) {
1628
range = std::numeric_limits<double>::max();
1629
}
1630
const int num = myInputStorage.readUnsignedByte();
1631
std::vector<int> variables;
1632
std::vector<std::shared_ptr<tcpip::Storage> > parameters;
1633
for (int i = 0; i < num; ++i) {
1634
const int varID = myInputStorage.readUnsignedByte();
1635
variables.push_back(varID);
1636
parameters.push_back(std::make_shared<tcpip::Storage>());
1637
if ((myParameterized.count(std::make_pair(0, varID)) > 0) || (myParameterized.count(std::make_pair(commandId, varID)) > 0)) {
1638
if (!myInputStorage.valid_pos()) {
1639
writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Missing parameter for subscription " + toHex(commandId, 2));
1640
return false;
1641
}
1642
int count = 1;
1643
while (count-- > 0) {
1644
const int parType = myInputStorage.readUnsignedByte();
1645
parameters.back()->writeUnsignedByte(parType);
1646
if (parType == libsumo::TYPE_DOUBLE) {
1647
parameters.back()->writeDouble(myInputStorage.readDouble());
1648
} else if (parType == libsumo::TYPE_INTEGER) {
1649
parameters.back()->writeInt(myInputStorage.readInt());
1650
} else if (parType == libsumo::TYPE_STRING) {
1651
parameters.back()->writeString(myInputStorage.readString());
1652
} else if (parType == libsumo::TYPE_BYTE) {
1653
parameters.back()->writeByte(myInputStorage.readByte());
1654
} else if (parType == libsumo::TYPE_UBYTE) {
1655
parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1656
} else if (parType == libsumo::POSITION_2D) {
1657
parameters.back()->writeDouble(myInputStorage.readDouble());
1658
parameters.back()->writeDouble(myInputStorage.readDouble());
1659
if (varID == libsumo::DISTANCE_REQUEST) {
1660
parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1661
break;
1662
}
1663
} else if (parType == libsumo::POSITION_3D) {
1664
parameters.back()->writeDouble(myInputStorage.readDouble());
1665
parameters.back()->writeDouble(myInputStorage.readDouble());
1666
parameters.back()->writeDouble(myInputStorage.readDouble());
1667
if (varID == libsumo::DISTANCE_REQUEST) {
1668
parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1669
break;
1670
}
1671
} else if (parType == libsumo::POSITION_ROADMAP) {
1672
parameters.back()->writeString(myInputStorage.readString());
1673
parameters.back()->writeDouble(myInputStorage.readDouble());
1674
parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1675
if (varID == libsumo::DISTANCE_REQUEST) {
1676
parameters.back()->writeUnsignedByte(myInputStorage.readUnsignedByte());
1677
break;
1678
}
1679
} else if (parType == libsumo::TYPE_COMPOUND) {
1680
count = myInputStorage.readInt();
1681
parameters.back()->writeInt(count);
1682
} else {
1683
writeStatusCmd(commandId, libsumo::RTYPE_ERR, "Invalid parameter for subscription " + toHex(commandId, 2));
1684
return false;
1685
}
1686
}
1687
}
1688
}
1689
// check subscribe/unsubscribe
1690
if (variables.empty()) {
1691
removeSubscription(commandId, id, domain);
1692
return true;
1693
}
1694
// process subscription
1695
libsumo::Subscription s(commandId, id, variables, parameters, begin, end, domain, range);
1696
initialiseSubscription(s);
1697
return true;
1698
}
1699
1700
1701
1702
bool
1703
TraCIServer::addSubscriptionFilter() {
1704
bool success = true;
1705
// Read filter type
1706
int filterType = myInputStorage.readUnsignedByte();
1707
1708
if (myLastContextSubscription == nullptr) {
1709
writeStatusCmd(libsumo::CMD_ADD_SUBSCRIPTION_FILTER, libsumo::RTYPE_ERR,
1710
"No previous vehicle context subscription exists to apply filter type " + toHex(filterType, 2));
1711
return false;
1712
}
1713
1714
// dispatch according to filter type
1715
switch (filterType) {
1716
case libsumo::FILTER_TYPE_NONE:
1717
// Remove all filters
1718
removeFilters();
1719
break;
1720
case libsumo::FILTER_TYPE_LANES: {
1721
// Read relative lanes to consider for context filter
1722
int nrLanes = (int)myInputStorage.readByte();
1723
std::vector<int> lanes;
1724
for (int i = 0; i < nrLanes; ++i) {
1725
lanes.push_back((int) myInputStorage.readByte());
1726
}
1727
addSubscriptionFilterLanes(lanes);
1728
}
1729
break;
1730
case libsumo::FILTER_TYPE_NOOPPOSITE:
1731
// Add no-opposite filter
1732
addSubscriptionFilterNoOpposite();
1733
break;
1734
case libsumo::FILTER_TYPE_DOWNSTREAM_DIST: {
1735
myInputStorage.readByte(); // read type double
1736
double dist = myInputStorage.readDouble();
1737
addSubscriptionFilterDownstreamDistance(dist);
1738
}
1739
break;
1740
case libsumo::FILTER_TYPE_UPSTREAM_DIST: {
1741
myInputStorage.readByte(); // read type double
1742
double dist = myInputStorage.readDouble();
1743
addSubscriptionFilterUpstreamDistance(dist);
1744
}
1745
break;
1746
case libsumo::FILTER_TYPE_LEAD_FOLLOW: {
1747
// Read relative lanes to consider for context filter
1748
addSubscriptionFilterLeadFollow();
1749
}
1750
break;
1751
case libsumo::FILTER_TYPE_TURN: {
1752
myInputStorage.readByte(); // read type double
1753
double dist = myInputStorage.readDouble();
1754
addSubscriptionFilterTurn(dist);
1755
}
1756
break;
1757
case libsumo::FILTER_TYPE_VCLASS: {
1758
myInputStorage.readByte(); // read type stringlist
1759
SVCPermissions vClasses = parseVehicleClasses(myInputStorage.readStringList());
1760
addSubscriptionFilterVClass(vClasses);
1761
}
1762
break;
1763
case libsumo::FILTER_TYPE_VTYPE: {
1764
myInputStorage.readByte(); // read type stringlist
1765
std::vector<std::string> vTypesVector = myInputStorage.readStringList();
1766
std::set<std::string> vTypesSet;
1767
vTypesSet.insert(vTypesVector.begin(), vTypesVector.end());
1768
addSubscriptionFilterVType(vTypesSet);
1769
}
1770
break;
1771
case libsumo::FILTER_TYPE_FIELD_OF_VISION: {
1772
myInputStorage.readByte(); // read type double
1773
double angle = myInputStorage.readDouble();
1774
addSubscriptionFilterFieldOfVision(angle);
1775
}
1776
break;
1777
case libsumo::FILTER_TYPE_LATERAL_DIST: {
1778
myInputStorage.readByte(); // read type double
1779
double dist = myInputStorage.readDouble();
1780
addSubscriptionFilterLateralDistance(dist);
1781
}
1782
break;
1783
default:
1784
writeStatusCmd(libsumo::CMD_ADD_SUBSCRIPTION_FILTER, libsumo::RTYPE_NOTIMPLEMENTED,
1785
"'" + toString(filterType) + "' is no valid filter type code.");
1786
success = false;
1787
}
1788
1789
if (success) {
1790
// acknowledge filter addition
1791
writeStatusCmd(libsumo::CMD_ADD_SUBSCRIPTION_FILTER, libsumo::RTYPE_OK, "");
1792
}
1793
1794
return success;
1795
}
1796
1797
1798
void
1799
TraCIServer::removeFilters() {
1800
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1801
std::cout << "Removing filters" << std::endl;
1802
#endif
1803
myLastContextSubscription->activeFilters = libsumo::SUBS_FILTER_NONE;
1804
}
1805
1806
void
1807
TraCIServer::addSubscriptionFilterLanes(std::vector<int> lanes) {
1808
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1809
std::cout << "Adding lane filter (lanes=" << toString(lanes) << ")" << std::endl;
1810
#endif
1811
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_LANES;
1812
myLastContextSubscription->filterLanes = lanes;
1813
}
1814
1815
void
1816
TraCIServer::addSubscriptionFilterNoOpposite() {
1817
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1818
std::cout << "Adding no opposite filter" << std::endl;
1819
#endif
1820
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_NOOPPOSITE;
1821
}
1822
1823
void
1824
TraCIServer::addSubscriptionFilterDownstreamDistance(double dist) {
1825
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1826
std::cout << "Adding downstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1827
#endif
1828
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_DOWNSTREAM_DIST;
1829
myLastContextSubscription->filterDownstreamDist = dist;
1830
}
1831
1832
void
1833
TraCIServer::addSubscriptionFilterUpstreamDistance(double dist) {
1834
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1835
std::cout << "Adding upstream dist filter (dist=" << toString(dist) << ")" << std::endl;
1836
#endif
1837
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_UPSTREAM_DIST;
1838
myLastContextSubscription->filterUpstreamDist = dist;
1839
}
1840
1841
void
1842
TraCIServer::addSubscriptionFilterLeadFollow() {
1843
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1844
std::cout << "Adding Lead/Follow-maneuver filter" << std::endl;
1845
#endif
1846
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_LEAD_FOLLOW;
1847
}
1848
1849
void
1850
TraCIServer::addSubscriptionFilterTurn(double dist) {
1851
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1852
std::cout << "Adding turn-maneuver filter" << std::endl;
1853
#endif
1854
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_TURN;
1855
myLastContextSubscription->filterFoeDistToJunction = dist;
1856
}
1857
1858
void
1859
TraCIServer::addSubscriptionFilterVClass(SVCPermissions vClasses) {
1860
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1861
std::cout << "Adding vClass filter (vClasses=" << toString(vClasses) << ")" << std::endl;
1862
#endif
1863
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_VCLASS;
1864
myLastContextSubscription->filterVClasses = vClasses;
1865
}
1866
1867
void
1868
TraCIServer::addSubscriptionFilterVType(std::set<std::string> vTypes) {
1869
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1870
std::cout << "Adding vType filter (vTypes=" << toString(vTypes) << ")" << std::endl;
1871
#endif
1872
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_VTYPE;
1873
myLastContextSubscription->filterVTypes = vTypes;
1874
}
1875
1876
void
1877
TraCIServer::addSubscriptionFilterFieldOfVision(double openingAngle) {
1878
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1879
std::cout << "Adding FieldOfVision filter (openingAngle=" << toString(openingAngle) << ")" << std::endl;
1880
#endif
1881
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_FIELD_OF_VISION;
1882
myLastContextSubscription->filterFieldOfVisionOpeningAngle = openingAngle;
1883
}
1884
1885
void
1886
TraCIServer::addSubscriptionFilterLateralDistance(double dist) {
1887
#ifdef DEBUG_SUBSCRIPTION_FILTERS
1888
std::cout << "Adding lateral dist filter (dist=" << toString(dist) << ")" << std::endl;
1889
#endif
1890
myLastContextSubscription->activeFilters = myLastContextSubscription->activeFilters | libsumo::SUBS_FILTER_LATERAL_DIST;
1891
myLastContextSubscription->filterLateralDist = dist;
1892
}
1893
1894
void
1895
TraCIServer::writeResponseWithLength(tcpip::Storage& outputStorage, tcpip::Storage& tempMsg) {
1896
if (tempMsg.size() < 254) {
1897
outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short
1898
} else {
1899
outputStorage.writeUnsignedByte(0); // command length -> extended
1900
outputStorage.writeInt(1 + 4 + (int)tempMsg.size());
1901
}
1902
outputStorage.writeStorage(tempMsg);
1903
}
1904
1905
1906
void
1907
TraCIServer::stateLoaded(SUMOTime targetTime) {
1908
myTargetTime = targetTime;
1909
for (auto& s : mySockets) {
1910
s.second->targetTime = targetTime;
1911
s.second->executeMove = false;
1912
for (auto& stateChange : s.second->vehicleStateChanges) {
1913
stateChange.second.clear();
1914
}
1915
for (auto& stateChange : s.second->transportableStateChanges) {
1916
stateChange.second.clear();
1917
}
1918
}
1919
mySubscriptions.clear();
1920
mySubscriptionCache.reset();
1921
}
1922
1923
1924
bool
1925
TraCIServer::centralObject(const libsumo::Subscription& s, const std::string& objID) {
1926
return (s.id == objID && s.commandId + 32 == s.contextDomain);
1927
}
1928
1929
1930
/****************************************************************************/
1931
1932