|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // APIs for getting/setting edge values via TraCI 00008 /****************************************************************************/ 00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors 00011 /****************************************************************************/ 00012 // 00013 // This program is free software; you can redistribute it and/or modify 00014 // it under the terms of the GNU General Public License as published by 00015 // the Free Software Foundation; either version 2 of the License, or 00016 // (at your option) any later version. 00017 // 00018 /****************************************************************************/ 00019 00020 00021 // =========================================================================== 00022 // included modules 00023 // =========================================================================== 00024 #ifdef _MSC_VER 00025 #include <windows_config.h> 00026 #else 00027 #include <config.h> 00028 #endif 00029 00030 #include <utils/common/StdDefs.h> 00031 #include <utils/geom/GeoConvHelper.h> 00032 #include <microsim/MSNet.h> 00033 #include <microsim/MSEdgeControl.h> 00034 #include <microsim/MSInsertionControl.h> 00035 #include <microsim/MSLane.h> 00036 #include <microsim/MSVehicle.h> 00037 #include "TraCIConstants.h" 00038 #include "TraCIDijkstraRouter.h" 00039 #include "TraCIServerAPI_Simulation.h" 00040 00041 #ifdef CHECK_MEMORY_LEAKS 00042 #include <foreign/nvwa/debug_new.h> 00043 #endif // CHECK_MEMORY_LEAKS 00044 00045 00046 // =========================================================================== 00047 // used namespaces 00048 // =========================================================================== 00049 using namespace traci; 00050 00051 00052 // =========================================================================== 00053 // method definitions 00054 // =========================================================================== 00055 bool 00056 TraCIServerAPI_Simulation::processGet(TraCIServer& server, tcpip::Storage& inputStorage, 00057 tcpip::Storage& outputStorage) { 00058 std::string warning = ""; // additional description for response 00059 // variable & id 00060 int variable = inputStorage.readUnsignedByte(); 00061 std::string id = inputStorage.readString(); 00062 // check variable 00063 if (variable!=VAR_TIME_STEP 00064 &&variable!=VAR_LOADED_VEHICLES_NUMBER&&variable!=VAR_LOADED_VEHICLES_IDS 00065 &&variable!=VAR_DEPARTED_VEHICLES_NUMBER&&variable!=VAR_DEPARTED_VEHICLES_IDS 00066 &&variable!=VAR_TELEPORT_STARTING_VEHICLES_NUMBER&&variable!=VAR_TELEPORT_STARTING_VEHICLES_IDS 00067 &&variable!=VAR_TELEPORT_ENDING_VEHICLES_NUMBER&&variable!=VAR_TELEPORT_ENDING_VEHICLES_IDS 00068 &&variable!=VAR_ARRIVED_VEHICLES_NUMBER&&variable!=VAR_ARRIVED_VEHICLES_IDS 00069 &&variable!=VAR_DELTA_T&&variable!=VAR_NET_BOUNDING_BOX 00070 &&variable!=VAR_MIN_EXPECTED_VEHICLES 00071 &&variable!=POSITION_CONVERSION&&variable!=DISTANCE_REQUEST 00072 ) { 00073 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Get Simulation Variable: unsupported variable specified", outputStorage); 00074 return false; 00075 } 00076 // begin response building 00077 tcpip::Storage tempMsg; 00078 // response-code, variableID, objectID 00079 tempMsg.writeUnsignedByte(RESPONSE_GET_SIM_VARIABLE); 00080 tempMsg.writeUnsignedByte(variable); 00081 tempMsg.writeString(id); 00082 // process request 00083 switch (variable) { 00084 case VAR_TIME_STEP: 00085 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00086 tempMsg.writeInt(MSNet::getInstance()->getCurrentTimeStep()); 00087 break; 00088 case VAR_LOADED_VEHICLES_NUMBER: { 00089 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second; 00090 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00091 tempMsg.writeInt((int) ids.size()); 00092 } 00093 break; 00094 case VAR_LOADED_VEHICLES_IDS: { 00095 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_BUILT)->second; 00096 tempMsg.writeUnsignedByte(TYPE_STRINGLIST); 00097 tempMsg.writeStringList(ids); 00098 } 00099 break; 00100 case VAR_DEPARTED_VEHICLES_NUMBER: { 00101 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second; 00102 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00103 tempMsg.writeInt((int) ids.size()); 00104 } 00105 break; 00106 case VAR_DEPARTED_VEHICLES_IDS: { 00107 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_DEPARTED)->second; 00108 tempMsg.writeUnsignedByte(TYPE_STRINGLIST); 00109 tempMsg.writeStringList(ids); 00110 } 00111 break; 00112 case VAR_TELEPORT_STARTING_VEHICLES_NUMBER: { 00113 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second; 00114 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00115 tempMsg.writeInt((int) ids.size()); 00116 } 00117 break; 00118 case VAR_TELEPORT_STARTING_VEHICLES_IDS: { 00119 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_STARTING_TELEPORT)->second; 00120 tempMsg.writeUnsignedByte(TYPE_STRINGLIST); 00121 tempMsg.writeStringList(ids); 00122 } 00123 break; 00124 case VAR_TELEPORT_ENDING_VEHICLES_NUMBER: { 00125 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second; 00126 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00127 tempMsg.writeInt((int) ids.size()); 00128 } 00129 break; 00130 case VAR_TELEPORT_ENDING_VEHICLES_IDS: { 00131 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ENDING_TELEPORT)->second; 00132 tempMsg.writeUnsignedByte(TYPE_STRINGLIST); 00133 tempMsg.writeStringList(ids); 00134 } 00135 break; 00136 case VAR_ARRIVED_VEHICLES_NUMBER: { 00137 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second; 00138 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00139 tempMsg.writeInt((int) ids.size()); 00140 } 00141 break; 00142 case VAR_ARRIVED_VEHICLES_IDS: { 00143 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second; 00144 tempMsg.writeUnsignedByte(TYPE_STRINGLIST); 00145 tempMsg.writeStringList(ids); 00146 } 00147 break; 00148 case VAR_DELTA_T: 00149 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00150 tempMsg.writeInt(DELTA_T); 00151 break; 00152 case VAR_NET_BOUNDING_BOX: { 00153 tempMsg.writeUnsignedByte(TYPE_BOUNDINGBOX); 00154 Boundary b = GeoConvHelper::getDefaultInstance().getConvBoundary(); 00155 tempMsg.writeDouble(b.xmin()); 00156 tempMsg.writeDouble(b.ymin()); 00157 tempMsg.writeDouble(b.xmax()); 00158 tempMsg.writeDouble(b.ymax()); 00159 break; 00160 } 00161 break; 00162 case VAR_MIN_EXPECTED_VEHICLES: { 00163 const std::vector<std::string> &ids = server.getVehicleStateChanges().find(MSNet::VEHICLE_STATE_ARRIVED)->second; 00164 tempMsg.writeUnsignedByte(TYPE_INTEGER); 00165 tempMsg.writeInt(MSNet::getInstance()->getVehicleControl().getActiveVehicleCount() + MSNet::getInstance()->getInsertionControl().getPendingFlowCount()); 00166 } 00167 break; 00168 case POSITION_CONVERSION: 00169 if (inputStorage.readUnsignedByte()!=TYPE_COMPOUND) { 00170 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a compound object.", outputStorage); 00171 return false; 00172 } 00173 if (inputStorage.readInt()!=2) { 00174 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Position conversion requires a source position and a position type as parameter.", outputStorage); 00175 return false; 00176 } 00177 if (!commandPositionConversion(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) { 00178 return false; 00179 } 00180 break; 00181 case DISTANCE_REQUEST: 00182 if (inputStorage.readUnsignedByte()!=TYPE_COMPOUND) { 00183 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires a compound object.", outputStorage); 00184 return false; 00185 } 00186 if (inputStorage.readInt()!=3) { 00187 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_ERR, "Retrieval of distance requires two positions and a distance type as parameter.", outputStorage); 00188 return false; 00189 } 00190 if (!commandDistanceRequest(server, inputStorage, tempMsg, CMD_GET_SIM_VARIABLE)) { 00191 return false; 00192 } 00193 break; 00194 default: 00195 break; 00196 } 00197 server.writeStatusCmd(CMD_GET_SIM_VARIABLE, RTYPE_OK, warning, outputStorage); 00198 server.writeResponseWithLength(outputStorage, tempMsg); 00199 return true; 00200 } 00201 00202 00203 std::pair<MSLane*, SUMOReal> 00204 TraCIServerAPI_Simulation::convertCartesianToRoadMap(Position pos) { 00205 std::pair<MSLane*, SUMOReal> result; 00206 std::vector<std::string> allEdgeIds; 00207 SUMOReal minDistance = std::numeric_limits<SUMOReal>::max(); 00208 00209 allEdgeIds = MSNet::getInstance()->getEdgeControl().getEdgeNames(); 00210 for (std::vector<std::string>::iterator itId = allEdgeIds.begin(); itId != allEdgeIds.end(); itId++) { 00211 const std::vector<MSLane*> &allLanes = MSEdge::dictionary((*itId))->getLanes(); 00212 for (std::vector<MSLane*>::const_iterator itLane = allLanes.begin(); itLane != allLanes.end(); itLane++) { 00213 const SUMOReal newDistance = (*itLane)->getShape().distance(pos); 00214 if (newDistance < minDistance) { 00215 minDistance = newDistance; 00216 result.first = (*itLane); 00217 } 00218 } 00219 } 00220 result.second = result.first->getShape().nearest_position_on_line_to_point(pos, false); 00221 return result; 00222 } 00223 00224 00225 const MSLane* 00226 TraCIServerAPI_Simulation::getLaneChecking(std::string roadID, int laneIndex, SUMOReal pos) { 00227 const MSEdge* edge = MSEdge::dictionary(roadID); 00228 if (edge == 0) { 00229 throw TraCIException("Unknown edge " + roadID); 00230 } 00231 if (laneIndex < 0 || laneIndex >= (int)edge->getLanes().size()) { 00232 throw TraCIException("Invalid lane index for " + roadID); 00233 } 00234 const MSLane* lane = edge->getLanes()[laneIndex]; 00235 if (pos < 0 ||pos > lane->getLength()) { 00236 throw TraCIException("Position on lane invalid"); 00237 } 00238 return lane; 00239 } 00240 00241 00242 bool 00243 TraCIServerAPI_Simulation::commandPositionConversion(traci::TraCIServer& server, tcpip::Storage& inputStorage, 00244 tcpip::Storage& outputStorage, int commandId) { 00245 tcpip::Storage tmpResult; 00246 std::pair<MSLane*, SUMOReal> roadPos; 00247 Position cartesianPos; 00248 Position geoPos; 00249 SUMOReal z = 0; 00250 00251 // actual position type that will be converted 00252 int srcPosType = inputStorage.readUnsignedByte(); 00253 00254 switch (srcPosType) { 00255 case POSITION_2D: 00256 case POSITION_3D: 00257 case POSITION_LAT_LON: 00258 case POSITION_LAT_LON_ALT: { 00259 SUMOReal x = inputStorage.readDouble(); 00260 SUMOReal y = inputStorage.readDouble(); 00261 if (srcPosType != POSITION_2D && srcPosType != POSITION_LAT_LON) { 00262 z = inputStorage.readDouble(); 00263 } 00264 geoPos.set(x, y); 00265 cartesianPos.set(x, y); 00266 if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) { 00267 GeoConvHelper::getDefaultInstance().x2cartesian(cartesianPos); 00268 } else { 00269 GeoConvHelper::getDefaultInstance().cartesian2geo(geoPos); 00270 } 00271 } 00272 break; 00273 case POSITION_ROADMAP: { 00274 std::string roadID = inputStorage.readString(); 00275 SUMOReal pos = inputStorage.readDouble(); 00276 int laneIdx = inputStorage.readUnsignedByte(); 00277 try { 00278 cartesianPos = geoPos = getLaneChecking(roadID, laneIdx, pos)->getShape().positionAtLengthPosition(pos); 00279 GeoConvHelper::getDefaultInstance().cartesian2geo(geoPos); 00280 } catch (TraCIException& e) { 00281 server.writeStatusCmd(commandId, RTYPE_ERR, e.what()); 00282 return false; 00283 } 00284 } 00285 break; 00286 default: 00287 server.writeStatusCmd(commandId, RTYPE_ERR, 00288 "Source position type not supported"); 00289 return false; 00290 } 00291 00292 int destPosType = inputStorage.readUnsignedByte(); 00293 00294 switch (destPosType) { 00295 case POSITION_ROADMAP: { 00296 if (commandId != CMD_POSITIONCONVERSION) { 00297 // skip empty values 00298 inputStorage.readString(); 00299 inputStorage.readDouble(); 00300 inputStorage.readUnsignedByte(); 00301 } 00302 // convert road map to 3D position 00303 roadPos = convertCartesianToRoadMap(cartesianPos); 00304 00305 // write result that is added to response msg 00306 tmpResult.writeUnsignedByte(POSITION_ROADMAP); 00307 tmpResult.writeString(roadPos.first->getEdge().getID()); 00308 tmpResult.writeDouble(roadPos.second); 00309 const std::vector<MSLane*> lanes = roadPos.first->getEdge().getLanes(); 00310 tmpResult.writeUnsignedByte((int)distance(lanes.begin(), find(lanes.begin(), lanes.end(), roadPos.first))); 00311 } 00312 break; 00313 case POSITION_2D: 00314 case POSITION_3D: 00315 case POSITION_LAT_LON: 00316 case POSITION_LAT_LON_ALT: 00317 if (commandId != CMD_POSITIONCONVERSION) { 00318 // skip empty values 00319 inputStorage.readDouble(); 00320 inputStorage.readDouble(); 00321 if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) { 00322 inputStorage.readDouble(); 00323 } 00324 } 00325 tmpResult.writeUnsignedByte(destPosType); 00326 if (srcPosType == POSITION_LAT_LON || srcPosType == POSITION_LAT_LON_ALT) { 00327 tmpResult.writeDouble(geoPos.x()); 00328 tmpResult.writeDouble(geoPos.y()); 00329 } else { 00330 tmpResult.writeDouble(cartesianPos.x()); 00331 tmpResult.writeDouble(cartesianPos.y()); 00332 } 00333 if (destPosType != POSITION_2D && destPosType != POSITION_LAT_LON) { 00334 tmpResult.writeDouble(z); 00335 } 00336 break; 00337 default: 00338 server.writeStatusCmd(commandId, RTYPE_ERR, 00339 "Destination position type not supported"); 00340 return false; 00341 } 00342 if (commandId == CMD_POSITIONCONVERSION) { 00343 // add converted Position to response 00344 outputStorage.writeUnsignedByte(1 + 1 + (int)tmpResult.size() + 1); // length 00345 outputStorage.writeUnsignedByte(commandId); // command id 00346 outputStorage.writeStorage(tmpResult); // position dependant part 00347 outputStorage.writeUnsignedByte(destPosType); // destination type 00348 } else { 00349 outputStorage.writeStorage(tmpResult); // position dependant part 00350 } 00351 return true; 00352 } 00353 00354 /****************************************************************************/ 00355 00356 bool 00357 TraCIServerAPI_Simulation::commandDistanceRequest(traci::TraCIServer& server, tcpip::Storage& inputStorage, 00358 tcpip::Storage& outputStorage, int commandId) { 00359 Position pos1; 00360 Position pos2; 00361 std::pair<const MSLane*, SUMOReal> roadPos1; 00362 std::pair<const MSLane*, SUMOReal> roadPos2; 00363 00364 // read position 1 00365 int posType = inputStorage.readUnsignedByte(); 00366 switch (posType) { 00367 case POSITION_ROADMAP: 00368 try { 00369 std::string roadID = inputStorage.readString(); 00370 roadPos1.second = inputStorage.readDouble(); 00371 roadPos1.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos1.second); 00372 pos1 = roadPos1.first->getShape().positionAtLengthPosition(roadPos1.second); 00373 } catch (TraCIException& e) { 00374 server.writeStatusCmd(commandId, RTYPE_ERR, e.what()); 00375 return false; 00376 } 00377 break; 00378 case POSITION_2D: 00379 case POSITION_3D: { 00380 SUMOReal p1x = inputStorage.readDouble(); 00381 SUMOReal p1y = inputStorage.readDouble(); 00382 pos1.set(p1x, p1y); 00383 } 00384 if (posType == POSITION_3D) { 00385 inputStorage.readDouble(); // z value is ignored 00386 } 00387 roadPos1 = convertCartesianToRoadMap(pos1); 00388 break; 00389 default: 00390 server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request"); 00391 return false; 00392 } 00393 00394 // read position 2 00395 posType = inputStorage.readUnsignedByte(); 00396 switch (posType) { 00397 case POSITION_ROADMAP: 00398 try { 00399 std::string roadID = inputStorage.readString(); 00400 roadPos2.second = inputStorage.readDouble(); 00401 roadPos2.first = getLaneChecking(roadID, inputStorage.readUnsignedByte(), roadPos2.second); 00402 pos2 = roadPos2.first->getShape().positionAtLengthPosition(roadPos2.second); 00403 } catch (TraCIException& e) { 00404 server.writeStatusCmd(commandId, RTYPE_ERR, e.what()); 00405 return false; 00406 } 00407 break; 00408 case POSITION_2D: 00409 case POSITION_3D: { 00410 SUMOReal p2x = inputStorage.readDouble(); 00411 SUMOReal p2y = inputStorage.readDouble(); 00412 pos2.set(p2x, p2y); 00413 } 00414 if (posType == POSITION_3D) { 00415 inputStorage.readDouble(); // z value is ignored 00416 } 00417 roadPos2 = convertCartesianToRoadMap(pos2); 00418 break; 00419 default: 00420 server.writeStatusCmd(commandId, RTYPE_ERR, "Unknown position format used for distance request"); 00421 return false; 00422 } 00423 00424 // read distance type 00425 int distType = inputStorage.readUnsignedByte(); 00426 00427 SUMOReal distance = 0.0; 00428 if (distType == REQUEST_DRIVINGDIST) { 00429 // compute driving distance 00430 std::vector<const MSEdge*> edges; 00431 TraCIDijkstraRouter<MSEdge> router(MSEdge::dictSize()); 00432 00433 if ((roadPos1.first == roadPos2.first) 00434 && (roadPos1.second <= roadPos2.second)) { 00435 distance = roadPos2.second - roadPos1.second; 00436 } else { 00437 router.compute(&roadPos1.first->getEdge(), &roadPos2.first->getEdge(), NULL, 00438 MSNet::getInstance()->getCurrentTimeStep(), edges); 00439 MSRoute route("", edges, false, RGBColor::DEFAULT_COLOR, std::vector<SUMOVehicleParameter::Stop>()); 00440 distance = route.getDistanceBetween(roadPos1.second, roadPos2.second, 00441 &roadPos1.first->getEdge(), &roadPos2.first->getEdge()); 00442 } 00443 } else { 00444 // compute air distance (default) 00445 // correct the distance type in case it was not valid 00446 distType = REQUEST_AIRDIST; 00447 distance = pos1.distanceTo(pos2); 00448 } 00449 // write response command 00450 if (commandId == CMD_DISTANCEREQUEST) { 00451 outputStorage.writeUnsignedByte(1 + 1 + 1 + 8); // length 00452 outputStorage.writeUnsignedByte(commandId); 00453 outputStorage.writeUnsignedByte(distType); 00454 } else { 00455 outputStorage.writeUnsignedByte(TYPE_DOUBLE); 00456 } 00457 outputStorage.writeDouble(distance); 00458 return true; 00459 }