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