SUMO - Simulation of Urban MObility
TraCIServerAPI_TLS.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00009 // APIs for getting/setting traffic light values via TraCI
00010 /****************************************************************************/
00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00013 /****************************************************************************/
00014 //
00015 //   This file is part of SUMO.
00016 //   SUMO is free software: you can redistribute it and/or modify
00017 //   it under the terms of the GNU General Public License as published by
00018 //   the Free Software Foundation, either version 3 of the License, or
00019 //   (at your option) any later version.
00020 //
00021 /****************************************************************************/
00022 
00023 
00024 // ===========================================================================
00025 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #ifndef NO_TRACI
00034 
00035 #include "TraCIConstants.h"
00036 #include <microsim/traffic_lights/MSTLLogicControl.h>
00037 #include <microsim/MSLane.h>
00038 #include "TraCIServerAPI_TLS.h"
00039 
00040 #ifdef CHECK_MEMORY_LEAKS
00041 #include <foreign/nvwa/debug_new.h>
00042 #endif // CHECK_MEMORY_LEAKS
00043 
00044 
00045 // ===========================================================================
00046 // used namespaces
00047 // ===========================================================================
00048 using namespace traci;
00049 
00050 
00051 // ===========================================================================
00052 // method definitions
00053 // ===========================================================================
00054 bool
00055 TraCIServerAPI_TLS::processGet(TraCIServer& server, tcpip::Storage& inputStorage,
00056                                tcpip::Storage& outputStorage) {
00057     std::string warning = ""; // additional description for response
00058     // variable & id
00059     int variable = inputStorage.readUnsignedByte();
00060     std::string id = inputStorage.readString();
00061     // check variable
00062     if (variable != ID_LIST && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_DEFINITION_RYG
00063             && variable != TL_CONTROLLED_LANES && variable != TL_CONTROLLED_LINKS
00064             && variable != TL_CURRENT_PHASE && variable != TL_CURRENT_PROGRAM
00065             && variable != TL_NEXT_SWITCH && variable != TL_PHASE_DURATION && variable != ID_COUNT) {
00066         server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Get TLS Variable: unsupported variable specified", outputStorage);
00067         return false;
00068     }
00069     // begin response building
00070     tcpip::Storage tempMsg;
00071     //  response-code, variableID, objectID
00072     tempMsg.writeUnsignedByte(RESPONSE_GET_TL_VARIABLE);
00073     tempMsg.writeUnsignedByte(variable);
00074     tempMsg.writeString(id);
00075     if (variable == ID_LIST) {
00076         std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
00077         tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
00078         tempMsg.writeStringList(ids);
00079     } else if (variable == ID_COUNT) {
00080         std::vector<std::string> ids = MSNet::getInstance()->getTLSControl().getAllTLIds();
00081         tempMsg.writeUnsignedByte(TYPE_INTEGER);
00082         tempMsg.writeInt((int) ids.size());
00083     } else {
00084         if (!MSNet::getInstance()->getTLSControl().knows(id)) {
00085             server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
00086             return false;
00087         }
00088         MSTLLogicControl::TLSLogicVariants& vars = MSNet::getInstance()->getTLSControl().get(id);
00089         switch (variable) {
00090             case ID_LIST:
00091                 break;
00092             case TL_RED_YELLOW_GREEN_STATE: {
00093                 tempMsg.writeUnsignedByte(TYPE_STRING);
00094                 std::string state = vars.getActive()->getCurrentPhaseDef().getState();
00095                 tempMsg.writeString(state);
00096             }
00097             break;
00098             case TL_COMPLETE_DEFINITION_RYG: {
00099                 std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
00100                 tempMsg.writeUnsignedByte(TYPE_COMPOUND);
00101                 tcpip::Storage tempContent;
00102                 unsigned int cnt = 0;
00103                 tempContent.writeUnsignedByte(TYPE_INTEGER);
00104                 tempContent.writeInt((int) logics.size());
00105                 ++cnt;
00106                 for (unsigned int i = 0; i < logics.size(); ++i) {
00107                     MSTrafficLightLogic* logic = logics[i];
00108                     tempContent.writeUnsignedByte(TYPE_STRING);
00109                     tempContent.writeString(logic->getProgramID());
00110                     ++cnt;
00111                     // type (always 0 by now)
00112                     tempContent.writeUnsignedByte(TYPE_INTEGER);
00113                     tempContent.writeInt(0);
00114                     ++cnt;
00115                     // subparameter (always 0 by now)
00116                     tempContent.writeUnsignedByte(TYPE_COMPOUND);
00117                     tempContent.writeInt(0);
00118                     ++cnt;
00119                     // (current) phase index
00120                     tempContent.writeUnsignedByte(TYPE_INTEGER);
00121                     tempContent.writeInt((int) logic->getCurrentPhaseIndex());
00122                     ++cnt;
00123                     // phase number
00124                     unsigned int phaseNo = logic->getPhaseNumber();
00125                     tempContent.writeUnsignedByte(TYPE_INTEGER);
00126                     tempContent.writeInt((int) phaseNo);
00127                     ++cnt;
00128                     for (unsigned int j = 0; j < phaseNo; ++j) {
00129                         MSPhaseDefinition phase = logic->getPhase(j);
00130                         tempContent.writeUnsignedByte(TYPE_INTEGER);
00131                         tempContent.writeInt(phase.duration);
00132                         ++cnt;
00133                         tempContent.writeUnsignedByte(TYPE_INTEGER);
00134                         tempContent.writeInt(phase.minDuration);
00135                         ++cnt; // not implemented
00136                         tempContent.writeUnsignedByte(TYPE_INTEGER);
00137                         tempContent.writeInt(phase.maxDuration);
00138                         ++cnt; // not implemented
00139                         const std::string& state = phase.getState();
00140                         //unsigned int linkNo = (unsigned int)(vars.getActive()->getLinks().size());
00141                         tempContent.writeUnsignedByte(TYPE_STRING);
00142                         tempContent.writeString(state);
00143                         ++cnt;
00144                     }
00145                 }
00146                 tempMsg.writeInt((int) cnt);
00147                 tempMsg.writeStorage(tempContent);
00148             }
00149             break;
00150             case TL_CONTROLLED_LANES: {
00151                 const MSTrafficLightLogic::LaneVectorVector& lanes = vars.getActive()->getLanes();
00152                 tempMsg.writeUnsignedByte(TYPE_STRINGLIST);
00153                 std::vector<std::string> laneIDs;
00154                 for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
00155                     const MSTrafficLightLogic::LaneVector& llanes = (*i);
00156                     for (MSTrafficLightLogic::LaneVector::const_iterator j = llanes.begin(); j != llanes.end(); ++j) {
00157                         laneIDs.push_back((*j)->getID());
00158                     }
00159                 }
00160                 tempMsg.writeStringList(laneIDs);
00161             }
00162             break;
00163             case TL_CONTROLLED_LINKS: {
00164                 const MSTrafficLightLogic::LaneVectorVector& lanes = vars.getActive()->getLanes();
00165                 const MSTrafficLightLogic::LinkVectorVector& links = vars.getActive()->getLinks();
00166                 //
00167                 tempMsg.writeUnsignedByte(TYPE_COMPOUND);
00168                 tcpip::Storage tempContent;
00169                 unsigned int cnt = 0;
00170                 tempContent.writeUnsignedByte(TYPE_INTEGER);
00171                 unsigned int no = (unsigned int) lanes.size();
00172                 tempContent.writeInt((int) no);
00173                 for (unsigned int i = 0; i < no; ++i) {
00174                     const MSTrafficLightLogic::LaneVector& llanes = lanes[i];
00175                     const MSTrafficLightLogic::LinkVector& llinks = links[i];
00176                     // number of links controlled by this signal (signal i)
00177                     tempContent.writeUnsignedByte(TYPE_INTEGER);
00178                     unsigned int no2 = (unsigned int) llanes.size();
00179                     tempContent.writeInt((int) no2);
00180                     ++cnt;
00181                     for (unsigned int j = 0; j < no2; ++j) {
00182                         MSLink* link = llinks[j];
00183                         std::vector<std::string> def;
00184                         // incoming lane
00185                         def.push_back(llanes[j]->getID());
00186                         // approached non-internal lane (if any)
00187                         def.push_back(link->getLane() != 0 ? link->getLane()->getID() : "");
00188                         // approached "via", internal lane (if any)
00189 #ifdef HAVE_INTERNAL_LANES
00190                         def.push_back(link->getViaLane() != 0 ? link->getViaLane()->getID() : "");
00191 #else
00192                         def.push_back("");
00193 #endif
00194                         tempContent.writeUnsignedByte(TYPE_STRINGLIST);
00195                         tempContent.writeStringList(def);
00196                         ++cnt;
00197                     }
00198                 }
00199                 tempMsg.writeInt((int) cnt);
00200                 tempMsg.writeStorage(tempContent);
00201             }
00202             break;
00203             case TL_CURRENT_PHASE:
00204                 tempMsg.writeUnsignedByte(TYPE_INTEGER);
00205                 tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseIndex());
00206                 break;
00207             case TL_CURRENT_PROGRAM:
00208                 tempMsg.writeUnsignedByte(TYPE_STRING);
00209                 tempMsg.writeString(vars.getActive()->getProgramID());
00210                 break;
00211             case TL_PHASE_DURATION:
00212                 tempMsg.writeUnsignedByte(TYPE_INTEGER);
00213                 tempMsg.writeInt((int) vars.getActive()->getCurrentPhaseDef().duration);
00214                 break;
00215             case TL_NEXT_SWITCH:
00216                 tempMsg.writeUnsignedByte(TYPE_INTEGER);
00217                 tempMsg.writeInt((int) vars.getActive()->getNextSwitchTime());
00218                 break;
00219             case TL_CONTROLLED_JUNCTIONS: {
00220             }
00221             break;
00222             default:
00223                 break;
00224         }
00225     }
00226     server.writeStatusCmd(CMD_GET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
00227     server.writeResponseWithLength(outputStorage, tempMsg);
00228     return true;
00229 }
00230 
00231 
00232 bool
00233 TraCIServerAPI_TLS::processSet(TraCIServer& server, tcpip::Storage& inputStorage,
00234                                tcpip::Storage& outputStorage) {
00235     std::string warning = ""; // additional description for response
00236     // variable
00237     int variable = inputStorage.readUnsignedByte();
00238     if (variable != TL_PHASE_INDEX && variable != TL_PROGRAM
00239             && variable != TL_PHASE_DURATION && variable != TL_RED_YELLOW_GREEN_STATE && variable != TL_COMPLETE_PROGRAM_RYG) {
00240         server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Change TLS State: unsupported variable specified", outputStorage);
00241         return false;
00242     }
00243     std::string id = inputStorage.readString();
00244     if (!MSNet::getInstance()->getTLSControl().knows(id)) {
00245         server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "Traffic light '" + id + "' is not known", outputStorage);
00246         return false;
00247     }
00248     MSTLLogicControl& tlsControl = MSNet::getInstance()->getTLSControl();
00249     SUMOTime cTime = MSNet::getInstance()->getCurrentTimeStep();
00250     MSTLLogicControl::TLSLogicVariants& vars = tlsControl.get(id);
00251     int valueDataType = inputStorage.readUnsignedByte();
00252     switch (variable) {
00253         case TL_PHASE_INDEX: {
00254             if (valueDataType != TYPE_INTEGER) {
00255                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index must be given as an integer.", outputStorage);
00256                 return false;
00257             }
00258             int index = inputStorage.readInt();
00259             if (index < 0 || vars.getActive()->getPhaseNumber() <= (unsigned int)index) {
00260                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase index is not in the allowed range.", outputStorage);
00261                 return false;
00262             }
00263             int duration = vars.getActive()->getPhase(index).duration;
00264             vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
00265         }
00266         break;
00267         case TL_PROGRAM: {
00268             if (valueDataType != TYPE_STRING) {
00269                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The program must be given as a string.", outputStorage);
00270                 return false;
00271             }
00272             std::string subID = inputStorage.readString();
00273             try {
00274                 vars.switchTo(tlsControl, subID);
00275             } catch (ProcessError& e) {
00276                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, e.what(), outputStorage);
00277                 return false;
00278             }
00279         }
00280         break;
00281         case TL_PHASE_DURATION: {
00282             if (valueDataType != TYPE_INTEGER) {
00283                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase duration must be given as an integer.", outputStorage);
00284                 return false;
00285             }
00286             int duration = inputStorage.readInt();
00287             int index = vars.getActive()->getCurrentPhaseIndex();
00288             vars.getActive()->changeStepAndDuration(tlsControl, cTime, index, duration);
00289         }
00290         break;
00291         case TL_RED_YELLOW_GREEN_STATE: {
00292             if (valueDataType != TYPE_STRING) {
00293                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "The phase must be given as a string.", outputStorage);
00294                 return false;
00295             }
00296             // build only once...
00297             std::string state = inputStorage.readString();
00298             if (vars.getLogic("online") == 0) {
00299                 MSPhaseDefinition* phase = new MSPhaseDefinition(DELTA_T, state);
00300                 std::vector<MSPhaseDefinition*> phases;
00301                 phases.push_back(phase);
00302                 MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, "online", phases, 0, cTime + DELTA_T);
00303                 vars.addLogic("online", logic, true, true);
00304             } else {
00305                 MSPhaseDefinition nphase(DELTA_T, state);
00306                 *(static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic("online"))->getPhases()[0]) = nphase;
00307             }
00308             // @note: this assumes logic "online" is still active
00309             vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
00310             vars.executeOnSwitchActions();
00311         }
00312         break;
00313         case TL_COMPLETE_PROGRAM_RYG: {
00314             if (valueDataType != TYPE_COMPOUND) {
00315                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "A compound object is needed for setting a new program.", outputStorage);
00316                 return false;
00317             }
00318             //read itemNo
00319             inputStorage.readInt();
00320             if (inputStorage.readUnsignedByte() != TYPE_STRING) {
00321                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 1. parameter (subid) must be a string.", outputStorage);
00322                 return false;
00323             }
00324             std::string subid = inputStorage.readString();
00325             if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00326                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 2. parameter (type) must be an int.", outputStorage);
00327                 return false;
00328             }
00329             //read type
00330             inputStorage.readInt();
00331             if (inputStorage.readUnsignedByte() != TYPE_COMPOUND) {
00332                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 3. parameter (subparams) must be a compound object.", outputStorage);
00333                 return false;
00334             }
00335             //read sublength
00336             inputStorage.readInt();
00337             if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00338                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4. parameter (index) must be an int.", outputStorage);
00339                 return false;
00340             }
00341             int index = inputStorage.readInt();
00342             if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00343                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 5. parameter (phase number) must be an int.", outputStorage);
00344                 return false;
00345             }
00346             int phaseNo = inputStorage.readInt();
00347             // make sure index and phaseNo are consistent
00348             if (index >= phaseNo) {
00349                 server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 4/5. parameter (index) must be less than parameter (phase number).", outputStorage);
00350                 return false;
00351             }
00352 
00353             std::vector<MSPhaseDefinition*> phases;
00354             for (int j = 0; j < phaseNo; ++j) {
00355                 if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00356                     server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.1. parameter (duration) must be an int.", outputStorage);
00357                     return false;
00358                 }
00359                 int duration = inputStorage.readInt();
00360                 if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00361                     server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.2. parameter (min duration) must be an int.", outputStorage);
00362                     return false;
00363                 }
00364                 int minDuration = inputStorage.readInt();
00365                 if (inputStorage.readUnsignedByte() != TYPE_INTEGER) {
00366                     server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.3. parameter (max duration) must be an int.", outputStorage);
00367                     return false;
00368                 }
00369                 int maxDuration = inputStorage.readInt();
00370                 if (inputStorage.readUnsignedByte() != TYPE_STRING) {
00371                     server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_ERR, "set program: 6.4. parameter (phase) must be a string.", outputStorage);
00372                     return false;
00373                 }
00374                 std::string state = inputStorage.readString();
00375                 MSPhaseDefinition* phase = new MSPhaseDefinition(duration, minDuration, maxDuration, state);
00376                 phases.push_back(phase);
00377             }
00378             if (vars.getLogic(subid) == 0) {
00379                 MSTrafficLightLogic* logic = new MSSimpleTrafficLightLogic(tlsControl, id, subid, phases, index, 0);
00380                 vars.addLogic(subid, logic, true, true);
00381             } else {
00382                 static_cast<MSSimpleTrafficLightLogic*>(vars.getLogic(subid))->setPhases(phases, index);
00383             }
00384             vars.getActive()->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
00385             vars.executeOnSwitchActions();
00386         }
00387         break;
00388         default:
00389             break;
00390     }
00391     server.writeStatusCmd(CMD_SET_TL_VARIABLE, RTYPE_OK, warning, outputStorage);
00392     return true;
00393 }
00394 
00395 #endif
00396 
00397 
00398 /****************************************************************************/
00399 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines