|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Importer for traffic lights stored in XML 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 <string> 00031 #include <iostream> 00032 #include <xercesc/sax/HandlerBase.hpp> 00033 #include <xercesc/sax/AttributeList.hpp> 00034 #include <xercesc/sax/SAXParseException.hpp> 00035 #include <xercesc/sax/SAXException.hpp> 00036 #include <utils/common/StringTokenizer.h> 00037 #include <utils/xml/SUMOSAXHandler.h> 00038 #include <utils/xml/SUMOXMLDefinitions.h> 00039 #include <utils/common/ToString.h> 00040 #include <utils/common/TplConvert.h> 00041 #include <utils/common/TplConvertSec.h> 00042 #include <utils/common/UtilExceptions.h> 00043 #include <utils/common/MsgHandler.h> 00044 #include <utils/options/OptionsCont.h> 00045 #include <netbuild/NBEdge.h> 00046 #include <netbuild/NBEdgeCont.h> 00047 #include <netbuild/NBNode.h> 00048 #include <netbuild/NBOwnTLDef.h> 00049 #include <netbuild/NBLoadedSUMOTLDef.h> 00050 #include <netbuild/NBTrafficLightLogicCont.h> 00051 #include "NIImporter_SUMO.h" 00052 #include "NIXMLTrafficLightsHandler.h" 00053 00054 #ifdef CHECK_MEMORY_LEAKS 00055 #include <foreign/nvwa/debug_new.h> 00056 #endif // CHECK_MEMORY_LEAKS 00057 00058 00059 // =========================================================================== 00060 // method definitions 00061 // =========================================================================== 00062 NIXMLTrafficLightsHandler::NIXMLTrafficLightsHandler( 00063 NBTrafficLightLogicCont& tlCont, NBEdgeCont& ec) throw() : 00064 SUMOSAXHandler("xml-tllogics"), 00065 myTLLCont(tlCont), 00066 myEdgeCont(ec), 00067 myCurrentTL(0), 00068 myResetPhases(false) 00069 {} 00070 00071 00072 NIXMLTrafficLightsHandler::~NIXMLTrafficLightsHandler() throw() {} 00073 00074 00075 void 00076 NIXMLTrafficLightsHandler::myStartElement( 00077 int element, const SUMOSAXAttributes& attrs) throw(ProcessError) { 00078 switch (element) { 00079 case SUMO_TAG_TLLOGIC: 00080 myCurrentTL = initTrafficLightLogic(attrs, myCurrentTL); 00081 break; 00082 case SUMO_TAG_PHASE: 00083 if (myResetPhases) { 00084 myCurrentTL->getLogic()->resetPhases(); 00085 myResetPhases = false; 00086 } 00087 NIImporter_SUMO::addPhase(attrs, myCurrentTL); 00088 break; 00089 case SUMO_TAG_CONNECTION: 00090 addTlConnection(attrs); 00091 break; 00092 case SUMO_TAG_RESET: 00093 removeTlConnection(attrs); 00094 break; 00095 default: 00096 break; 00097 } 00098 } 00099 00100 00101 void 00102 NIXMLTrafficLightsHandler::myEndElement(int element) throw(ProcessError) { 00103 switch (element) { 00104 case SUMO_TAG_TLLOGIC: 00105 if (!myCurrentTL) { 00106 WRITE_ERROR("Unmatched closing tag for tl-logic."); 00107 } else { 00108 if (!myTLLCont.insert(myCurrentTL)) { 00109 WRITE_MESSAGE("Updating program '" + myCurrentTL->getProgramID() + 00110 "' for traffic light '" + myCurrentTL->getID() + "'"); 00111 } 00112 myCurrentTL = 0; 00113 } 00114 break; 00115 default: 00116 break; 00117 } 00118 } 00119 00120 00121 NBLoadedSUMOTLDef* 00122 NIXMLTrafficLightsHandler::initTrafficLightLogic(const SUMOSAXAttributes& attrs, NBLoadedSUMOTLDef* currentTL) { 00123 if (currentTL) { 00124 WRITE_ERROR("Definition of tl-logic '" + currentTL->getID() + "' was not finished."); 00125 return 0; 00126 } 00127 bool ok = true; 00128 std::string id = attrs.getStringReporting(SUMO_ATTR_ID, 0, ok); 00129 std::string programID = attrs.getOptStringReporting(SUMO_ATTR_PROGRAMID, id.c_str(), ok, "<unknown>"); 00130 00131 // there are two scenarios to consider 00132 // 1) the tll.xml is loaded to updated traffic lights defined in a net.xml: 00133 // simply retrieve the loaded definitions and update them 00134 // 2) the tll.xml is loaded to define new traffic lights 00135 // nod.xml will have triggered building of NBOwnTLDef. Replace it with NBLoadedSUMOTLDef 00136 NBLoadedSUMOTLDef* loadedDef = dynamic_cast<NBLoadedSUMOTLDef*>(myTLLCont.getDefinition(id, programID)); 00137 if (loadedDef == 0) { 00138 // case 2 00139 NBOwnTLDef* newDef = dynamic_cast<NBOwnTLDef*>(myTLLCont.getDefinition( 00140 id, NBTrafficLightDefinition::DefaultProgramID)); 00141 assert(newDef != 0); 00142 loadedDef = new NBLoadedSUMOTLDef(id, programID, 0); 00143 std::vector<NBNode*> nodes = newDef->getControlledNodes(); 00144 for (std::vector<NBNode*>::iterator it=nodes.begin(); it != nodes.end(); it++) { 00145 (*it)->removeTrafficLight(newDef); 00146 (*it)->addTrafficLight(loadedDef); 00147 } 00148 myTLLCont.removeProgram(id, NBTrafficLightDefinition::DefaultProgramID); 00149 myTLLCont.insert(loadedDef); 00150 00151 std::string type = attrs.getOptStringReporting(SUMO_ATTR_TYPE, 0, ok, toString(TLTYPE_STATIC)); 00152 if (type != toString(TLTYPE_STATIC)) { 00153 WRITE_WARNING("Traffic light '" + id + "' has unsupported type '" + type + "' and will be converted to '" + 00154 toString(TLTYPE_STATIC) + "'"); 00155 } 00156 } 00157 if (attrs.hasAttribute(SUMO_ATTR_OFFSET)) { 00158 SUMOTime offset = TIME2STEPS(attrs.getSUMORealReporting(SUMO_ATTR_OFFSET, id.c_str(), ok)); 00159 loadedDef->getLogic()->setOffset(offset); 00160 } 00161 if (ok) { 00162 myResetPhases = true; 00163 return loadedDef; 00164 } else { 00165 return 0; 00166 } 00167 } 00168 00169 00170 void 00171 NIXMLTrafficLightsHandler::addTlConnection(const SUMOSAXAttributes& attrs) { 00172 bool ok = true; 00173 // parse identifying attributes 00174 NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok); 00175 NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok); 00176 if (!ok) { 00177 return; 00178 } 00179 int fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok); 00180 int toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok); 00181 if (!ok) { 00182 return; 00183 } 00184 // retrieve connection 00185 const std::vector<NBEdge::Connection> &connections = from->getConnections(); 00186 std::vector<NBEdge::Connection>::const_iterator con_it; 00187 con_it = find_if(connections.begin(), connections.end(), 00188 NBEdge::connections_finder(fromLane, to, toLane)); 00189 if (con_it == connections.end()) { 00190 WRITE_ERROR("Connection from=" + from->getID() + " to=" + to->getID() + 00191 " fromLane=" + toString(fromLane) + " toLane=" + toString(toLane) + " not found"); 00192 return; 00193 } 00194 NBEdge::Connection c = *con_it; 00195 // read other attributes 00196 std::string tlID = attrs.getOptStringReporting(SUMO_ATTR_TLID, 0, ok, ""); 00197 if (tlID == "") { 00198 // we are updating an existing connection 00199 tlID = c.tlID; 00200 assert(tlID != ""); 00201 } 00202 int tlIndex = attrs.getOptIntReporting(SUMO_ATTR_TLLINKINDEX, 0, ok, -1); 00203 if (tlIndex == -1) { 00204 // we are updating an existing connection 00205 tlIndex = c.tlLinkNo; 00206 } 00207 00208 // register the connection with all definitions 00209 const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID); 00210 if (programs.size() > 0) { 00211 std::map<std::string, NBTrafficLightDefinition*>::const_iterator it; 00212 for (it = programs.begin(); it!= programs.end(); it++) { 00213 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second); 00214 if (tlDef) { 00215 tlDef->addConnection(from, c.toEdge, c.fromLane, c.toLane, tlIndex); 00216 } else { 00217 throw ProcessError("Corrupt traffic light definition '" 00218 + tlID + "' (program '" + it->first + "')"); 00219 } 00220 } 00221 } else { 00222 WRITE_ERROR("The traffic light '" + tlID + "' is not known."); 00223 } 00224 } 00225 00226 00227 void 00228 NIXMLTrafficLightsHandler::removeTlConnection(const SUMOSAXAttributes& attrs) { 00229 bool ok = true; 00230 std::string tlID = attrs.getStringReporting(SUMO_ATTR_TLID, 0, ok); 00231 // does the traffic light still exist? 00232 const std::map<std::string, NBTrafficLightDefinition*>& programs = myTLLCont.getPrograms(tlID); 00233 if (programs.size() > 0) { 00234 // parse identifying attributes 00235 NBEdge* from = retrieveEdge(attrs, SUMO_ATTR_FROM, ok); 00236 NBEdge* to = retrieveEdge(attrs, SUMO_ATTR_TO, ok); 00237 if (!ok) { 00238 return; 00239 } 00240 int fromLane = retrieveLaneIndex(attrs, SUMO_ATTR_FROM_LANE, from, ok); 00241 int toLane = retrieveLaneIndex(attrs, SUMO_ATTR_TO_LANE, to, ok); 00242 if (!ok) { 00243 return; 00244 } 00245 int tlIndex = attrs.getIntReporting(SUMO_ATTR_TLLINKINDEX, 0, ok); 00246 00247 NBConnection conn(from, fromLane, to, toLane, tlIndex); 00248 // remove the connection from all definitions 00249 std::map<std::string, NBTrafficLightDefinition*>::const_iterator it; 00250 for (it = programs.begin(); it!= programs.end(); it++) { 00251 NBLoadedSUMOTLDef* tlDef = dynamic_cast<NBLoadedSUMOTLDef*>(it->second); 00252 if (tlDef) { 00253 tlDef->removeConnection(conn, false); 00254 } else { 00255 throw ProcessError("Corrupt traffic light definition '" 00256 + tlID + "' (program '" + it->first + "')"); 00257 } 00258 } 00259 } 00260 } 00261 00262 00263 NBEdge* 00264 NIXMLTrafficLightsHandler::retrieveEdge( 00265 const SUMOSAXAttributes& attrs, SumoXMLAttr attr, bool& ok) { 00266 std::string edgeID = attrs.getStringReporting(attr, 0, ok); 00267 NBEdge* edge = myEdgeCont.retrieve(edgeID, true); 00268 if (edge == 0) { 00269 WRITE_ERROR("Unknown edge '" + edgeID + "' given in connection."); 00270 ok = false; 00271 } 00272 return edge; 00273 } 00274 00275 00276 int 00277 NIXMLTrafficLightsHandler::retrieveLaneIndex( 00278 const SUMOSAXAttributes& attrs, SumoXMLAttr attr, NBEdge* edge, bool& ok) { 00279 int laneIndex = attrs.getIntReporting(attr, 0, ok); 00280 if (edge->getNumLanes()<=(size_t) laneIndex) { 00281 WRITE_ERROR("Invalid lane index '" + toString(laneIndex) + "' for edge '" + edge->getID() + "'."); 00282 ok = false; 00283 } 00284 return laneIndex; 00285 } 00286 00287 00288 /****************************************************************************/ 00289