SUMO - Simulation of Urban MObility

NIXMLConnectionsHandler.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Importer for edge connections 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 "NIXMLConnectionsHandler.h"
00037 #include <netbuild/NBEdge.h>
00038 #include <netbuild/NBEdgeCont.h>
00039 #include <netbuild/NBNode.h>
00040 #include <utils/common/StringTokenizer.h>
00041 #include <utils/xml/SUMOSAXHandler.h>
00042 #include <utils/xml/SUMOXMLDefinitions.h>
00043 #include <utils/common/ToString.h>
00044 #include <utils/common/TplConvert.h>
00045 #include <utils/common/TplConvertSec.h>
00046 #include <utils/common/UtilExceptions.h>
00047 #include <utils/common/MsgHandler.h>
00048 #include <utils/options/OptionsCont.h>
00049 
00050 #ifdef CHECK_MEMORY_LEAKS
00051 #include <foreign/nvwa/debug_new.h>
00052 #endif // CHECK_MEMORY_LEAKS
00053 
00054 
00055 // ===========================================================================
00056 // method definitions
00057 // ===========================================================================
00058 NIXMLConnectionsHandler::NIXMLConnectionsHandler(NBEdgeCont& ec) throw() :
00059     SUMOSAXHandler("xml-connection-description"),
00060     myEdgeCont(ec),
00061     myHaveWarnedAboutDeprecatedLanes(false),
00062     myErrorMsgHandler(OptionsCont::getOptions().getBool("ignore-errors.connections") ?
00063                       MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()) {}
00064 
00065 
00066 NIXMLConnectionsHandler::~NIXMLConnectionsHandler() throw() {}
00067 
00068 
00069 void
00070 NIXMLConnectionsHandler::myStartElement(int element,
00071                                         const SUMOSAXAttributes& attrs) throw(ProcessError) {
00072     if (element==SUMO_TAG_RESET) {
00073         bool ok = true;
00074         std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, 0, ok);
00075         std::string to = attrs.getStringReporting(SUMO_ATTR_TO, 0, ok);
00076         if (!ok) {
00077             return;
00078         }
00079         // these connections were removed when the edge was deleted
00080         if (myEdgeCont.wasRemoved(from) || myEdgeCont.wasRemoved(to)) {
00081             return;
00082         }
00083         NBEdge* fromEdge = myEdgeCont.retrieve(from);
00084         NBEdge* toEdge = myEdgeCont.retrieve(to);
00085         if (fromEdge==0) {
00086             myErrorMsgHandler->inform("The connection-source edge '" + from + "' to reset is not known.");
00087             return;
00088         }
00089         if (toEdge==0) {
00090             myErrorMsgHandler->inform("The connection-destination edge '" + to + "' to reset is not known.");
00091             return;
00092         }
00093         if (!fromEdge->isConnectedTo(toEdge)) {
00094             WRITE_WARNING("Target edge '" + toEdge->getID() + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
00095             return;
00096         }
00097         int fromLane = -1; // Assume all lanes are to be reset.
00098         int toLane = -1;
00099         if (attrs.hasAttribute(SUMO_ATTR_LANE)
00100                 || attrs.hasAttribute(SUMO_ATTR_FROM_LANE)
00101                 || attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
00102             if (!parseLaneInfo(attrs, fromEdge, toEdge, &fromLane, &toLane)) {
00103                 return;
00104             }
00105             // we could be trying to reset a connection loaded from a sumo net and which has become obsolete.
00106             // In this case it's ok to encounter invalid lance indices
00107             if (!fromEdge->hasConnectionTo(toEdge, toLane)) {
00108                 WRITE_WARNING("Target lane '" + toEdge->getLaneID(toLane) + "' is not connected with '" + fromEdge->getID() + "'; the connection cannot be reset.");
00109             }
00110         }
00111         fromEdge->removeFromConnections(toEdge, fromLane, toLane);
00112     }
00113 
00114     if (element==SUMO_TAG_CONNECTION) {
00115         bool ok = true;
00116         std::string from = attrs.getStringReporting(SUMO_ATTR_FROM, "connection", ok);
00117         std::string to = attrs.getOptStringReporting(SUMO_ATTR_TO, "connection", ok, "");
00118         if (!ok || myEdgeCont.wasIgnored(from) || myEdgeCont.wasIgnored(to)) {
00119             return;
00120         }
00121         // extract edges
00122         NBEdge* fromEdge = myEdgeCont.retrieve(from);
00123         NBEdge* toEdge = to.length()!=0 ? myEdgeCont.retrieve(to) : 0;
00124         // check whether they are valid
00125         if (fromEdge==0) {
00126             myErrorMsgHandler->inform("The connection-source edge '" + from + "' is not known.");
00127             return;
00128         }
00129         if (toEdge==0 && to.length()!=0) {
00130             myErrorMsgHandler->inform("The connection-destination edge '" + to + "' is not known.");
00131             return;
00132         }
00133         // parse optional lane information
00134         if (attrs.hasAttribute(SUMO_ATTR_LANE)||attrs.hasAttribute(SUMO_ATTR_FROM_LANE)||attrs.hasAttribute(SUMO_ATTR_TO_LANE)) {
00135             parseLaneBound(attrs, fromEdge, toEdge);
00136         } else {
00137             fromEdge->addEdge2EdgeConnection(toEdge);
00138         }
00139     }
00140     if (element==SUMO_TAG_PROHIBITION) {
00141         bool ok = true;
00142         std::string prohibitor = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITOR, 0, ok, "");
00143         std::string prohibited = attrs.getOptStringReporting(SUMO_ATTR_PROHIBITED, 0, ok, "");
00144         if (!ok) {
00145             return;
00146         }
00147         NBConnection prohibitorC = parseConnection("prohibitor", prohibitor);
00148         NBConnection prohibitedC = parseConnection("prohibited", prohibited);
00149         if (prohibitorC.getFrom()==0||prohibitedC.getFrom()==0) {
00150             // something failed
00151             return;
00152         }
00153         NBNode* n = prohibitorC.getFrom()->getToNode();
00154         n->addSortedLinkFoes(prohibitorC, prohibitedC);
00155     }
00156 }
00157 
00158 
00159 NBConnection
00160 NIXMLConnectionsHandler::parseConnection(const std::string& defRole, const std::string& def) throw() {
00161     // split from/to
00162     size_t div = def.find("->");
00163     if (div==std::string::npos) {
00164         myErrorMsgHandler->inform("Missing connection divider in " + defRole + " '" + def + "'");
00165         return NBConnection(0, 0);
00166     }
00167     std::string fromDef = def.substr(0, div);
00168     std::string toDef = def.substr(div+2);
00169 
00170     // retrieve the edges
00171     // check whether the definition includes a lane information (do not process it)
00172     if (fromDef.find('_')!=std::string::npos) {
00173         fromDef = fromDef.substr(0, fromDef.find('_'));
00174     }
00175     if (toDef.find('_')!=std::string::npos) {
00176         toDef = toDef.substr(0, toDef.find('_'));
00177     }
00178     // retrieve them now
00179     NBEdge* fromE = myEdgeCont.retrieve(fromDef);
00180     NBEdge* toE = myEdgeCont.retrieve(toDef);
00181     // check
00182     if (fromE==0) {
00183         myErrorMsgHandler->inform("Could not find edge '" + fromDef + "' in " + defRole + " '" + def + "'");
00184         return NBConnection(0, 0);
00185     }
00186     if (toE==0) {
00187         myErrorMsgHandler->inform("Could not find edge '" + toDef + "' in " + defRole + " '" + def + "'");
00188         return NBConnection(0, 0);
00189     }
00190     return NBConnection(fromE, toE);
00191 }
00192 
00193 
00194 void
00195 NIXMLConnectionsHandler::parseLaneBound(const SUMOSAXAttributes& attrs, NBEdge* from, NBEdge* to) throw() {
00196     if (to==0) {
00197         // do nothing if it's a dead end
00198         return;
00199     }
00200     bool ok = true;
00201     const bool mayDefinitelyPass = attrs.getOptBoolReporting(SUMO_ATTR_PASS, 0, ok, false);
00202     if (!ok) {
00203         return;
00204     }
00205     // get the begin and the end lane
00206     int fromLane;
00207     int toLane;
00208     try {
00209         if (!parseLaneInfo(attrs, from, to, &fromLane, &toLane)) {
00210             return;
00211         }
00212         if (!validateLaneInfo(false /* canLanesBeNegative */, from, to, fromLane, toLane)) {
00213             return;
00214         }
00215         if (from->hasConnectionTo(to, toLane)) {
00216             WRITE_WARNING("Target lane '" + to->getLaneID(toLane) + "' is already connected from '" + from->getID() + "'.");
00217         }
00218         if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, true, mayDefinitelyPass)) {
00219             NBEdge* nFrom = from;
00220             bool toNext = true;
00221             do {
00222                 if (nFrom->getToNode()->getOutgoingEdges().size()!=1) {
00223                     toNext = false;
00224                     break;
00225                 }
00226                 NBEdge* t = nFrom->getToNode()->getOutgoingEdges()[0];
00227                 if (t->getID().substr(0, t->getID().find('/'))!=nFrom->getID().substr(0, nFrom->getID().find('/'))) {
00228                     toNext = false;
00229                     break;
00230                 }
00231                 if (toNext) {
00232                     nFrom = t;
00233                 }
00234             } while (toNext);
00235             if (nFrom==0||!nFrom->addLane2LaneConnection(fromLane, to, toLane, NBEdge::L2L_USER, false, mayDefinitelyPass)) {
00236                 WRITE_WARNING("Could not set loaded connection from '" + from->getLaneID(fromLane) +
00237                               "' to '" + to->getLaneID(toLane) + "'.");
00238             } else {
00239                 from = nFrom;
00240             }
00241         }
00242     } catch (NumberFormatException&) {
00243         myErrorMsgHandler->inform("At least one of the defined lanes was not numeric");
00244     }
00245     //
00246     bool keepUncontrolled = attrs.getOptBoolReporting(SUMO_ATTR_UNCONTROLLED, 0, ok, false);
00247     if (keepUncontrolled) {
00248         from->disableConnection4TLS(fromLane, to, toLane);
00249     }
00250 }
00251 
00252 bool
00253 NIXMLConnectionsHandler::parseLaneInfo(const SUMOSAXAttributes& attributes, NBEdge* fromEdge, NBEdge* toEdge,
00254                                        int* fromLane, int* toLane) {
00255     if (attributes.hasAttribute(SUMO_ATTR_LANE)) {
00256         return parseDeprecatedLaneDefinition(attributes, fromEdge, toEdge, fromLane, toLane);
00257     } else {
00258         return parseLaneDefinition(attributes, fromLane, toLane);
00259     }
00260 }
00261 
00262 
00263 inline bool
00264 NIXMLConnectionsHandler::parseDeprecatedLaneDefinition(const SUMOSAXAttributes& attributes,
00265         NBEdge* from, NBEdge* to,
00266         int* fromLane, int* toLane) {
00267     bool ok = true;
00268     if (!myHaveWarnedAboutDeprecatedLanes) {
00269         myHaveWarnedAboutDeprecatedLanes = true;
00270         WRITE_WARNING("'" + toString(SUMO_ATTR_LANE) + "' is deprecated, please use '" +
00271                       toString(SUMO_ATTR_FROM_LANE) + "' and '" + toString(SUMO_ATTR_TO_LANE) +
00272                       "' instead.");
00273     }
00274 
00275     std::string laneConn = attributes.getStringReporting(SUMO_ATTR_LANE, 0, ok);
00276     StringTokenizer st(laneConn, ':');
00277     if (!ok || st.size()!=2) {
00278         myErrorMsgHandler->inform("Invalid lane to lane connection from '" +
00279                                   from->getID() + "' to '" + to->getID() + "'.");
00280         return false; // There was an error.
00281     }
00282 
00283     *fromLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1);
00284     *toLane = TplConvertSec<char>::_2intSec(st.next().c_str(), -1);
00285 
00286     return true; // We succeeded.
00287 }
00288 
00289 
00290 inline bool
00291 NIXMLConnectionsHandler::parseLaneDefinition(const SUMOSAXAttributes& attributes,
00292         int* fromLane,
00293         int* toLane) {
00294     bool ok = true;
00295     *fromLane = attributes.getIntReporting(SUMO_ATTR_FROM_LANE, 0, ok);
00296     *toLane = attributes.getIntReporting(SUMO_ATTR_TO_LANE, 0, ok);
00297     return ok;
00298 }
00299 
00300 
00301 bool
00302 NIXMLConnectionsHandler::validateLaneInfo(bool canLanesBeNegative, NBEdge* fromEdge, NBEdge* toEdge, int fromLane, int toLane) {
00303     if ((!canLanesBeNegative && fromLane<0) ||
00304             static_cast<unsigned int>(fromLane)>=fromEdge->getNumLanes()) {
00305         myErrorMsgHandler->inform("Invalid value '" + toString(fromLane) +
00306                                   "' for " + toString(SUMO_ATTR_FROM_LANE) + " in connection from '" +
00307                                   fromEdge->getID() + "' to '" + toEdge->getID() + "'.");
00308         return false;
00309     }
00310     if ((!canLanesBeNegative && toLane<0) ||
00311             static_cast<unsigned int>(toLane)>=toEdge->getNumLanes()) {
00312         myErrorMsgHandler->inform("Invalid value '" + toString(toLane) +
00313                                   "' for " + toString(SUMO_ATTR_TO_LANE) + " in connection from '" +
00314                                   fromEdge->getID() + "' to '" + toEdge->getID() + "'.");
00315         return false;
00316     }
00317     return true;
00318 }
00319 
00320 /****************************************************************************/
00321 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines