SUMO - Simulation of Urban MObility

TraCIServerAPI_Simulation.cpp

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines