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 #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