|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This program is free software; you can redistribute it and/or modify 00016 // it under the terms of the GNU General Public License as published by 00017 // the Free Software Foundation; either version 2 of the License, or 00018 // (at your option) any later version. 00019 // 00020 /****************************************************************************/ 00021 00022 // =========================================================================== 00023 // included modules 00024 // =========================================================================== 00025 #ifdef _MSC_VER 00026 #include <windows_config.h> 00027 #else 00028 #include <config.h> 00029 #endif 00030 00031 #ifdef HAVE_VERSION_H 00032 #include <version.h> 00033 #endif 00034 00035 #ifndef NO_TRACI 00036 00037 #ifdef HAVE_PYTHON 00038 #include <Python.h> 00039 #endif 00040 00041 #include <string> 00042 #include <map> 00043 #include <iostream> 00044 #include <foreign/tcpip/socket.h> 00045 #include <foreign/tcpip/storage.h> 00046 #include <utils/common/SUMOTime.h> 00047 #include <utils/common/DijkstraRouterTT.h> 00048 #include <utils/common/NamedObjectCont.h> 00049 #include <utils/common/RandHelper.h> 00050 #include <utils/common/MsgHandler.h> 00051 #include <utils/common/HelpersHBEFA.h> 00052 #include <utils/common/HelpersHarmonoise.h> 00053 #include <utils/common/SUMOVehicleParameter.h> 00054 #include <utils/shapes/PointOfInterest.h> 00055 #include <utils/shapes/ShapeContainer.h> 00056 #include <utils/shapes/Polygon.h> 00057 #include <utils/xml/XMLSubSys.h> 00058 #include <microsim/MSNet.h> 00059 #include <microsim/MSVehicleControl.h> 00060 #include <microsim/MSVehicle.h> 00061 #include <microsim/MSEdge.h> 00062 #include <microsim/MSJunctionControl.h> 00063 #include <microsim/MSJunction.h> 00064 #include <microsim/MSEdgeControl.h> 00065 #include <microsim/MSLane.h> 00066 #include <microsim/MSGlobals.h> 00067 #include <microsim/traffic_lights/MSTLLogicControl.h> 00068 #include "TraCIConstants.h" 00069 #include "TraCIServer.h" 00070 #include "TraCIServerAPI_InductionLoop.h" 00071 #include "TraCIServerAPI_Junction.h" 00072 #include "TraCIServerAPI_Lane.h" 00073 #include "TraCIServerAPI_MeMeDetector.h" 00074 #include "TraCIServerAPI_TLS.h" 00075 #include "TraCIServerAPI_Vehicle.h" 00076 #include "TraCIServerAPI_VehicleType.h" 00077 #include "TraCIServerAPI_Route.h" 00078 #include "TraCIServerAPI_POI.h" 00079 #include "TraCIServerAPI_Polygon.h" 00080 #include "TraCIServerAPI_Edge.h" 00081 #include "TraCIServerAPI_Simulation.h" 00082 00083 #ifdef CHECK_MEMORY_LEAKS 00084 #include <foreign/nvwa/debug_new.h> 00085 #endif // CHECK_MEMORY_LEAKS 00086 00087 00088 // =========================================================================== 00089 // used namespaces 00090 // =========================================================================== 00091 namespace traci { 00092 00093 // =========================================================================== 00094 // static member definitions 00095 // =========================================================================== 00096 TraCIServer* TraCIServer::myInstance = 0; 00097 bool TraCIServer::myDoCloseConnection = false; 00098 00099 00100 // =========================================================================== 00101 // method definitions 00102 // =========================================================================== 00103 00104 void 00105 TraCIServer::openSocket(const std::map<int, CmdExecutor> &execs) { 00106 if (myInstance == 0) { 00107 if (!myDoCloseConnection && OptionsCont::getOptions().getInt("remote-port") != 0) { 00108 myInstance = new traci::TraCIServer(OptionsCont::getOptions().getInt("remote-port")); 00109 for (std::map<int, CmdExecutor>::const_iterator i=execs.begin(); i!=execs.end(); ++i) { 00110 myInstance->myExecutors[i->first] = i->second; 00111 } 00112 } 00113 } 00114 } 00115 00116 /*****************************************************************************/ 00117 00118 TraCIServer::TraCIServer(int port) 00119 : mySocket(0), myTargetTime(0), myDoingSimStep(false), myHaveWarnedDeprecation(false), myAmEmbedded(port == 0) { 00120 myVehicleStateChanges[MSNet::VEHICLE_STATE_BUILT] = std::vector<std::string>(); 00121 myVehicleStateChanges[MSNet::VEHICLE_STATE_DEPARTED] = std::vector<std::string>(); 00122 myVehicleStateChanges[MSNet::VEHICLE_STATE_STARTING_TELEPORT] = std::vector<std::string>(); 00123 myVehicleStateChanges[MSNet::VEHICLE_STATE_ENDING_TELEPORT] = std::vector<std::string>(); 00124 myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED] = std::vector<std::string>(); 00125 myVehicleStateChanges[MSNet::VEHICLE_STATE_NEWROUTE] = std::vector<std::string>(); 00126 MSNet::getInstance()->addVehicleStateListener(this); 00127 00128 myExecutors[CMD_GET_INDUCTIONLOOP_VARIABLE] = &TraCIServerAPI_InductionLoop::processGet; 00129 myExecutors[CMD_GET_MULTI_ENTRY_EXIT_DETECTOR_VARIABLE] = &TraCIServerAPI_MeMeDetector::processGet; 00130 myExecutors[CMD_GET_TL_VARIABLE] = &TraCIServerAPI_TLS::processGet; 00131 myExecutors[CMD_SET_TL_VARIABLE] = &TraCIServerAPI_TLS::processSet; 00132 myExecutors[CMD_GET_LANE_VARIABLE] = &TraCIServerAPI_Lane::processGet; 00133 myExecutors[CMD_SET_LANE_VARIABLE] = &TraCIServerAPI_Lane::processSet; 00134 myExecutors[CMD_GET_VEHICLE_VARIABLE] = &TraCIServerAPI_Vehicle::processGet; 00135 myExecutors[CMD_SET_VEHICLE_VARIABLE] = &TraCIServerAPI_Vehicle::processSet; 00136 myExecutors[CMD_GET_VEHICLETYPE_VARIABLE] = &TraCIServerAPI_VehicleType::processGet; 00137 myExecutors[CMD_SET_VEHICLETYPE_VARIABLE] = &TraCIServerAPI_VehicleType::processSet; 00138 myExecutors[CMD_GET_ROUTE_VARIABLE] = &TraCIServerAPI_Route::processGet; 00139 myExecutors[CMD_SET_ROUTE_VARIABLE] = &TraCIServerAPI_Route::processSet; 00140 myExecutors[CMD_GET_POI_VARIABLE] = &TraCIServerAPI_POI::processGet; 00141 myExecutors[CMD_SET_POI_VARIABLE] = &TraCIServerAPI_POI::processSet; 00142 myExecutors[CMD_GET_POLYGON_VARIABLE] = &TraCIServerAPI_Polygon::processGet; 00143 myExecutors[CMD_SET_POLYGON_VARIABLE] = &TraCIServerAPI_Polygon::processSet; 00144 myExecutors[CMD_GET_JUNCTION_VARIABLE] = &TraCIServerAPI_Junction::processGet; 00145 myExecutors[CMD_GET_EDGE_VARIABLE] = &TraCIServerAPI_Edge::processGet; 00146 myExecutors[CMD_SET_EDGE_VARIABLE] = &TraCIServerAPI_Edge::processSet; 00147 myExecutors[CMD_GET_SIM_VARIABLE] = &TraCIServerAPI_Simulation::processGet; 00148 00149 myDoCloseConnection = false; 00150 00151 // display warning if internal lanes are not used 00152 if (!MSGlobals::gUsingInternalLanes) { 00153 WRITE_WARNING("Starting TraCI without using internal lanes!"); 00154 MsgHandler::getWarningInstance()->inform("Vehicles will jump over junctions.", false); 00155 MsgHandler::getWarningInstance()->inform("Use without option --no-internal-links to avoid unexpected behavior", false); 00156 } 00157 00158 if (!myAmEmbedded) { 00159 try { 00160 WRITE_MESSAGE("***Starting server on port " + toString(port) + " ***"); 00161 mySocket = new tcpip::Socket(port); 00162 mySocket->accept(); 00163 // When got here, a client has connected 00164 } catch (tcpip::SocketException& e) { 00165 throw ProcessError(e.what()); 00166 } 00167 } 00168 } 00169 00170 /*****************************************************************************/ 00171 00172 TraCIServer::~TraCIServer() { 00173 MSNet::getInstance()->removeVehicleStateListener(this); 00174 if (mySocket != NULL) { 00175 mySocket->close(); 00176 delete mySocket; 00177 } 00178 } 00179 00180 /*****************************************************************************/ 00181 00182 void 00183 TraCIServer::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to) { 00184 if (myDoCloseConnection || OptionsCont::getOptions().getInt("remote-port") == 0) { 00185 return; 00186 } 00187 myVehicleStateChanges[to].push_back(vehicle->getID()); 00188 } 00189 00190 /*****************************************************************************/ 00191 void 00192 TraCIServer::processCommandsUntilSimStep(SUMOTime step) { 00193 try { 00194 if (myInstance == 0) { 00195 if (!myDoCloseConnection && OptionsCont::getOptions().getInt("remote-port") != 0) { 00196 myInstance = new traci::TraCIServer(OptionsCont::getOptions().getInt("remote-port")); 00197 } else { 00198 return; 00199 } 00200 } 00201 if (myInstance->myAmEmbedded || step < myInstance->myTargetTime) { 00202 return; 00203 } 00204 // Simulation should run until 00205 // 1. end time reached or 00206 // 2. got CMD_CLOSE or 00207 // 3. Client closes socket connection 00208 if (myInstance->myDoingSimStep) { 00209 myInstance->postProcessSimulationStep2(); 00210 myInstance->myDoingSimStep = false; 00211 } 00212 while (!myDoCloseConnection) { 00213 if (!myInstance->myInputStorage.valid_pos()) { 00214 if (myInstance->myOutputStorage.size() > 0) { 00215 // send out all answers as one storage 00216 myInstance->mySocket->sendExact(myInstance->myOutputStorage); 00217 } 00218 myInstance->myInputStorage.reset(); 00219 myInstance->myOutputStorage.reset(); 00220 // Read a message 00221 myInstance->mySocket->receiveExact(myInstance->myInputStorage); 00222 } 00223 while (myInstance->myInputStorage.valid_pos() && !myDoCloseConnection) { 00224 // dispatch each command 00225 int cmd = myInstance->dispatchCommand(); 00226 if (cmd==CMD_SIMSTEP2) { 00227 myInstance->myDoingSimStep = true; 00228 for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i=myInstance->myVehicleStateChanges.begin(); i!=myInstance->myVehicleStateChanges.end(); ++i) { 00229 (*i).second.clear(); 00230 } 00231 return; 00232 } 00233 } 00234 } 00235 if (myDoCloseConnection && myInstance->myOutputStorage.size() > 0) { 00236 // send out all answers as one storage 00237 myInstance->mySocket->sendExact(myInstance->myOutputStorage); 00238 } 00239 for (std::map<MSNet::VehicleState, std::vector<std::string> >::iterator i=myInstance->myVehicleStateChanges.begin(); i!=myInstance->myVehicleStateChanges.end(); ++i) { 00240 (*i).second.clear(); 00241 } 00242 } catch (std::invalid_argument& e) { 00243 throw ProcessError(e.what()); 00244 } catch (TraCIException& e) { 00245 throw ProcessError(e.what()); 00246 } catch (tcpip::SocketException& e) { 00247 throw ProcessError(e.what()); 00248 } 00249 if (myInstance != NULL) { 00250 delete myInstance; 00251 myInstance = 0; 00252 myDoCloseConnection = true; 00253 } 00254 } 00255 00256 /*****************************************************************************/ 00257 00258 bool 00259 TraCIServer::wasClosed() { 00260 return myDoCloseConnection; 00261 } 00262 00263 00264 void 00265 TraCIServer::close() { 00266 if (myInstance!=0) { 00267 delete myInstance; 00268 myInstance = 0; 00269 myDoCloseConnection = true; 00270 } 00271 } 00272 00273 /*****************************************************************************/ 00274 00275 #ifdef HAVE_PYTHON 00276 // =========================================================================== 00277 // python functions (traciemb module) 00278 // =========================================================================== 00279 static PyObject* 00280 traciemb_execute(PyObject* self, PyObject* args) { 00281 const char* msg; 00282 int size; 00283 if (!PyArg_ParseTuple(args, "s#", &msg, &size)) { 00284 return NULL; 00285 } 00286 std::string result = traci::TraCIServer::execute(std::string(msg, size)); 00287 return Py_BuildValue("s#", result.c_str(), result.size()); 00288 } 00289 00290 static PyMethodDef EmbMethods[] = { 00291 { 00292 "execute", traciemb_execute, METH_VARARGS, 00293 "Execute the given TraCI command and return the result." 00294 }, 00295 {NULL, NULL, 0, NULL} 00296 }; 00297 00298 00299 std::string 00300 TraCIServer::execute(std::string cmd) { 00301 try { 00302 if (myInstance == 0) { 00303 if (!myDoCloseConnection) { 00304 myInstance = new traci::TraCIServer(); 00305 } else { 00306 return ""; 00307 } 00308 } 00309 myInstance->myInputStorage.reset(); 00310 myInstance->myOutputStorage.reset(); 00311 for (std::string::iterator i = cmd.begin(); i != cmd.end(); ++i) { 00312 myInstance->myInputStorage.writeChar(*i); 00313 } 00314 myInstance->dispatchCommand(); 00315 return std::string(myInstance->myOutputStorage.begin(), myInstance->myOutputStorage.end()); 00316 } catch (std::invalid_argument& e) { 00317 throw ProcessError(e.what()); 00318 } catch (TraCIException& e) { 00319 throw ProcessError(e.what()); 00320 } catch (tcpip::SocketException& e) { 00321 throw ProcessError(e.what()); 00322 } 00323 } 00324 00325 00326 void 00327 TraCIServer::runEmbedded(std::string pyFile) { 00328 PyObject* pName, *pModule; 00329 Py_Initialize(); 00330 Py_InitModule("traciemb", EmbMethods); 00331 if (pyFile.length() > 3 && !pyFile.compare(pyFile.length() - 3, 3, ".py")) { 00332 FILE* pFile = fopen(pyFile.c_str(), "r"); 00333 PyRun_SimpleFile(pFile, pyFile.c_str()); 00334 fclose(pFile); 00335 } else { 00336 pName = PyString_FromString(pyFile.c_str()); 00337 /* Error checking of pName left out */ 00338 pModule = PyImport_Import(pName); 00339 Py_DECREF(pName); 00340 if (pModule == NULL) { 00341 PyErr_Print(); 00342 throw ProcessError("Failed to load \"" + pyFile + "\"!"); 00343 } 00344 } 00345 Py_Finalize(); 00346 } 00347 #endif 00348 00349 /*****************************************************************************/ 00350 00351 int 00352 TraCIServer::dispatchCommand() { 00353 unsigned int commandStart = myInputStorage.position(); 00354 unsigned int commandLength = myInputStorage.readUnsignedByte(); 00355 if (commandLength==0) { 00356 commandLength = myInputStorage.readInt(); 00357 } 00358 00359 int commandId = myInputStorage.readUnsignedByte(); 00360 bool success = false; 00361 // dispatch commands 00362 if (myExecutors.find(commandId)!=myExecutors.end()) { 00363 success = myExecutors[commandId](*this, myInputStorage, myOutputStorage); 00364 } else { 00365 switch (commandId) { 00366 case CMD_GETVERSION: 00367 success = commandGetVersion(); 00368 break; 00369 case CMD_SIMSTEP2: { 00370 SUMOTime nextT = myInputStorage.readInt(); 00371 success = true; 00372 if (nextT!=0) { 00373 myTargetTime = nextT; 00374 } else { 00375 myTargetTime += DELTA_T; 00376 } 00377 if (myAmEmbedded) { 00378 MSNet::getInstance()->simulationStep(); 00379 postProcessSimulationStep2(); 00380 } 00381 return commandId; 00382 } 00383 case CMD_CLOSE: 00384 success = commandCloseConnection(); 00385 break; 00386 case CMD_POSITIONCONVERSION: { 00387 if (!myHaveWarnedDeprecation) { 00388 WRITE_WARNING("Using old TraCI API, please update your client!"); 00389 myHaveWarnedDeprecation = true; 00390 } 00391 tcpip::Storage tempMsg; 00392 success = TraCIServerAPI_Simulation::commandPositionConversion(*this, myInputStorage, tempMsg, CMD_POSITIONCONVERSION); 00393 if (success) { 00394 writeStatusCmd(CMD_POSITIONCONVERSION, RTYPE_OK, ""); 00395 myOutputStorage.writeStorage(tempMsg); 00396 } 00397 } 00398 break; 00399 case CMD_ADDVEHICLE: 00400 if (!myHaveWarnedDeprecation) { 00401 WRITE_WARNING("Using old TraCI API, please update your client!"); 00402 myHaveWarnedDeprecation = true; 00403 } 00404 success = commandAddVehicle(); 00405 break; 00406 case CMD_DISTANCEREQUEST: { 00407 if (!myHaveWarnedDeprecation) { 00408 WRITE_WARNING("Using old TraCI API, please update your client!"); 00409 myHaveWarnedDeprecation = true; 00410 } 00411 tcpip::Storage tempMsg; 00412 success = TraCIServerAPI_Simulation::commandDistanceRequest(*this, myInputStorage, tempMsg, CMD_DISTANCEREQUEST); 00413 if (success) { 00414 writeStatusCmd(CMD_DISTANCEREQUEST, RTYPE_OK, ""); 00415 myOutputStorage.writeStorage(tempMsg); 00416 } 00417 } 00418 break; 00419 case CMD_SUBSCRIBE_INDUCTIONLOOP_VARIABLE: 00420 case CMD_SUBSCRIBE_MULTI_ENTRY_EXIT_DETECTOR_VARIABLE: 00421 case CMD_SUBSCRIBE_TL_VARIABLE: 00422 case CMD_SUBSCRIBE_LANE_VARIABLE: 00423 case CMD_SUBSCRIBE_VEHICLE_VARIABLE: 00424 case CMD_SUBSCRIBE_VEHICLETYPE_VARIABLE: 00425 case CMD_SUBSCRIBE_ROUTE_VARIABLE: 00426 case CMD_SUBSCRIBE_POI_VARIABLE: 00427 case CMD_SUBSCRIBE_POLYGON_VARIABLE: 00428 case CMD_SUBSCRIBE_JUNCTION_VARIABLE: 00429 case CMD_SUBSCRIBE_EDGE_VARIABLE: 00430 case CMD_SUBSCRIBE_SIM_VARIABLE: 00431 case CMD_SUBSCRIBE_GUI_VARIABLE: 00432 success = addSubscription(commandId); 00433 break; 00434 default: 00435 writeStatusCmd(commandId, RTYPE_NOTIMPLEMENTED, "Command not implemented in sumo"); 00436 } 00437 } 00438 if (!success) { 00439 while (myInputStorage.valid_pos() && myInputStorage.position() < commandStart + commandLength) { 00440 myInputStorage.readChar(); 00441 } 00442 } 00443 if (myInputStorage.position() != commandStart + commandLength) { 00444 std::ostringstream msg; 00445 msg << "Wrong position in requestMessage after dispatching command."; 00446 msg << " Expected command length was " << commandLength; 00447 msg << " but " << myInputStorage.position() - commandStart << " Bytes were read."; 00448 writeStatusCmd(commandId, RTYPE_ERR, msg.str()); 00449 myDoCloseConnection = true; 00450 } 00451 return commandId; 00452 } 00453 00454 /*****************************************************************************/ 00455 00456 void 00457 TraCIServer::postProcessSimulationStep2() { 00458 SUMOTime t = MSNet::getInstance()->getCurrentTimeStep(); 00459 writeStatusCmd(CMD_SIMSTEP2, RTYPE_OK, ""); 00460 int noActive = 0; 00461 for (std::vector<Subscription>::iterator i=mySubscriptions.begin(); i!=mySubscriptions.end();) { 00462 const Subscription& s = *i; 00463 bool isArrivedVehicle = (s.commandId == CMD_SUBSCRIBE_VEHICLE_VARIABLE) && (find(myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED].begin(), myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED].end(), s.id) != myVehicleStateChanges[MSNet::VEHICLE_STATE_ARRIVED].end()); 00464 if ((s.endTime<t) || isArrivedVehicle) { 00465 i = mySubscriptions.erase(i); 00466 continue; 00467 } 00468 ++i; 00469 if (s.beginTime>t) { 00470 continue; 00471 } 00472 ++noActive; 00473 } 00474 myOutputStorage.writeInt(noActive); 00475 for (std::vector<Subscription>::iterator i=mySubscriptions.begin(); i!=mySubscriptions.end(); ++i) { 00476 const Subscription& s = *i; 00477 if (s.beginTime>t) { 00478 continue; 00479 } 00480 tcpip::Storage into; 00481 std::string errors; 00482 processSingleSubscription(s, into, errors); 00483 myOutputStorage.writeStorage(into); 00484 } 00485 } 00486 00487 /*****************************************************************************/ 00488 00489 bool 00490 TraCIServer::commandGetVersion() { 00491 00492 std::string sumoVersion = VERSION_STRING; 00493 00494 // Prepare response 00495 tcpip::Storage answerTmp; 00496 00497 answerTmp.writeInt(TRACI_VERSION); 00498 answerTmp.writeString(std::string("SUMO ") + sumoVersion); 00499 00500 // When we get here, the response is stored in answerTmp -> put into myOutputStorage 00501 writeStatusCmd(CMD_GETVERSION, RTYPE_OK, ""); 00502 00503 // command length 00504 myOutputStorage.writeUnsignedByte(1 + 1 + static_cast<int>(answerTmp.size())); 00505 // command type 00506 myOutputStorage.writeUnsignedByte(CMD_GETVERSION); 00507 // and the parameter dependant part 00508 myOutputStorage.writeStorage(answerTmp); 00509 return true; 00510 } 00511 00512 /*****************************************************************************/ 00513 00514 bool 00515 TraCIServer::commandCloseConnection() { 00516 myDoCloseConnection = true; 00517 // write answer 00518 writeStatusCmd(CMD_CLOSE, RTYPE_OK, "Goodbye"); 00519 return true; 00520 } 00521 00522 /*****************************************************************************/ 00523 00524 bool 00525 TraCIServer::commandAddVehicle() { 00526 00527 // read parameters 00528 std::string vehicleId = myInputStorage.readString(); 00529 std::string vehicleTypeId = myInputStorage.readString(); 00530 std::string routeId = myInputStorage.readString(); 00531 std::string laneId = myInputStorage.readString(); 00532 SUMOReal insertionPosition = myInputStorage.readFloat(); 00533 SUMOReal insertionSpeed = myInputStorage.readFloat(); 00534 00535 // find vehicleType 00536 MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(vehicleTypeId); 00537 if (!vehicleType) { 00538 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_ERR, "Invalid vehicleTypeId: '"+vehicleTypeId+"'"); 00539 return false; 00540 } 00541 00542 // find route 00543 const MSRoute* route = MSRoute::dictionary(routeId); 00544 if (!route) { 00545 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_ERR, "Invalid routeId: '"+routeId+"'"); 00546 return false; 00547 } 00548 00549 // find lane 00550 MSLane* lane; 00551 if (laneId != "") { 00552 lane = MSLane::dictionary(laneId); 00553 if (!lane) { 00554 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_ERR, "Invalid laneId: '"+laneId+"'"); 00555 return false; 00556 } 00557 } else { 00558 lane = route->getEdges()[0]->getLanes()[0]; 00559 if (!lane) { 00560 writeStatusCmd(CMD_STOP, RTYPE_ERR, "Could not find first lane of first edge in routeId '"+routeId+"'"); 00561 return false; 00562 } 00563 } 00564 00565 if (&lane->getEdge()!=*route->begin()) { 00566 writeStatusCmd(CMD_STOP, RTYPE_ERR, "The route must start at the edge the lane starts at."); 00567 return false; 00568 } 00569 00570 // build vehicle 00571 SUMOVehicleParameter* vehicleParams = new SUMOVehicleParameter(); 00572 vehicleParams->id = vehicleId; 00573 vehicleParams->depart = MSNet::getInstance()->getCurrentTimeStep()+1; 00574 MSVehicle* vehicle = static_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().buildVehicle(vehicleParams, route, vehicleType)); 00575 if (vehicle == NULL) { 00576 writeStatusCmd(CMD_STOP, RTYPE_ERR, "Could not build vehicle"); 00577 return false; 00578 } 00579 00580 // calculate speed 00581 float clippedInsertionSpeed; 00582 if (insertionSpeed<0) { 00583 clippedInsertionSpeed = (float) MIN2(lane->getMaxSpeed(), vehicle->getMaxSpeed()); 00584 } else { 00585 clippedInsertionSpeed = (float) MIN3(lane->getMaxSpeed(), vehicle->getMaxSpeed(), insertionSpeed); 00586 } 00587 00588 // insert vehicle into the dictionary 00589 if (!MSNet::getInstance()->getVehicleControl().addVehicle(vehicle->getID(), vehicle)) { 00590 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_ERR, "Could not add vehicle to VehicleControl"); 00591 return false; 00592 } 00593 00594 // try to emit 00595 if (!lane->isInsertionSuccess(vehicle, clippedInsertionSpeed, insertionPosition, true)) { 00596 MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle); 00597 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_ERR, "Could not insert vehicle"); 00598 return false; 00599 } 00600 00601 // exec callback 00602 vehicle->onDepart(); 00603 00604 // create a reply message 00605 writeStatusCmd(CMD_ADDVEHICLE, RTYPE_OK, ""); 00606 00607 return true; 00608 } 00609 00610 00611 /*****************************************************************************/ 00612 00613 void 00614 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description) { 00615 writeStatusCmd(commandId, status, description, myOutputStorage); 00616 } 00617 00618 00619 void 00620 TraCIServer::writeStatusCmd(int commandId, int status, const std::string& description, tcpip::Storage& outputStorage) { 00621 if (status == RTYPE_ERR) { 00622 WRITE_ERROR("Answered with error to command " + toString(commandId) + ": " + description); 00623 } else if (status == RTYPE_NOTIMPLEMENTED) { 00624 WRITE_ERROR("Requested command not implemented (" + toString(commandId) + "): " + description); 00625 } 00626 outputStorage.writeUnsignedByte(1 + 1 + 1 + 4 + static_cast<int>(description.length())); // command length 00627 outputStorage.writeUnsignedByte(commandId); // command type 00628 outputStorage.writeUnsignedByte(status); // status 00629 outputStorage.writeString(description); // description 00630 } 00631 00632 /*****************************************************************************/ 00633 00634 bool 00635 TraCIServer::addSubscription(int commandId) { 00636 SUMOTime beginTime = myInputStorage.readInt(); 00637 SUMOTime endTime = myInputStorage.readInt(); 00638 std::string id = myInputStorage.readString(); 00639 int no = myInputStorage.readUnsignedByte(); 00640 std::vector<int> variables; 00641 for (int i=0; i<no; ++i) { 00642 variables.push_back(myInputStorage.readUnsignedByte()); 00643 } 00644 // check subscribe/unsubscribe 00645 bool ok = true; 00646 if (variables.size()==0) { 00647 // try unsubscribe 00648 bool found = false; 00649 for (std::vector<Subscription>::iterator j=mySubscriptions.begin(); j!=mySubscriptions.end();) { 00650 if ((*j).id==id&&(*j).commandId==commandId) { 00651 j = mySubscriptions.erase(j); 00652 found = true; 00653 continue; 00654 } 00655 ++j; 00656 } 00657 if (found) { 00658 writeStatusCmd(commandId, RTYPE_OK, ""); 00659 } else { 00660 writeStatusCmd(commandId, RTYPE_OK, "The subscription to remove was not found."); 00661 } 00662 } else { 00663 // process subscription 00664 Subscription s(commandId, id, variables, beginTime, endTime); 00665 tcpip::Storage writeInto; 00666 std::string errors; 00667 if (s.endTime<MSNet::getInstance()->getCurrentTimeStep()) { 00668 processSingleSubscription(s, writeInto, errors); 00669 writeStatusCmd(s.commandId, RTYPE_ERR, "Subscription has ended."); 00670 } else { 00671 if (processSingleSubscription(s, writeInto, errors)) { 00672 mySubscriptions.push_back(s); 00673 writeStatusCmd(s.commandId, RTYPE_OK, ""); 00674 } else { 00675 writeStatusCmd(s.commandId, RTYPE_ERR, "Could not add subscription (" + errors + ")."); 00676 } 00677 } 00678 myOutputStorage.writeStorage(writeInto); 00679 } 00680 return ok; 00681 } 00682 00683 00684 bool 00685 TraCIServer::processSingleSubscription(const Subscription& s, tcpip::Storage& writeInto, 00686 std::string& errors) { 00687 bool ok = true; 00688 tcpip::Storage outputStorage; 00689 for (std::vector<int>::const_iterator i=s.variables.begin(); i!=s.variables.end(); ++i) { 00690 tcpip::Storage message; 00691 message.writeUnsignedByte(*i); 00692 message.writeString(s.id); 00693 tcpip::Storage tmpOutput; 00694 int getId = s.commandId - 0x30; 00695 if (myExecutors.find(getId)!=myExecutors.end()) { 00696 ok &= myExecutors[getId](*this, message, tmpOutput); 00697 } else { 00698 writeStatusCmd(s.commandId, RTYPE_NOTIMPLEMENTED, "Unsupported command specified", tmpOutput); 00699 ok = false; 00700 } 00701 // copy response part 00702 if (ok) { 00703 int length = tmpOutput.readUnsignedByte(); 00704 while (--length>0) { 00705 tmpOutput.readUnsignedByte(); 00706 } 00707 int lengthLength = 1; 00708 length = tmpOutput.readUnsignedByte(); 00709 if (length==0) { 00710 lengthLength = 5; 00711 length = tmpOutput.readInt(); 00712 } 00713 //read responseType 00714 tmpOutput.readUnsignedByte(); 00715 int variable = tmpOutput.readUnsignedByte(); 00716 std::string id = tmpOutput.readString(); 00717 outputStorage.writeUnsignedByte(variable); 00718 outputStorage.writeUnsignedByte(RTYPE_OK); 00719 length -= (lengthLength+1+4+(int)id.length()); 00720 while (--length>0) { 00721 outputStorage.writeUnsignedByte(tmpOutput.readUnsignedByte()); 00722 } 00723 } else { 00724 //read length 00725 tmpOutput.readUnsignedByte(); 00726 //read cmd 00727 tmpOutput.readUnsignedByte(); 00728 //read status 00729 tmpOutput.readUnsignedByte(); 00730 std::string msg = tmpOutput.readString(); 00731 outputStorage.writeUnsignedByte(*i); 00732 outputStorage.writeUnsignedByte(RTYPE_ERR); 00733 outputStorage.writeUnsignedByte(TYPE_STRING); 00734 outputStorage.writeString(msg); 00735 errors = errors + msg; 00736 } 00737 } 00738 writeInto.writeUnsignedByte(0); // command length -> extended 00739 writeInto.writeInt((1+4) + 1 + (4 + (int)(s.id.length())) + 1 + (int)outputStorage.size()); 00740 writeInto.writeUnsignedByte(s.commandId + 0x10); 00741 writeInto.writeString(s.id); 00742 writeInto.writeUnsignedByte((int)(s.variables.size())); 00743 writeInto.writeStorage(outputStorage); 00744 return ok; 00745 } 00746 00747 void 00748 TraCIServer::writeResponseWithLength(tcpip::Storage& outputStorage, tcpip::Storage& tempMsg) { 00749 if (tempMsg.size()<254) { 00750 outputStorage.writeUnsignedByte(1 + (int)tempMsg.size()); // command length -> short 00751 } else { 00752 outputStorage.writeUnsignedByte(0); // command length -> extended 00753 outputStorage.writeInt(1 + 4 + (int)tempMsg.size()); 00754 } 00755 outputStorage.writeStorage(tempMsg); 00756 } 00757 00758 } 00759 00760 #endif