Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[sumo-user] Problem with implementing a new car following model

Greetings,

I am trying to implement a car-following model (General Motors model) to SUMO. I've successfully downloaded the developer version and compiled (built) the code on windows.

However, I am having some trouble with the implementation of a car-following model. I've followed and completed every step in the guide at the documentation ( https://sumo.dlr.de/docs/Developer/How_To/Car-Following_Model.html). My main issue occurs at the "MSVehicleType.cpp" when I try to compile again. According to the documentation, I need to add the following to the "MSVehicleType.cpp" ;

        case SUMO_TAG_CF_GM:
            model = new MSCFModel_GM(vtype,
                from.get(SUMO_ATTR_GM_Alpha,1.),
                from.get(SUMO_ATTR_GM_M, 1.),
                from.get(SUMO_ATTR_GM_L, 1.));
            break ;

However, when I try to compile the code again, the "from.get" command does not work and build fails around step 390-400 with the following errors;
  • 'get': is not a member of 'SUMOVTypeParameter'7
  • model : undeclared identifier
I have tried the following as well, which is the current format for the car-following models already existing inside the MSVehicleType.cpp

        case SUMO_TAG_CF_GM:
            vtype->myCarFollowModel = new MSCFModel_GM(vtype,
                from.getCFParam(SUMO_ATTR_GM_Alpha,1.),
                from.getCFParam(SUMO_ATTR_GM_M, 1.),
                from.getCFParam(SUMO_ATTR_GM_L, 1.));
            break ;

When I compile this I get the error that "no overloaded function takes 4 arguments.

Another version I've tried

        case SUMO_TAG_CF_GM:
            vtype->myCarFollowModel = new MSCFModel_GM(vtype)
             break ;

At this version, compile procedure successfully runs to the step 740 but fails with an error message as follows :

[740/1025] C:\PROGRA~2\MICROS~3\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\cl.exe  /nologo /TP -DFLOAT_MATH_FUNCTIONS -IC:\SUMOLibraries\googletest-1.10.0\include -Isrc -I..\..\..\src -IC:\SUMOLibraries\xerces-c-3.2.3\include -IC:\SUMOLibraries\proj-7.2.0\include -IC:\SUMOLibraries\fox-1.6.57\include -IC:\SUMOLibraries\freetype-2.10.4\include\freetype2 -IC:\SUMOLibraries\3rdPartyLibs\zlib-1.2.11\include -IC:\SUMOLibraries\gdal-3.2.1\include -IC:\SUMOLibraries\FFMPEG-4.2.0\include -IC:\SUMOLibraries\OSG-3.6.5\include -IC:\SUMOLibraries\gl2ps-1.4.0\include -IC:\SUMOLibraries\eigen-3.3.9 /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MP /bigobj /MD /O2 /Ob2 /DNDEBUG /showIncludes /Fosrc\utils\gui\images\CMakeFiles\utils_gui_images.dir\GUIIconSubSys.cpp.obj /Fdsrc\utils\gui\images\CMakeFiles\utils_gui_images.dir\utils_gui_images.pdb /FS -c ..\..\..\src\utils\gui\images\GUIIconSubSys.cpp
  [741/1025] cmd.exe /C "cd /D C:\Users\l\source\repos\sumo\out\build\x64-Release\src\libsumo && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E make_directory C:/Users/source/repos/sumo/tools/libsumo C:/Users//source/repos/sumo/out/build/x64-Release/src/libsumo && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env SWIG_LIB=C:/SUMOLibraries/swigwin-4.0.2/Lib C:/SUMOLibraries/swigwin-4.0.2/swig.exe -python -keyword -outdir C:/Users/source/repos/sumo/tools/libsumo -c++ -interface _libsumo -IC:/SUMOLibraries/googletest-1.10.0/include -IC:/SUMOLibraries/xerces-c-3.2.3/include -IC:/SUMOLibraries/proj-7.2.0/include -IC:/SUMOLibraries/fox-1.6.57/include -IC:/SUMOLibraries/freetype-2.10.4/include/freetype2 -IC:/SUMOLibraries/3rdPartyLibs/zlib-1.2.11/include -IC:/SUMOLibraries/gdal-3.2.1/include -IC:/SUMOLibraries/FFMPEG-4.2.0/include -IC:/SUMOLibraries/OSG-3.6.5/include -IC:/SUMOLibraries/gl2ps-1.4.0/include -IC:/SUMOLibraries/eigen-3.3.9 -IC:/Users/source/repos/sumo/out/build/x64-Release/src -IC:/Users/source/repos/sumo/src -IC:/Users/anaconda3/include -o C:/Users/source/repos/sumo/out/build/x64-Release/src/libsumo/libsumoPYTHON_wrap.cxx C:/Users/source/repos/sumo/src/libsumo/libsumo.i"
  ninja: build stopped: subcommand failed.


Another common error I get at is the following:

Severity Code Description Project File Line Suppression State Detail Description
Error (active) E0289 no instance of constructor "MSCFModel_GM::MSCFModel_GM" matches the argument list microsim.lib (src\microsim\microsim.lib) - x64-Release C:\Users\sadul\source\repos\sumo\src\microsim\MSVehicleType.cpp 356            argument types are: (MSVehicleType *, double, double, double)


Sorry for the long e-mail but I would really appreciate any help. You can find the code files in the attachment as well.

Best Regards,
Sadullah.
/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2001-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    MSCFModel_GM.cpp
/// @author  Sadullah Göncü
/// @author  
/// @author  
/// @author  
/// @author  
/// @date    Friday, 22 October 2021
///
// The original General Motors (1958) car-following model and parameter
/****************************************************************************/
#include <config.h>

#include <microsim/MSVehicle.h>
#include <microsim/MSLane.h>
#include "MSCFModel_GM.h"
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
#include <utils/common/RandHelper.h>
#include <microsim/MSGlobals.h>

// ===========================================================================
// DEBUG constants
// ===========================================================================
//#define DEBUG_COND (veh->getID()=="disabled")

// ===========================================================================
// method definitions
// ===========================================================================
MSCFModel_GM::MSCFModel_GM(const MSVehicleType* vtype) :
    MSCFModel(vtype),
    myalpha(vtype->getParameter().getCFParam(SUMO_ATTR_GM_Alpha, 1)), // This is the sensitivity parameter, default value is set to 1
    myM(vtype->getParameter().getCFParam(SUMO_ATTR_GM_M, -2)), // This is the speed exponent, takes values between -2 to +2
    myL(vtype->getParameter().getCFParam(SUMO_ATTR_GM_L, 4)), // This is the distance headway exponent, takes values between +4 to -1
    myTauDecel(myDecel* myHeadwayTime) {


}

MSCFModel_GM::~MSCFModel_GM() {}


double
MSCFModel_GM::finalizeSpeed(MSVehicle* const veh, double vPos) const {
    const double vNext = MSCFModel::finalizeSpeed(veh, vPos);
    VehicleVariables* vars = (VehicleVariables*)veh->getCarFollowVariables();
    vars->rand = RandHelper::rand(veh->getRNG());
    return vNext;
}


double
MSCFModel_GM::followSpeed(const MSVehicle* const veh, double speed, double gap, double predSpeed, double /*predMaxDecel*/, const MSVehicle* const /*pred*/) const {
    return MIN2(_v(veh, speed, maxNextSpeed(speed, veh), gap, predSpeed), maxNextSpeed(speed, veh));
}


double
MSCFModel_GM::stopSpeed(const MSVehicle* const veh, const double speed, double gap, double /*decel*/) const {
    return MIN2(_v(veh, speed, maxNextSpeed(speed, veh), gap, 0), maxNextSpeed(speed, veh));
}


MSCFModel::VehicleVariables*
MSCFModel_GM::createVehicleVariables() const {
    VehicleVariables* ret = new VehicleVariables();
    /// XXX should use egoVehicle->getRNG()
    ret->rand = RandHelper::rand();
    return ret;
}

double
MSCFModel_GM::_v(const MSVehicle* const veh, double speed, double vfree, double gap, double predSpeed) const {
    if (predSpeed == 0 && gap < 0.01) {
        return 0;
    }
    // !!! in the following, the prior step is not considered!!!
    double GM_acc = MAX2((double)(myalpha * pow(predSpeed, myM) / pow(gap, myL)) * (speed - predSpeed), (double)0);
    double vsafe = (double)(speed + ACCEL2SPEED(GM_acc));

    double v = MAX2((double)0, MIN2(vfree, vsafe));
    return v;
}


MSCFModel*
MSCFModel_GM::duplicate(const MSVehicleType* vtype) const {
    return new MSCFModel_GM(vtype);
}

/****************************************************************************/
/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2001-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    MSCFModel_GM.h
/// @author  Sadullah Göncü
/// 
/// 
/// 
/// @date    Friday, 22 October 2021
///
// The original General Motors (1958) car-following model and parameter
/****************************************************************************/
#pragma once
#include <config.h>

#include "MSCFModel.h"
#include <utils/xml/SUMOXMLDefinitions.h>


// ===========================================================================
// class definitions
// ===========================================================================
/** @class MSCFModel_GM
 * @brief The General Motors (1958) car-following model and parameter
 * @see MSCFModel
 */
class MSCFModel_GM : public MSCFModel {
public:
    /** @brief Constructor
     *  @param[in] vtype the type for which this model is built and also the parameter object to configure this model
     */
    MSCFModel_GM(const MSVehicleType* vtype);


    /// @brief Destructor
    ~MSCFModel_GM();


    /// @name Implementations of the MSCFModel interface
    /// @{
    /// @brief apply dawdling
    double finalizeSpeed(MSVehicle* const veh, double vPos) const;

    /** @brief Computes the vehicle's safe speed (no dawdling)
     * @param[in] veh The vehicle (EGO)
     * @param[in] speed The vehicle's speed
     * @param[in] gap2pred The (netto) distance to the LEADER
     * @param[in] predSpeed The speed of LEADER
     * @return EGO's safe speed
     * @see MSCFModel::ffeV
     */
    double followSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const pred = 0) const;


    /** @brief Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
     * @param[in] veh The vehicle (EGO)
     * @param[in] gap2pred The (netto) distance to the the obstacle
     * @return EGO's safe speed for approaching a non-moving obstacle
     * @see MSCFModel::ffeS
     * @todo generic Interface, models can call for the values they need
     */
    virtual double stopSpeed(const MSVehicle* const veh, const double speed, double gap2pred, double decel) const;


    /** @brief Returns the model's name
     * @return The model's name
     * @see MSCFModel::getModelName
     */
    virtual int getModelID() const {
        return SUMO_TAG_CF_GM ;
    }


    /** @brief Get the driver's imperfection
     * @return The imperfection of drivers of this class
     */
    double getImperfection() const {
        return myDawdle;
    }
    /// @}

private:
    class VehicleVariables : public MSCFModel::VehicleVariables {
    public:
        double rand;
    };

    /** @brief Returns the "safe" velocity
     * @param[in] gap2pred The (netto) distance to the LEADER
     * @param[in] predSpeed The LEADER's speed
     * @return the safe velocity
     */
    double _v(const MSVehicle* const veh, double speed, double vfree, double gap, double predSpeed) const;




    /// @name Setter methods
    /// @{
    /** @brief Sets a new value for maximum deceleration [m/s^2]
     * @param[in] accel The new deceleration in m/s^2
     */
    void setMaxDecel(double decel) {
        myDecel = decel;
        myTauDecel = myDecel * myHeadwayTime;
    }


    /** @brief Sets a new value for driver imperfection
     * @param[in] accel The new driver imperfection
     */
    void setImperfection(double imperfection) {
        myDawdle = imperfection;
    }


    /** @brief Sets a new value for desired headway [s]
     * @param[in] headwayTime The new desired headway (in s)
     */
    void setHeadwayTime(double headwayTime) {
        myHeadwayTime = headwayTime;
        myTauDecel = myDecel * headwayTime;
    }
    /// @}


    /** @brief Duplicates the car-following model
     * @param[in] vtype The vehicle type this model belongs to (1:1)
     * @return A duplicate of this car-following model
     */
    virtual MSCFModel* duplicate(const MSVehicleType* vtype) const;


    MSCFModel::VehicleVariables* createVehicleVariables() const;
protected:
    /** @brief Returns the "safe" velocity
     * @param[in] gap2pred The (netto) distance to the LEADER
     * @param[in] predSpeed The LEADER's speed
     * @param[in] predMaxDecel The LEADER's maximum deceleration
     * @return the safe velocity
     */
    virtual double vsafe(double gap, double predSpeed, double predMaxDecel) const;


    /** @brief Applies driver imperfection (dawdling / sigma)
     * @param[in] speed The speed with no dawdling
     * @return The speed after dawdling
     */
    virtual double dawdle(double speed, SumoRNG* rng) const;

protected:
    /// @brief The vehicle's dawdle-parameter. 0 for no dawdling, 1 for max.
    double myDawdle;

    /// @brief The precomputed value for myDecel*myTau
    double myTauDecel;


private:
    /// @name model parameter
    /// @{
    /// @brief General Motors sensitivity
    double myalpha;

    /// @brief General Motors speed exponent
    double myM;

    /// @brief General Motors Distance Headway Exponent
    double myL;
    /// @}
};


/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2001-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    MSVehicleType.h
/// @author  Christian Roessel
/// @author  Daniel Krajzewicz
/// @author  Jakob Erdmann
/// @author  Michael Behrisch
/// @date    Mon, 12 Mar 2001
///
// The car-following model and parameter
/****************************************************************************/
#pragma once
#include <config.h>

#include <cassert>
#include <map>
#include <string>
#include <microsim/cfmodels/MSCFModel.h>
#include <utils/common/SUMOTime.h>
#include <utils/common/StdDefs.h>
#include <utils/common/SUMOVehicleClass.h>
#include <utils/common/RandHelper.h>
#include <utils/vehicle/SUMOVTypeParameter.h>
#include <utils/common/RGBColor.h>


// ===========================================================================
// class declarations
// ===========================================================================
class MSLane;
class MSCFModel;
class SUMOVTypeParameter;


// ===========================================================================
// class definitions
// ===========================================================================
/**
 * @class MSVehicleType
 * @brief The car-following model and parameter
 *
 * MSVehicleType stores the parameter of a single vehicle type and methods
 *  that use these for computing the vehicle's car-following behavior
 *
 * It is assumed that within the simulation many vehicles are using the same
 *  vehicle type, quite common is using only one vehicle type for all vehicles.
 *
 * You can think of it like of having a vehicle type for each VW Golf or
 *  Ford Mustang in your simulation while the car instances just refer to it.
 */
class MSVehicleType {
public:
    /** @brief Constructor.
     *
     * @param[in] parameter The vehicle type's parameter
     */
    MSVehicleType(const SUMOVTypeParameter& parameter);


    /// @brief Destructor
    virtual ~MSVehicleType();


    /** @brief Returns whether the given parameter was set
     * @param[in] what The parameter which one asks for
     * @return Whether the given parameter was set
     */
    bool wasSet(int what) const {
        return (myParameter.parametersSet & what) != 0;
    }


    /// @name Atomar getter for simulation
    /// @{

    /** @brief Returns the name of the vehicle type
     * @return This type's id
     */
    const std::string& getID() const {
        return myParameter.id;
    }


    /** @brief Returns the running index of the vehicle type
     * @return This type's numerical id
     */
    int getNumericalID() const {
        return myIndex;
    }


    /** @brief Get vehicle's length [m]
     * @return The length vehicles of this type have in m
     */
    double getLength() const {
        return myParameter.length;
    }


    /** @brief Get vehicle's length including the minimum gap [m]
     * @return The length vehicles of this type have (including the minimum gap in m
     */
    double getLengthWithGap() const {
        return myParameter.length + myParameter.minGap;
    }


    /** @brief Get the free space in front of vehicles of this class
     * @return The place before the vehicle
     */
    double getMinGap() const {
        return myParameter.minGap;
    }

    /** @brief Get the minimum lateral gap that vehicles of this type maintain
     * @return The place before the vehicle
     */
    double getMinGapLat() const {
        return myParameter.minGapLat;
    }


    /** @brief Returns the vehicle type's car following model definition (const version)
     * @return The vehicle type's car following model definition
     */
    inline const MSCFModel& getCarFollowModel() const {
        return *myCarFollowModel;
    }


    /** @brief Returns the vehicle type's car following model definition (non-const version)
     * @return The vehicle type's car following model definition
     */
    inline MSCFModel& getCarFollowModel() {
        return *myCarFollowModel;
    }


    inline LaneChangeModel getLaneChangeModel() const {
        return myParameter.lcModel;
    }


    /** @brief Get vehicle's maximum speed [m/s].
     * @return The maximum speed (in m/s) of vehicles of this class
     */
    double getMaxSpeed() const {
        return myParameter.maxSpeed;
    }


    /** @brief Computes and returns the speed deviation
     * @return A new, random speed deviation
     */
    double computeChosenSpeedDeviation(SumoRNG* rng, const double minDev = -1.) const;


    /** @brief Get the default probability of this vehicle type
     * @return The probability to use this type
     */
    double getDefaultProbability() const {
        return myParameter.defaultProbability;
    }


    /** @brief Get this vehicle type's vehicle class
     * @return The class of this vehicle type
     * @see SUMOVehicleClass
     */
    SUMOVehicleClass getVehicleClass() const {
        return myParameter.vehicleClass;
    }


    /** @brief Get this vehicle type's emission class
     * @return The emission class of this vehicle type
     * @see SUMOEmissionClass
     */
    SUMOEmissionClass getEmissionClass() const {
        return myParameter.emissionClass;
    }


    /** @brief Returns this type's color
     * @return The color of this type
     */
    const RGBColor& getColor() const {
        return myParameter.color;
    }


    /** @brief Returns this type's speed factor
     * @return The speed factor of this type
     */
    const Distribution_Parameterized& getSpeedFactor() const {
        return myParameter.speedFactor;
    }


    /** @brief Returns this type's default action step length
     * @return The default action step length of this type (in ms.)
     */
    SUMOTime getActionStepLength() const {
        return myParameter.actionStepLength;
    }


    /** @brief Returns this type's default action step length in seconds
     * @return The default action step length of this type (in s.)
     */
    double getActionStepLengthSecs() const {
        return myCachedActionStepLengthSecs;
    }


    /** @brief Returns this type's impatience
     * @return The impatience of this type
     */
    double getImpatience() const {
        return myParameter.impatience;
    }
    /// @}



    /// @name Atomar getter for visualization
    /// @{

    /** @brief Get the width which vehicles of this class shall have when being drawn
     * @return The width of this type's vehicles
     */
    double getWidth() const {
        return myParameter.width;
    }

    /** @brief Get the height which vehicles of this class shall have when being drawn
     * @return The height of this type's vehicles
     */
    double getHeight() const {
        return myParameter.height;
    }

    /** @brief Get this vehicle type's shape
     * @return The shape of this vehicle type
     * @see SUMOVehicleShape
     */
    SUMOVehicleShape getGuiShape() const {
        return myParameter.shape;
    }

    /** @brief Get this vehicle type's 3D model file name
     * @return The model file name of this vehicle type
     */
    std::string getOSGFile() const {
        return myParameter.osgFile;
    }


    /** @brief Get this vehicle type's raster model file name
     * @return The raster file name of this vehicle type
     */
    std::string getImgFile() const {
        return myParameter.imgFile;
    }


    /** @brief Get this vehicle type's person capacity
     * @return The person capacity of this vehicle type
     */
    int getPersonCapacity() const {
        return myParameter.personCapacity;
    }


    /** @brief Get this vehicle type's container capacity
     * @return The container capacity of this vehicle type
     */
    int getContainerCapacity() const {
        return myParameter.containerCapacity;
    }

    /** @brief Get this vehicle type's boarding duration
     * @return The time a person needs to board a vehicle of this type
     */
    SUMOTime getBoardingDuration() const {
        return myParameter.boardingDuration;
    }

    /** @brief Get this vehicle type's loading duration
     * @return The time a container needs to get laoded on a vehicle of this type
     */
    SUMOTime getLoadingDuration() const {
        return myParameter.loadingDuration;
    }

    /** @brief Get vehicle's maximum lateral speed [m/s].
     * @return The maximum lateral speed (in m/s) of vehicles of this class
     */
    double getMaxSpeedLat() const {
        return myParameter.maxSpeedLat;
    }

    /** @brief Get vehicle's preferred lateral alignment procedure
     * @return The vehicle's preferred lateral alignment procedure
     */
    const LatAlignmentDefinition& getPreferredLateralAlignment() const {
        return myParameter.latAlignmentProcedure;
    }

    /** @brief Get vehicle's preferred lateral alignment offset (in m from center line)
     * @return The vehicle's preferred lateral alignment offset
     */
    double getPreferredLateralAlignmentOffset() const {
        return myParameter.latAlignmentOffset;
    }

    /// @brief Get offset of first seat from vehicle front
    double getFrontSeatPos() const {
        return myParameter.frontSeatPos;
    }
    /// @}


    /// @name Setter methods
    /// @{

    /** @brief Set a new value for this type's acceleration.
     * @param[in] accel The new acceleration of this type
     */
    void setAccel(double accel);

    /** @brief Set a new value for this type's deceleration.
     * @param[in] decel The new deceleration of this type
     */
    void setDecel(double decel);

    /** @brief Set a new value for this type's emergency deceleration.
     * @param[in] emergencyDecel The new emergency deceleration of this type
     */
    void setEmergencyDecel(double emergencyDecel);

    /** @brief Set a new value for this type's apparent deceleration.
     * @param[in] apparentDecel The new apparent deceleration of this type
     */
    void setApparentDecel(double apparentDecel);

    /** @brief Set a new value for this type's imperfection.
     * @param[in] imperfection The new imperfection of this type
     */
    void setImperfection(double imperfection);

    /** @brief Set a new value for this type's headway.
     * @param[in] tau The new headway of this type
     */
    void setTau(double tau);

    /** @brief Set a new value for this type's length
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] length The new length of this type
     */
    void setLength(const double& length);


    /** @brief Set a new value for this type's height
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] height The new height of this type
     */
    void setHeight(const double& height);


    /** @brief Set a new value for this type's minimum gap
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] minGap The new minimum gap of this type
     */
    void setMinGap(const double& minGap);


    /** @brief Set a new value for this type's minimum lataral gap
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] minGapLat The new minimum lateral gap of this type
     */
    void setMinGapLat(const double& minGapLat);

    /** @brief Set a new value for this type's maximum speed
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] maxSpeed The new maximum speed of this type
     */
    void setMaxSpeed(const double& maxSpeed);

    /** @brief Set a new value for this type's maximum lateral speed
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] maxSpeedLat The new maximum lateral speed of this type
     */
    void setMaxSpeedLat(const double& maxSpeedLat);

    /** @brief Set a new value for this type's vehicle class
     * @param[in] vclass The new vehicle class of this type
     */
    void setVClass(SUMOVehicleClass vclass);


    /** @brief Set a new value for this type's default probability
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] prob The new default probability of this type
     */
    void setDefaultProbability(const double& prob);


    /** @brief Set a new value for this type's speed factor
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] factor The new speed factor of this type
     */
    void setSpeedFactor(const double& factor);


    /** @brief Set a new value for this type's speed deviation
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] dev The new speed deviation of this type
     */
    void setSpeedDeviation(const double& dev);


    /** @brief Set a new value for this type's action step length
     *
     * @param[in] actionStepLength The new action step length of this type (in ms.)
     * @param[in] resetActionOffset If True (default), the next action point is
     *            scheduled immediately. if If resetActionOffset == False, the interval
     *            between the last and the next action point is updated to match the given
     *            value for all vehicles of this type, or if the latter is smaller than the
     *            time since the last action point, the next action follows immediately.
     *
     * @note: Singular vtypes do not update the state of the corresponding vehicle, because
     *        the global lookup would be too expensive. The caller is responsible to
     *        perform the actionOffsetReset operation at caller context, where the vehicle is known.
     */
    void setActionStepLength(const SUMOTime actionStepLength, bool resetActionOffset);


    /** @brief Set a new value for this type's emission class
     * @param[in] eclass The new emission class of this type
     */
    void setEmissionClass(SUMOEmissionClass eclass);


    /** @brief Set a new value for this type's color
     * @param[in] color The new color of this type
     */
    void setColor(const RGBColor& color);


    /** @brief Set a new value for this type's width
     *
     * If the given value<0 then the one from the original type will
     *  be used.
     *
     * @param[in] width The new width of this type
     */
    void setWidth(const double& width);


    /** @brief Set a new value for this type's shape
     * @param[in] shape The new shape of this type
     */
    void setShape(SUMOVehicleShape shape);

    /** @brief Set a new value for this type's impatience
     * @param[in] impatience The new impatience of this type
     */
    void setImpatience(const double impatience);

    /** @brief Set vehicle's preferred lateral alignment
     */
    void setPreferredLateralAlignment(const LatAlignmentDefinition& latAlignment, double latAlignmentOffset = 0.0);
    /// @}



    /// @name methods for building vehicle types
    /// @{

    /** @brief Builds the microsim vehicle type described by the given parameter
     * @param[in] from The vehicle type description
     * @return The built vehicle type
     * @exception ProcessError on false values (not et used)
     */
    static MSVehicleType* build(SUMOVTypeParameter& from);

    /// @brief   Accessor function for parameter equivalent returning entry time for a specific manoeuver angle
    SUMOTime getEntryManoeuvreTime(const int angle) const;
    /// @brief   Accessor function for parameter equivalent returning exit time for a specific manoeuver angle
    SUMOTime getExitManoeuvreTime(const int angle) const;


    /** @brief Duplicates the microsim vehicle type giving the newly created type the given id,
     *         marking it as vehicle specific
     * @param[in] id The new id of the type
     * @return The built vehicle type
     * @note This method is used in case that a vType is meant to be used only for a specific vehicle
     *       The created vType will be removed with the vehicle or if it is assigned a new type.
     */
    MSVehicleType* buildSingularType(const std::string& id) const;


    /** @brief Duplicates the microsim vehicle type giving the newly created type the given id.
     *
     * @param[in] id The new id of the type
     * @param[in] persistent If true the created vType will be persistent and can be used by several vehicles,
     *            otherwise it may be removed before simulation end, @see buildSingularType()
     * @return The built vehicle type
     */
    MSVehicleType* duplicateType(const std::string& id, bool persistent) const;
    /// @}


    /** @brief Returns whether this type belongs to a single vehicle only (was modified)
     * @return Whether this vehicle type is based on a different one, and belongs to one vehicle only
     */
    bool isVehicleSpecific() const {
        return myOriginalType != nullptr;
    }


    /** @brief Returns the id of the original vehicle type if this is a vehicle specific type, the id otherwise
     * @return the original vehicle type id
     */
    const std::string& getOriginalID() const {
        return myOriginalType != nullptr ? myOriginalType->getID() : getID();
    }


    const SUMOVTypeParameter& getParameter() const {
        return myParameter;
    }

    /** @brief Checks whether vehicle type parameters may be problematic
     *         (Currently, only the value for the action step length is
     *         compared with the value for the desired headway time.)
     */
    void check();

private:
    /// @brief the parameter container
    SUMOVTypeParameter myParameter;

    /// @brief the vtypes actionsStepLength in seconds (cached because needed very often)
    double myCachedActionStepLengthSecs;

    /// @brief Indicator whether the user was already warned once about an action step length
    ///        larger than the desired time headway.
    bool myWarnedActionStepLengthTauOnce;
    bool myWarnedActionStepLengthBallisticOnce;

    /// @brief the running index
    const int myIndex;

    /// @brief instance of the car following model.
    MSCFModel* myCarFollowModel;

    /// @brief The original type
    const MSVehicleType* myOriginalType;

    /// @brief next value for the running index
    static int myNextIndex;


private:
    /// @brief Invalidated copy constructor
    MSVehicleType(const MSVehicleType&) = delete;

    /// @brief Invalidated assignment operator
    MSVehicleType& operator=(const MSVehicleType&) = delete;
};
/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2001-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    MSVehicleType.cpp
/// @author  Christian Roessel
/// @author  Daniel Krajzewicz
/// @author  Jakob Erdmann
/// @author  Thimor Bohn
/// @author  Michael Behrisch
/// @date    Tue, 06 Mar 2001
///
// The car-following model and parameter
/****************************************************************************/
#include <config.h>

#include <cassert>
#include <utils/options/OptionsCont.h>
#include <utils/common/FileHelpers.h>
#include <utils/common/RandHelper.h>
#include <utils/common/StringUtils.h>
#include <utils/vehicle/SUMOVTypeParameter.h>
#include <microsim/cfmodels/MSCFModel_Rail.h>
#include "MSNet.h"
#include "cfmodels/MSCFModel_IDM.h"
#include "cfmodels/MSCFModel_Kerner.h"
#include "cfmodels/MSCFModel_Krauss.h"
#include "cfmodels/MSCFModel_KraussOrig1.h"
#include "cfmodels/MSCFModel_KraussPS.h"
#include "cfmodels/MSCFModel_KraussX.h"
#include "cfmodels/MSCFModel_EIDM.h"
#include "cfmodels/MSCFModel_SmartSK.h"
#include "cfmodels/MSCFModel_Daniel1.h"
#include "cfmodels/MSCFModel_PWag2009.h"
#include "cfmodels/MSCFModel_Wiedemann.h"
#include "cfmodels/MSCFModel_W99.h"
#include "cfmodels/MSCFModel_ACC.h"
#include "cfmodels/MSCFModel_CACC.h"
#include "MSVehicleControl.h"
#include "cfmodels/MSCFModel_CC.h"
#include "cfmodels/MSCFModel_GM.h"
#include "MSVehicleType.h"


// ===========================================================================
// static members
// ===========================================================================
int MSVehicleType::myNextIndex = 0;


// ===========================================================================
// method definitions
// ===========================================================================
MSVehicleType::MSVehicleType(const SUMOVTypeParameter& parameter) :
    myParameter(parameter),
    myWarnedActionStepLengthTauOnce(false),
    myWarnedActionStepLengthBallisticOnce(false),
    myIndex(myNextIndex++),
    myCarFollowModel(nullptr),
    myOriginalType(nullptr) {
    assert(getLength() > 0);
    assert(getMaxSpeed() > 0);

    // Check if actionStepLength was set by user, if not init to global default
    if (!myParameter.wasSet(VTYPEPARS_ACTIONSTEPLENGTH_SET)) {
        myParameter.actionStepLength = MSGlobals::gActionStepLength;
    }
    myCachedActionStepLengthSecs = STEPS2TIME(myParameter.actionStepLength);
}


MSVehicleType::~MSVehicleType() {
    delete myCarFollowModel;
}


double
MSVehicleType::computeChosenSpeedDeviation(SumoRNG* rng, const double minDev) const {
    return MAX2(minDev, myParameter.speedFactor.sample(rng));
}


// ------------ Setter methods
void
MSVehicleType::setLength(const double& length) {
    if (myOriginalType != nullptr && length < 0) {
        myParameter.length = myOriginalType->getLength();
    } else {
        myParameter.length = length;
    }
    myParameter.parametersSet |= VTYPEPARS_LENGTH_SET;
}


void
MSVehicleType::setHeight(const double& height) {
    if (myOriginalType != nullptr && height < 0) {
        myParameter.height = myOriginalType->getHeight();
    } else {
        myParameter.height = height;
    }
    myParameter.parametersSet |= VTYPEPARS_HEIGHT_SET;
}


void
MSVehicleType::setMinGap(const double& minGap) {
    if (myOriginalType != nullptr && minGap < 0) {
        myParameter.minGap = myOriginalType->getMinGap();
    } else {
        myParameter.minGap = minGap;
    }
    myParameter.parametersSet |= VTYPEPARS_MINGAP_SET;
}


void
MSVehicleType::setMinGapLat(const double& minGapLat) {
    if (myOriginalType != nullptr && minGapLat < 0) {
        myParameter.minGapLat = myOriginalType->getMinGapLat();
    } else {
        myParameter.minGapLat = minGapLat;
    }
    myParameter.parametersSet |= VTYPEPARS_MINGAP_LAT_SET;
}


void
MSVehicleType::setMaxSpeed(const double& maxSpeed) {
    if (myOriginalType != nullptr && maxSpeed < 0) {
        myParameter.maxSpeed = myOriginalType->getMaxSpeed();
    } else {
        myParameter.maxSpeed = maxSpeed;
    }
    myParameter.parametersSet |= VTYPEPARS_MAXSPEED_SET;
}


void
MSVehicleType::setMaxSpeedLat(const double& maxSpeedLat) {
    if (myOriginalType != nullptr && maxSpeedLat < 0) {
        myParameter.maxSpeedLat = myOriginalType->getMaxSpeedLat();
    } else {
        myParameter.maxSpeedLat = maxSpeedLat;
    }
    myParameter.parametersSet |= VTYPEPARS_MAXSPEED_LAT_SET;
}


void
MSVehicleType::setVClass(SUMOVehicleClass vclass) {
    myParameter.vehicleClass = vclass;
    myParameter.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
}


void
MSVehicleType::setPreferredLateralAlignment(const LatAlignmentDefinition& latAlignment, double latAlignmentOffset) {
    myParameter.latAlignmentProcedure = latAlignment;
    myParameter.latAlignmentOffset = latAlignmentOffset;
    myParameter.parametersSet |= VTYPEPARS_LATALIGNMENT_SET;
}


void
MSVehicleType::setDefaultProbability(const double& prob) {
    if (myOriginalType != nullptr && prob < 0) {
        myParameter.defaultProbability = myOriginalType->getDefaultProbability();
    } else {
        myParameter.defaultProbability = prob;
    }
    myParameter.parametersSet |= VTYPEPARS_PROBABILITY_SET;
}


void
MSVehicleType::setSpeedFactor(const double& factor) {
    if (myOriginalType != nullptr && factor < 0) {
        myParameter.speedFactor.getParameter()[0] = myOriginalType->myParameter.speedFactor.getParameter()[0];
    } else {
        myParameter.speedFactor.getParameter()[0] = factor;
    }
    myParameter.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
}


void
MSVehicleType::setSpeedDeviation(const double& dev) {
    if (myOriginalType != nullptr && dev < 0) {
        myParameter.speedFactor.getParameter()[1] = myOriginalType->myParameter.speedFactor.getParameter()[1];
    } else {
        myParameter.speedFactor.getParameter()[1] = dev;
    }
    myParameter.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
}


void
MSVehicleType::setActionStepLength(const SUMOTime actionStepLength, bool resetActionOffset) {
    assert(actionStepLength >= 0.);
    myParameter.parametersSet |= VTYPEPARS_ACTIONSTEPLENGTH_SET;

    if (myParameter.actionStepLength == actionStepLength) {
        return;
    }

    SUMOTime previousActionStepLength = myParameter.actionStepLength;
    myParameter.actionStepLength = actionStepLength;
    myCachedActionStepLengthSecs = STEPS2TIME(myParameter.actionStepLength);
    check();

    if (isVehicleSpecific()) {
        // don't perform vehicle lookup for singular vtype
        return;
    }

    // For non-singular vType reset all vehicle's actionOffsets
    // Iterate through vehicles
    MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
    for (auto vehIt = vc.loadedVehBegin(); vehIt != vc.loadedVehEnd(); ++vehIt) {
        MSVehicle* veh = static_cast<MSVehicle*>(vehIt->second);
        if (&veh->getVehicleType() == this) {
            // Found vehicle of this type. Perform requested actionOffsetReset
            if (resetActionOffset) {
                veh->resetActionOffset();
            } else {
                veh->updateActionOffset(previousActionStepLength, actionStepLength);
            }
        }
    }
}


void
MSVehicleType::setEmissionClass(SUMOEmissionClass eclass) {
    myParameter.emissionClass = eclass;
    myParameter.parametersSet |= VTYPEPARS_EMISSIONCLASS_SET;
}


void
MSVehicleType::setColor(const RGBColor& color) {
    myParameter.color = color;
    myParameter.parametersSet |= VTYPEPARS_COLOR_SET;
}


void
MSVehicleType::setWidth(const double& width) {
    if (myOriginalType != nullptr && width < 0) {
        myParameter.width = myOriginalType->getWidth();
    } else {
        myParameter.width = width;
    }
    myParameter.parametersSet |= VTYPEPARS_WIDTH_SET;
}

void
MSVehicleType::setImpatience(const double impatience) {
    if (myOriginalType != nullptr && impatience < 0) {
        myParameter.impatience = myOriginalType->getImpatience();
    } else {
        myParameter.impatience = impatience;
    }
    myParameter.parametersSet |= VTYPEPARS_IMPATIENCE_SET;
}


void
MSVehicleType::setShape(SUMOVehicleShape shape) {
    myParameter.shape = shape;
    myParameter.parametersSet |= VTYPEPARS_SHAPE_SET;
}



// ------------ Static methods for building vehicle types
MSVehicleType*
MSVehicleType::build(SUMOVTypeParameter& from) {
    MSVehicleType* vtype = new MSVehicleType(from);
    const double decel = from.getCFParam(SUMO_ATTR_DECEL, SUMOVTypeParameter::getDefaultDecel(from.vehicleClass));
    const double emergencyDecel = from.getCFParam(SUMO_ATTR_EMERGENCYDECEL, SUMOVTypeParameter::getDefaultEmergencyDecel(from.vehicleClass, decel, MSGlobals::gDefaultEmergencyDecel));
    // by default decel and apparentDecel are identical
    const double apparentDecel = from.getCFParam(SUMO_ATTR_APPARENTDECEL, decel);

    if (emergencyDecel < decel) {
        WRITE_WARNING("Value of 'emergencyDecel' (" + toString(emergencyDecel) + ") should be higher than 'decel' (" + toString(decel) + ") for vType '" + from.id + "'.");
    }
    if (emergencyDecel < apparentDecel) {
        WRITE_WARNING("Value of 'emergencyDecel' (" + toString(emergencyDecel) + ") is lower than 'apparentDecel' (" + toString(apparentDecel) + ") for vType '" + from.id + "' may cause collisions.");
    }

    switch (from.cfModel) {
        case SUMO_TAG_CF_IDM:
            vtype->myCarFollowModel = new MSCFModel_IDM(vtype, false);
            break;
        case SUMO_TAG_CF_IDMM:
            vtype->myCarFollowModel = new MSCFModel_IDM(vtype, true);
            break;
        case SUMO_TAG_CF_BKERNER:
            vtype->myCarFollowModel = new MSCFModel_Kerner(vtype);
            break;
        case SUMO_TAG_CF_KRAUSS_ORIG1:
            vtype->myCarFollowModel = new MSCFModel_KraussOrig1(vtype);
            break;
        case SUMO_TAG_CF_KRAUSS_PLUS_SLOPE:
            vtype->myCarFollowModel = new MSCFModel_KraussPS(vtype);
            break;
        case SUMO_TAG_CF_KRAUSSX:
            vtype->myCarFollowModel = new MSCFModel_KraussX(vtype);
            break;
        case SUMO_TAG_CF_EIDM:
            vtype->myCarFollowModel = new MSCFModel_EIDM(vtype);
            break;
        case SUMO_TAG_CF_SMART_SK:
            vtype->myCarFollowModel = new MSCFModel_SmartSK(vtype);
            break;
        case SUMO_TAG_CF_DANIEL1:
            vtype->myCarFollowModel = new MSCFModel_Daniel1(vtype);
            break;
        case SUMO_TAG_CF_PWAGNER2009:
            vtype->myCarFollowModel = new MSCFModel_PWag2009(vtype);
            break;
        case SUMO_TAG_CF_WIEDEMANN:
            vtype->myCarFollowModel = new MSCFModel_Wiedemann(vtype);
            break;
        case SUMO_TAG_CF_W99:
            vtype->myCarFollowModel = new MSCFModel_W99(vtype);
            break;
        case SUMO_TAG_CF_RAIL:
            vtype->myCarFollowModel = new MSCFModel_Rail(vtype);
            break;
        case SUMO_TAG_CF_ACC:
            vtype->myCarFollowModel = new MSCFModel_ACC(vtype);
            break;
        case SUMO_TAG_CF_CACC:
            vtype->myCarFollowModel = new MSCFModel_CACC(vtype);
            break;
        case SUMO_TAG_CF_CC:
            vtype->myCarFollowModel = new MSCFModel_CC(vtype);
            break;
        case SUMO_TAG_CF_KRAUSS:
        default:
            vtype->myCarFollowModel = new MSCFModel_Krauss(vtype);
            break;
        case SUMO_TAG_CF_GM:
            vtype->myCarFollowModel = new MSCFModel_GM(vtype);
                //from.getCFParam(SUMO_ATTR_GM_Alpha,1.),
                //from.getCFParam(SUMO_ATTR_GM_M, 1.),
                //from.getCFParam(SUMO_ATTR_GM_L, 1.));
            break ;
 

    }
    // init Rail visualization parameters
    vtype->myParameter.initRailVisualizationParameters();
    vtype->check();
    return vtype;
}

SUMOTime
MSVehicleType::getEntryManoeuvreTime(const int angle) const {
    return (getParameter().getEntryManoeuvreTime(angle));
}

SUMOTime
MSVehicleType::getExitManoeuvreTime(const int angle) const {
    return (getParameter().getExitManoeuvreTime(angle));
}

MSVehicleType*
MSVehicleType::buildSingularType(const std::string& id) const {
    return duplicateType(id, false);
}


MSVehicleType*
MSVehicleType::duplicateType(const std::string& id, bool persistent) const {
    MSVehicleType* vtype = new MSVehicleType(myParameter);
    vtype->myParameter.id = id;
    vtype->myCarFollowModel = myCarFollowModel->duplicate(vtype);
    if (!persistent) {
        vtype->myOriginalType = this;
    }
    if (!MSNet::getInstance()->getVehicleControl().addVType(vtype)) {
        std::string singular = persistent ? "" : "singular ";
        throw ProcessError("could not add " + singular + "type " + vtype->getID());
    }
    return vtype;
}

void
MSVehicleType::check() {
    if (!myWarnedActionStepLengthTauOnce
            && myParameter.actionStepLength != DELTA_T
            && STEPS2TIME(myParameter.actionStepLength) > getCarFollowModel().getHeadwayTime()) {
        myWarnedActionStepLengthTauOnce = true;
        std::stringstream s;
        s << "Given action step length " << STEPS2TIME(myParameter.actionStepLength) << " for vehicle type '" << getID()
          << "' is larger than its parameter tau (=" << getCarFollowModel().getHeadwayTime() << ")!"
          << " This may lead to collisions. (This warning is only issued once per vehicle type).";
        WRITE_WARNING(s.str());
    }
    if (!myWarnedActionStepLengthBallisticOnce
            && myParameter.actionStepLength != DELTA_T
            && MSGlobals::gSemiImplicitEulerUpdate) {
        myWarnedActionStepLengthBallisticOnce = true;
        std::string warning2;
        if (OptionsCont::getOptions().isDefault("step-method.ballistic")) {
            warning2 = " Setting it now to avoid collisions.";
            MSGlobals::gSemiImplicitEulerUpdate = false;
        } else {
            warning2 = " This may cause collisions.";
        }
        WRITE_WARNINGF("Action step length '%' is used for vehicle type '%' but step-method.ballistic was not set." + warning2
                       , STEPS2TIME(myParameter.actionStepLength), getID())
    }
}

void
MSVehicleType::setAccel(double accel) {
    if (myOriginalType != nullptr && accel < 0) {
        accel = myOriginalType->getCarFollowModel().getMaxAccel();
    }
    myCarFollowModel->setMaxAccel(accel);
    myParameter.cfParameter[SUMO_ATTR_ACCEL] = toString(accel);
}

void
MSVehicleType::setDecel(double decel) {
    if (myOriginalType != nullptr && decel < 0) {
        decel = myOriginalType->getCarFollowModel().getMaxDecel();
    }
    myCarFollowModel->setMaxDecel(decel);
    myParameter.cfParameter[SUMO_ATTR_DECEL] = toString(decel);
}

void
MSVehicleType::setEmergencyDecel(double emergencyDecel) {
    if (myOriginalType != nullptr && emergencyDecel < 0) {
        emergencyDecel = myOriginalType->getCarFollowModel().getEmergencyDecel();
    }
    myCarFollowModel->setEmergencyDecel(emergencyDecel);
    myParameter.cfParameter[SUMO_ATTR_EMERGENCYDECEL] = toString(emergencyDecel);
}

void
MSVehicleType::setApparentDecel(double apparentDecel) {
    if (myOriginalType != nullptr && apparentDecel < 0) {
        apparentDecel = myOriginalType->getCarFollowModel().getApparentDecel();
    }
    myCarFollowModel->setApparentDecel(apparentDecel);
    myParameter.cfParameter[SUMO_ATTR_APPARENTDECEL] = toString(apparentDecel);
}

void
MSVehicleType::setImperfection(double imperfection) {
    if (myOriginalType != nullptr && imperfection < 0) {
        imperfection = myOriginalType->getCarFollowModel().getImperfection();
    }
    myCarFollowModel->setImperfection(imperfection);
    myParameter.cfParameter[SUMO_ATTR_SIGMA] = toString(imperfection);
}

void
MSVehicleType::setTau(double tau) {
    if (myOriginalType != nullptr && tau < 0) {
        tau = myOriginalType->getCarFollowModel().getHeadwayTime();
    }
    myCarFollowModel->setHeadwayTime(tau);
    myParameter.cfParameter[SUMO_ATTR_TAU] = toString(tau);
}

/****************************************************************************/
/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2002-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    SUMOXMLDefinitions.h
/// @author  Daniel Krajzewicz
/// @author  Jakob Erdmann
/// @author  Clemens Honomichl
/// @author  Piotr Woznica
/// @author  Michael Behrisch
/// @author  Walter Bamberger
/// @date    Sept 2002
///
// Definitions of elements and attributes known by SUMO
/****************************************************************************/
#pragma once
#include <config.h>

#include <utils/common/StringBijection.h>

// ===========================================================================
// definitions
// ===========================================================================
/**
 * @enum SumoXMLTag
 * @brief Numbers representing SUMO-XML - element names
 * @see GenericSAXHandler
 * @see SUMOSAXHandler
 */
enum SumoXMLTag {
    /// @brief invalid tag
    SUMO_TAG_NOTHING,
    /// @brief root file
    SUMO_TAG_ROOTFILE,
    /// @brief root element of a network file
    SUMO_TAG_NET,
    /// @brief begin/end of the description of an edge
    SUMO_TAG_EDGE,
    /// @brief begin/end of the description of a single lane
    SUMO_TAG_LANE,
    /// @brief begin/end of the description of a neighboring lane
    SUMO_TAG_NEIGH,
    /// @brief begin/end of the description of a polygon
    SUMO_TAG_POLY,
    /// @brief begin/end of the description of a Point of interest
    SUMO_TAG_POI,
    /// @brief begin/end of the description of a junction
    SUMO_TAG_JUNCTION,
    /// @brief begin/end of the description of an edge restriction
    SUMO_TAG_RESTRICTION,
    /// @brief edge-specific meso settings
    SUMO_TAG_MESO,
    /// @brief an e1 detector
    SUMO_TAG_E1DETECTOR,
    /// @brief alternative tag for e1 detector
    SUMO_TAG_INDUCTION_LOOP,
    /// @brief an e2 detector
    SUMO_TAG_E2DETECTOR,
    /// @brief an e2 detector over multiple lanes (placed here due create Additional Frame)
    GNE_TAG_E2DETECTOR_MULTILANE,
    /// @brief alternative tag for e2 detector
    SUMO_TAG_LANE_AREA_DETECTOR,
    /// @brief an e3 detector
    SUMO_TAG_E3DETECTOR,
    /// @brief alternative tag for e3 detector
    SUMO_TAG_ENTRY_EXIT_DETECTOR,
    /// @brief an edge based mean data detector
    SUMO_TAG_MEANDATA_EDGE,
    /// @brief a lane based mean data detector
    SUMO_TAG_MEANDATA_LANE,
    /// @brief an e3 entry point
    SUMO_TAG_DET_ENTRY,
    /// @brief an e3 exit point
    SUMO_TAG_DET_EXIT,
    /// @brief  An edge-following detector
    SUMO_TAG_EDGEFOLLOWDETECTOR,
    /// @brief An instantenous induction loop
    SUMO_TAG_INSTANT_INDUCTION_LOOP,
    /// @brief A variable speed sign
    SUMO_TAG_VSS,
    /// @brief A calibrator placed over edge
    SUMO_TAG_CALIBRATOR,
    /// @brief A calibrator placed over lane (used in netedit)
    SUMO_TAG_LANECALIBRATOR,
    /// @brief  A rerouter
    SUMO_TAG_REROUTER,
    /// @brief  A bus stop
    SUMO_TAG_BUS_STOP,
    /// @brief  A train stop (alias for bus stop)
    SUMO_TAG_TRAIN_STOP,
    /// @brief A pt line
    SUMO_TAG_PT_LINE,
    /// @brief  An access point for a train stop
    SUMO_TAG_ACCESS,
    /// @brief  A container stop
    SUMO_TAG_CONTAINER_STOP,
    /// @brief A parking area
    SUMO_TAG_PARKING_AREA,
    /// @brief A parking space for a single vehicle within a parking area
    SUMO_TAG_PARKING_SPACE,
    /// @brief  A Charging Station
    SUMO_TAG_CHARGING_STATION,
    /// @brief  An overhead wire segment
    SUMO_TAG_OVERHEAD_WIRE_SEGMENT,
    /// @brief  An overhead wire section
    SUMO_TAG_OVERHEAD_WIRE_SECTION,
    /// @brief  A traction substation
    SUMO_TAG_TRACTION_SUBSTATION,
    /// @brief  An overhead wire clamp (connection of wires in opposite directions)
    SUMO_TAG_OVERHEAD_WIRE_CLAMP,
    /// @brief a vtypeprobe detector
    SUMO_TAG_VTYPEPROBE,
    /// @brief a routeprobe detector
    SUMO_TAG_ROUTEPROBE,
    /// @brief root element of a route file
    SUMO_TAG_ROUTES,
    /// @brief description of a vehicle
    SUMO_TAG_VEHICLE,
    /// @brief description of a vehicle type
    SUMO_TAG_VTYPE,
    /// @brief description of a person type (used in NETEDIT)
    SUMO_TAG_PTYPE,
    /// @brief begin/end of the description of a route
    SUMO_TAG_ROUTE,
    /// @brief description of a logic request within the junction
    SUMO_TAG_REQUEST,
    /// @brief a source
    SUMO_TAG_SOURCE,
    /// @brief a traffic assignment zone
    SUMO_TAG_TAZ,
    /// @brief a source within a district (connection road)
    SUMO_TAG_TAZSOURCE,
    /// @brief a sink within a district (connection road)
    SUMO_TAG_TAZSINK,
    /// @brief a traffic light
    SUMO_TAG_TRAFFIC_LIGHT,
    /// @brief a traffic light logic
    SUMO_TAG_TLLOGIC,
    /// @brief a single phase description
    SUMO_TAG_PHASE,
    /// @brief a single trip definition (used by router)
    SUMO_TAG_TRIP,
    /// @brief a single trip definition that uses TAZs (used in NETEDIT)
    SUMO_TAG_TRIP_TAZ,
    /// @brief a flow definitio nusing a from-to edges instead of a route (used by router)
    SUMO_TAG_FLOW,
    /// @brief a flow state definition (used when saving and loading simulatino state)
    SUMO_TAG_FLOWSTATE,
    /// @brief trigger: a step description
    SUMO_TAG_STEP,
    /// @brief an aggreagated-output interval
    SUMO_TAG_INTERVAL,
    /// @brief a relation between two edges
    SUMO_TAG_EDGEREL,
    /// @brief a relation between two TAZs
    SUMO_TAG_TAZREL,
    /// @brief The definition of a periodic event
    SUMO_TAG_TIMEDEVENT,
    /// @brief Incoming edge specification (jtrrouter)
    SUMO_TAG_FROMEDGE,
    /// @brief Outgoing edge specification (jtrrouter)
    SUMO_TAG_TOEDGE,
    /// @brief Sink(s) specification
    SUMO_TAG_SINK,
    /// @brief parameter associated to a certain key
    SUMO_TAG_PARAM,
    SUMO_TAG_WAUT,
    SUMO_TAG_WAUT_SWITCH,
    SUMO_TAG_WAUT_JUNCTION,
    /// @brief segment of a lane
    SUMO_TAG_SEGMENT,
    /// @brief delete certain element (note: DELETE is a macro)
    SUMO_TAG_DEL,
    /// @brief stop for vehicles
    SUMO_TAG_STOP,
    /// @brief stop placed over a lane (used in netedit)
    SUMO_TAG_STOP_LANE,
    /// @brief stop placed over a busStop (used in netedit)
    SUMO_TAG_STOP_BUSSTOP,
    /// @brief stop placed over a containerStop (used in netedit)
    SUMO_TAG_STOP_CONTAINERSTOP,
    /// @brief stop placed over a charging station (used in netedit)
    SUMO_TAG_STOP_CHARGINGSTATION,
    /// @brief stop placed over a parking area (used in netedit)
    SUMO_TAG_STOP_PARKINGAREA,
    /// @brief probability of destiny of a reroute
    SUMO_TAG_DEST_PROB_REROUTE,
    /// @brief reroute of type closing
    SUMO_TAG_CLOSING_REROUTE,
    /// @brief lane of a reroute of type closing
    SUMO_TAG_CLOSING_LANE_REROUTE,
    /// @brief probability of route of a reroute
    SUMO_TAG_ROUTE_PROB_REROUTE,
    /// @brief entry for an alternative parking zone
    SUMO_TAG_PARKING_ZONE_REROUTE,
    /// @brief type of polygon
    SUMO_TAG_POLYTYPE,
    /// @brief connectio between two lanes
    SUMO_TAG_CONNECTION,
    /// @brief prohibition of circulation between two edges
    SUMO_TAG_PROHIBITION,
    /// @brief split something
    SUMO_TAG_SPLIT,
    /// @brief alternative definition for junction
    SUMO_TAG_NODE,
    /// @brief type (edge)
    SUMO_TAG_TYPE,
    /// @brief lane type
    SUMO_TAG_LANETYPE,
    /// @brief definition of a detector
    SUMO_TAG_DETECTOR_DEFINITION,
    /// @brief distribution of a route
    SUMO_TAG_ROUTE_DISTRIBUTION,
    /// @brief distribution of a vehicle type
    SUMO_TAG_VTYPE_DISTRIBUTION,
    /// @brief vaporizer of vehicles
    SUMO_TAG_VAPORIZER,
    /// @brief roundabout defined in junction
    SUMO_TAG_ROUNDABOUT,
    /// @brief Join operation
    SUMO_TAG_JOIN,
    /// @brief join exlude operation
    SUMO_TAG_JOINEXCLUDE,
    /// @brief crossing between edges for pedestrians
    SUMO_TAG_CROSSING,
    /// @brief walking area for pedestrians
    SUMO_TAG_WALKINGAREA,
    /// @brief Information on vClass specific stop offsets at lane end
    SUMO_TAG_STOPOFFSET,
    /// @brief Constraints on switching a rail signal
    SUMO_TAG_RAILSIGNAL_CONSTRAINTS,
    /// @brief Predecessor constraint on switching a rail signal
    SUMO_TAG_PREDECESSOR,
    /// @brief Predecessor constraint on insertion before rail signal
    SUMO_TAG_INSERTION_PREDECESSOR,
    /// @brief Saved state for constraint tracker
    SUMO_TAG_RAILSIGNAL_CONSTRAINT_TRACKER,
    /// @brief Link information for state-saving
    SUMO_TAG_LINK,
    /// @brief Link-approaching vehicle information for state-saving
    SUMO_TAG_APPROACHING,

    SUMO_TAG_WAY,
    SUMO_TAG_ND,
    SUMO_TAG_TAG,
    SUMO_TAG_RELATION,
    SUMO_TAG_MEMBER,

    /// @name parameters associated to view settings
    /// @{
    SUMO_TAG_VIEWSETTINGS,
    SUMO_TAG_VIEWSETTINGS_DECAL,
    SUMO_TAG_VIEWSETTINGS_LIGHT,
    SUMO_TAG_VIEWSETTINGS_SCHEME,
    SUMO_TAG_VIEWSETTINGS_OPENGL,
    SUMO_TAG_VIEWSETTINGS_BACKGROUND,
    SUMO_TAG_VIEWSETTINGS_EDGES,
    SUMO_TAG_VIEWSETTINGS_VEHICLES,
    SUMO_TAG_VIEWSETTINGS_PERSONS,
    SUMO_TAG_VIEWSETTINGS_CONTAINERS,
    SUMO_TAG_VIEWSETTINGS_JUNCTIONS,
    SUMO_TAG_VIEWSETTINGS_ADDITIONALS,
    SUMO_TAG_VIEWSETTINGS_POIS,
    SUMO_TAG_VIEWSETTINGS_POLYS,
    SUMO_TAG_VIEWSETTINGS_LEGEND,
    SUMO_TAG_VIEWSETTINGS_EVENT,
    SUMO_TAG_VIEWSETTINGS_EVENT_JAM_TIME,
    SUMO_TAG_INCLUDE,
    SUMO_TAG_DELAY,
    SUMO_TAG_VIEWPORT,
    SUMO_TAG_SNAPSHOT,
    SUMO_TAG_BREAKPOINT,
    SUMO_TAG_LOCATION,
    SUMO_TAG_COLORSCHEME,
    SUMO_TAG_SCALINGSCHEME,
    SUMO_TAG_ENTRY,
    SUMO_TAG_RNGSTATE,
    SUMO_TAG_RNGLANE,
    /// @}

    SUMO_TAG_VEHICLETRANSFER,
    SUMO_TAG_DEVICE,

    /// @name Car-Following models
    /// @{
    SUMO_TAG_CF_KRAUSS,
    SUMO_TAG_CF_KRAUSS_PLUS_SLOPE,
    SUMO_TAG_CF_KRAUSS_ORIG1,
    SUMO_TAG_CF_KRAUSSX,
    SUMO_TAG_CF_EIDM,
    SUMO_TAG_CF_SMART_SK,
    SUMO_TAG_CF_DANIEL1,
    SUMO_TAG_CF_IDM,
    SUMO_TAG_CF_IDMM,
    SUMO_TAG_CF_PWAGNER2009,
    SUMO_TAG_CF_BKERNER,
    SUMO_TAG_CF_WIEDEMANN,
    SUMO_TAG_CF_W99,
    SUMO_TAG_CF_ACC,
    SUMO_TAG_CF_CACC,
    SUMO_TAG_CF_RAIL,
    SUMO_TAG_CF_CC,
    SUMO_TAG_CF_GM,
    /// @}

    /// @name Persons
    /// @{
    SUMO_TAG_PERSON,
    SUMO_TAG_PERSONTRIP,
    SUMO_TAG_RIDE,
    SUMO_TAG_WALK,
    SUMO_TAG_PERSONFLOW,
    /// @}

    /// @name Data elements (used by Netedit)
    /// @{
    SUMO_TAG_DATASET,
    SUMO_TAG_DATAINTERVAL,
    /// @}

    /// @name Containers
    /// @{
    SUMO_TAG_CONTAINER,
    SUMO_TAG_TRANSPORT,
    SUMO_TAG_TRANSHIP,
    SUMO_TAG_CONTAINERFLOW,
    /// @}

    SUMO_TAG_TRAJECTORIES,
    SUMO_TAG_TIMESTEP,
    SUMO_TAG_TIMESLICE,
    SUMO_TAG_ACTORCONFIG,
    SUMO_TAG_MOTIONSTATE,
    SUMO_TAG_OD_PAIR,
    SUMO_TAG_TRANSPORTABLES,

    /// @brief ActivityGen Tags
    AGEN_TAG_GENERAL,
    /// @brief streets object
    AGEN_TAG_STREET,
    /// @brief workingHours object
    AGEN_TAG_WORKHOURS,
    /// @brief opening for workingHours object
    AGEN_TAG_OPENING,
    /// @brief closing for workingHours object
    AGEN_TAG_CLOSING,
    /// @brief school object
    AGEN_TAG_SCHOOLS,
    /// @brief schools object
    AGEN_TAG_SCHOOL,
    /// @brief busStation and bus objects
    AGEN_TAG_BUSSTATION,
    /// @brief  bus line
    AGEN_TAG_BUSLINE,
    /// @brief stations for certain vehicles
    AGEN_TAG_STATIONS,
    /// @brief rev stations for certain vehicles
    AGEN_TAG_REV_STATIONS,
    /// @brief station for a certain vehicle
    AGEN_TAG_STATION,
    /// @brief frequency of a object
    AGEN_TAG_FREQUENCY,
    /// @brief population and children accompaniment brackets
    AGEN_TAG_POPULATION,
    /// @brief alternative definition for Population
    AGEN_TAG_BRACKET,
    //AGEN_TAG_CHILD_ACOMP,
    /// @brief city entrances
    AGEN_TAG_CITYGATES,
    /// @brief alternative definition for city entrances
    AGEN_TAG_ENTRANCE,
    /// @brief parameters
    AGEN_TAG_PARAM,

    /// @name NETEDIT elements
    /// @{
    /// @brief internal lane
    GNE_TAG_INTERNAL_LANE,
    /// @brief a flow definition within in Calibrator
    GNE_TAG_FLOW_CALIBRATOR,
    /// @brief Point of interest over Lane
    GNE_TAG_POILANE,
    /// @brief Point of interest over view with GEO attributes
    GNE_TAG_POIGEO,
    /// @brief Rerouter Symbol
    GNE_TAG_REROUTER_SYMBOL,
    /// @brief VSS Symbol
    GNE_TAG_VSS_SYMBOL,
    /// @brief description of a vehicle with an embedded route (used in NETEDIT)
    GNE_TAG_VEHICLE_WITHROUTE,
    /// @brief embedded route (used in NETEDIT)
    GNE_TAG_ROUTE_EMBEDDED,
    /// @brief a flow definition using a route instead of a from-to edges route (used in NETEDIT)
    GNE_TAG_FLOW_ROUTE,
    /// @brief description of a vehicle with an embedded route (used in NETEDIT)
    GNE_TAG_FLOW_WITHROUTE,
    // person trips
    GNE_TAG_PERSONTRIP_EDGE,
    GNE_TAG_PERSONTRIP_BUSSTOP,
    // walks
    GNE_TAG_WALK_EDGE,
    GNE_TAG_WALK_BUSSTOP,
    GNE_TAG_WALK_EDGES,
    GNE_TAG_WALK_ROUTE,
    // rides
    GNE_TAG_RIDE_EDGE,
    GNE_TAG_RIDE_BUSSTOP,
    // person stops
    GNE_TAG_STOPPERSON_BUSSTOP,
    GNE_TAG_STOPPERSON_EDGE,
    // person trips
    GNE_TAG_TRANSPORT_EDGE,
    GNE_TAG_TRANSPORT_CONTAINERSTOP,
    // walks
    GNE_TAG_TRANSHIP_EDGE,
    GNE_TAG_TRANSHIP_CONTAINERSTOP,
    GNE_TAG_TRANSHIP_EDGES,
    // container stops
    GNE_TAG_STOPCONTAINER_CONTAINERSTOP,
    GNE_TAG_STOPCONTAINER_EDGE,
    /// @}
};


/**
 * @enum SumoXMLAttr
 * @brief Numbers representing SUMO-XML - attributes
 * @see GenericSAXHandler
 * @see SUMOSAXHandler
 */
enum SumoXMLAttr {
    /// @brief invalid attribute
    SUMO_ATTR_NOTHING = 0,

    /// @name meanData output attributes
    /// @note: sorted first to simplify filtering written attributes with bit operations
    /// @{
    SUMO_ATTR_DEFAULT            =  1,
    /// MSMeanData_Net
    SUMO_ATTR_SAMPLEDSECONDS     =  2,
    SUMO_ATTR_DENSITY            =  3,
    SUMO_ATTR_LANEDENSITY        =  4,
    SUMO_ATTR_OCCUPANCY          =  5,
    SUMO_ATTR_WAITINGTIME        =  6,
    SUMO_ATTR_TIMELOSS           =  7,
    SUMO_ATTR_SPEED              =  8,
    SUMO_ATTR_DEPARTED           =  9,
    SUMO_ATTR_ARRIVED            = 10,
    SUMO_ATTR_ENTERED            = 11,
    SUMO_ATTR_LEFT               = 12,
    SUMO_ATTR_VAPORIZED          = 13,
    SUMO_ATTR_TRAVELTIME         = 14,
    SUMO_ATTR_LANECHANGEDFROM    = 15,
    SUMO_ATTR_LANECHANGEDTO      = 16,
    SUMO_ATTR_OVERLAPTRAVELTIME  = 17,
    /// MSMeanData_Emissions
    SUMO_ATTR_CO_ABS             = 18,
    SUMO_ATTR_CO2_ABS            = 19,
    SUMO_ATTR_HC_ABS             = 20,
    SUMO_ATTR_PMX_ABS            = 21,
    SUMO_ATTR_NOX_ABS            = 22,
    SUMO_ATTR_FUEL_ABS           = 23,
    SUMO_ATTR_ELECTRICITY_ABS    = 24,
    SUMO_ATTR_CO_NORMED          = 25,
    SUMO_ATTR_CO2_NORMED         = 26,
    SUMO_ATTR_HC_NORMED          = 27,
    SUMO_ATTR_PMX_NORMED         = 28,
    SUMO_ATTR_NOX_NORMED         = 29,
    SUMO_ATTR_FUEL_NORMED        = 30,
    SUMO_ATTR_ELECTRICITY_NORMED = 31,
    SUMO_ATTR_CO_PERVEH          = 32,
    SUMO_ATTR_CO2_PERVEH         = 33,
    SUMO_ATTR_HC_PERVEH          = 34,
    SUMO_ATTR_PMX_PERVEH         = 35,
    SUMO_ATTR_NOX_PERVEH         = 36,
    SUMO_ATTR_FUEL_PERVEH        = 37,
    SUMO_ATTR_ELECTRICITY_PERVEH = 38,
    /// MSMeanData_Harmonoise
    SUMO_ATTR_NOISE              = 39,
    /// MSMeanData_Amitran
    SUMO_ATTR_AMOUNT             = 40,
    SUMO_ATTR_AVERAGESPEED       = 41,
    // FCD-Output
    SUMO_ATTR_X                  = 42,
    SUMO_ATTR_Y                  = 43,
    SUMO_ATTR_Z                  = 44,
    SUMO_ATTR_ANGLE              = 45,
    SUMO_ATTR_TYPE               = 46,
    SUMO_ATTR_POSITION           = 47,
    SUMO_ATTR_EDGE               = 48,
    SUMO_ATTR_LANE               = 49,
    SUMO_ATTR_SLOPE              = 50,
    SUMO_ATTR_SIGNALS            = 51,
    SUMO_ATTR_ACCELERATION       = 52,
    SUMO_ATTR_ACCELERATION_LAT   = 53,
    SUMO_ATTR_DISTANCE           = 54,
    SUMO_ATTR_LEADER_ID          = 55,
    SUMO_ATTR_LEADER_SPEED       = 56,
    SUMO_ATTR_LEADER_GAP         = 57,
    SUMO_ATTR_VEHICLE            = 58,
    /// @}

    /// @name common attributes
    /// @{
    SUMO_ATTR_ID,
    SUMO_ATTR_REFID,
    SUMO_ATTR_NAME,
    SUMO_ATTR_VERSION,
    SUMO_ATTR_PRIORITY,
    SUMO_ATTR_NUMLANES,
    SUMO_ATTR_ONEWAY,
    SUMO_ATTR_WIDTH,
    SUMO_ATTR_WIDTHRESOLUTION,
    SUMO_ATTR_MAXWIDTH,
    SUMO_ATTR_MINWIDTH,
    SUMO_ATTR_SIDEWALKWIDTH,
    SUMO_ATTR_BIKELANEWIDTH,
    SUMO_ATTR_REMOVE,
    SUMO_ATTR_LENGTH,
    SUMO_ATTR_BIDI,
    SUMO_ATTR_ID_BEFORE,
    SUMO_ATTR_ID_AFTER,
    SUMO_ATTR_CENTER,
    SUMO_ATTR_CENTER_X,
    SUMO_ATTR_CENTER_Y,
    SUMO_ATTR_CENTER_Z,
    /// @}

    /// @name sumo-junction attributes
    /// @{
    SUMO_ATTR_KEY,
    SUMO_ATTR_REQUESTSIZE,
    SUMO_ATTR_REQUEST,
    SUMO_ATTR_RESPONSE,
    SUMO_ATTR_PROGRAMID,
    SUMO_ATTR_PHASE,
    SUMO_ATTR_OFFSET,
    SUMO_ATTR_ENDOFFSET,
    SUMO_ATTR_INCLANES,
    SUMO_ATTR_INTLANES,
    /// @}

    /// @name the weight of a district's source or sink
    /// @{
    SUMO_ATTR_WEIGHT,
    SUMO_ATTR_NODE,
    /// @}

    /// @brief the edges of a route
    SUMO_ATTR_EDGES,

    /// @name vehicle attributes
    /// @{
    SUMO_ATTR_DEPART,
    SUMO_ATTR_DEPARTLANE,
    SUMO_ATTR_DEPARTPOS,
    SUMO_ATTR_DEPARTPOS_LAT,
    SUMO_ATTR_DEPARTSPEED,
    SUMO_ATTR_DEPARTEDGE,
    SUMO_ATTR_ARRIVALLANE,
    SUMO_ATTR_ARRIVALPOS,
    SUMO_ATTR_ARRIVALPOS_LAT,
    SUMO_ATTR_ARRIVALSPEED,
    SUMO_ATTR_ARRIVALEDGE,
    SUMO_ATTR_ROUTE,
    SUMO_ATTR_MAXSPEED,
    SUMO_ATTR_MAXSPEED_LAT,
    SUMO_ATTR_LATALIGNMENT,
    SUMO_ATTR_MINGAP_LAT,
    SUMO_ATTR_ACCEL,
    SUMO_ATTR_DECEL,
    SUMO_ATTR_EMERGENCYDECEL,
    SUMO_ATTR_APPARENTDECEL,
    SUMO_ATTR_ACTIONSTEPLENGTH,
    SUMO_ATTR_VCLASS,
    SUMO_ATTR_VCLASSES,
    SUMO_ATTR_EXCEPTIONS,
    SUMO_ATTR_REPNUMBER,
    SUMO_ATTR_SPEEDFACTOR,
    SUMO_ATTR_SPEEDDEV,
    SUMO_ATTR_LANE_CHANGE_MODEL,
    SUMO_ATTR_CAR_FOLLOW_MODEL,
    SUMO_ATTR_MINGAP,
    SUMO_ATTR_COLLISION_MINGAP_FACTOR,
    SUMO_ATTR_BOARDING_DURATION,
    SUMO_ATTR_LOADING_DURATION,
    /// @brief Class specific timing values for vehicle manoeuvering through angle ranges
    SUMO_ATTR_MANEUVER_ANGLE_TIMES,
    /// @}

    /// @name elecHybrid output attributes
    /// @{
    /// @brief power charging from overhead wire to battery if the battery SoC is not full
    SUMO_ATTR_OVERHEADWIRECHARGINGPOWER,
    /// @}

    /// @name overheadWire attributes
    /// @{
    SUMO_ATTR_OVERHEAD_WIRE_SEGMENT,
    SUMO_ATTR_OVERHEAD_WIRE_SECTION,
    /// @brief voltage of the traction substation [V]
    SUMO_ATTR_VOLTAGE,
    /// @brief a voltage source on the overhead wire segment [bool]
    SUMO_ATTR_VOLTAGESOURCE,
    /// @brief current limit of the traction substation [A]
    SUMO_ATTR_CURRENTLIMIT,
    /// @brief id of a traction substation substation
    SUMO_ATTR_SUBSTATIONID,
    /// @brief resistivity of overhead wires
    SUMO_ATTR_OVERHEAD_WIRE_RESISTIVITY,
    /// @brief forbidden lanes for overhead wire segment
    SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN,
    /// @brief overhead wire clamps for overhead wire segment
    SUMO_ATTR_OVERHEAD_WIRE_CLAMPS,
    /// @brief id of the overhead wire segment, to the start of which the overhead wire clamp is connected
    SUMO_ATTR_OVERHEAD_WIRE_CLAMP_START,
    /// @brief id of the overhead wire segment, to the end of which the overhead wire clamp is connected
    SUMO_ATTR_OVERHEAD_WIRE_CLAMP_END,
    /// @}

    /// @name charging stations attributes
    /// @{
    /// @brief charge in W/s of the Charging Stations
    SUMO_ATTR_CHARGINGPOWER,
    /// @brief Eficiency of the charge in Charging Stations
    SUMO_ATTR_EFFICIENCY,
    /// @brief Allow/disallow charge in transit in Charging Stations
    SUMO_ATTR_CHARGEINTRANSIT,
    /// @brief Delay in the charge of charging stations
    SUMO_ATTR_CHARGEDELAY,
    /// @}

    /// @name battery device parameters
    /// @{
    /// @brief Actual battery capacity
    SUMO_ATTR_ACTUALBATTERYCAPACITY,
    /// @brief Maxium battery capacity
    SUMO_ATTR_MAXIMUMBATTERYCAPACITY,
    /// @brief Maximum Power
    SUMO_ATTR_MAXIMUMPOWER,
    /// @brief Vehicle mass
    SUMO_ATTR_VEHICLEMASS,
    /// @brief Front surface area
    SUMO_ATTR_FRONTSURFACEAREA,
    /// @brief Air drag coefficient
    SUMO_ATTR_AIRDRAGCOEFFICIENT,
    /// @brief Internal moment of inertia
    SUMO_ATTR_INTERNALMOMENTOFINERTIA,
    /// @brief Radial drag coefficient
    SUMO_ATTR_RADIALDRAGCOEFFICIENT,
    /// @brief Roll Drag coefficient
    SUMO_ATTR_ROLLDRAGCOEFFICIENT,
    /// @brief Constant Power Intake
    SUMO_ATTR_CONSTANTPOWERINTAKE,
    /// @brief Propulsion efficiency
    SUMO_ATTR_PROPULSIONEFFICIENCY,
    /// @brief Recuperation efficiency (constant)
    SUMO_ATTR_RECUPERATIONEFFICIENCY,
    /// @brief Recuperation efficiency (by deceleration)
    SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION,
    /// @brief Stopping treshold
    SUMO_ATTR_STOPPINGTRESHOLD,
    /// @}

    /// @name elecHybrid device export parameters
    /// @{
    // @brief Overhead Wire Segment ID
    SUMO_ATTR_OVERHEADWIREID,
    // @brief Traction substation ID
    SUMO_ATTR_TRACTIONSUBSTATIONID,
    // @brief Electric current drawn from overhead wire
    SUMO_ATTR_CURRENTFROMOVERHEADWIRE,
    // @brief Voltage of overhead wire (above the vehicle)
    SUMO_ATTR_VOLTAGEOFOVERHEADWIRE,
    // @brief Circuit solver alpha parameter
    SUMO_ATTR_ALPHACIRCUITSOLVER,
    /// @}

    /// @name battery export parameters
    /// @{
    /// @brief charging status
    SUMO_ATTR_CHARGING_STATUS,
    /// @brief Energy consumed
    SUMO_ATTR_ENERGYCONSUMED,
    /// @brief Total energy consumed
    SUMO_ATTR_TOTALENERGYCONSUMED,
    /// @brief Total energy regenerated
    SUMO_ATTR_TOTALENERGYREGENERATED,
    /// @brief Charging Station ID
    SUMO_ATTR_CHARGINGSTATIONID,
    /// @brief tgotal of Energy charged
    SUMO_ATTR_ENERGYCHARGED,
    /// @brief Energy charged in transit
    SUMO_ATTR_ENERGYCHARGEDINTRANSIT,
    /// @brief Energy charged stopped
    SUMO_ATTR_ENERGYCHARGEDSTOPPED,
    /// @brief Position on lane
    SUMO_ATTR_POSONLANE,
    /// @brief Time stopped
    SUMO_ATTR_TIMESTOPPED,
    /// @}

    /// @name chargingStations export parameters
    /// @{
    /// @brief total energy charged by charging station
    SUMO_ATTR_TOTALENERGYCHARGED,
    /// @brief number of steps that a vehicle is charging
    SUMO_ATTR_CHARGINGSTEPS,
    /// @brief total energy charged into a single vehicle
    SUMO_ATTR_TOTALENERGYCHARGED_VEHICLE,
    /// @brief timestep in which charging begins
    SUMO_ATTR_CHARGINGBEGIN,
    /// @brief timesteps in which charging ends
    SUMO_ATTR_CHARGINGEND,
    /// @brief energy provied by charging station at certain timestep
    SUMO_ATTR_PARTIALCHARGE,
    /// @}

    /// @name Car following model attributes
    /// @{
    SUMO_ATTR_SIGMA,    // used by: Krauss
    SUMO_ATTR_TAU,      // Krauss
    SUMO_ATTR_TMP1,
    SUMO_ATTR_TMP2,
    SUMO_ATTR_TMP3,
    SUMO_ATTR_TMP4,
    SUMO_ATTR_TMP5,

    // Car Following Model attributes of General Motors Model
    SUMO_ATTR_GM_Alpha,
    SUMO_ATTR_GM_M,
    SUMO_ATTR_GM_L,
    // Car Following Model attributes of the Extended IDM
    SUMO_ATTR_CF_EIDM_USEVEHDYNAMICS,
    SUMO_ATTR_CF_EIDM_T_LOOK_AHEAD,
    SUMO_ATTR_CF_EIDM_T_PERSISTENCE_DRIVE,
    SUMO_ATTR_CF_EIDM_T_REACTION,
    SUMO_ATTR_CF_EIDM_T_PERSISTENCE_ESTIMATE,
    SUMO_ATTR_CF_EIDM_C_COOLNESS,
    SUMO_ATTR_CF_EIDM_SIG_LEADER,
    SUMO_ATTR_CF_EIDM_SIG_GAP,
    SUMO_ATTR_CF_EIDM_SIG_ERROR,
    SUMO_ATTR_CF_EIDM_JERK_MAX,
    SUMO_ATTR_CF_EIDM_EPSILON_ACC,
    SUMO_ATTR_CF_EIDM_T_ACC_MAX,
    SUMO_ATTR_CF_EIDM_M_FLATNESS,
    SUMO_ATTR_CF_EIDM_M_BEGIN,
    SUMO_ATTR_CF_EIDM_MAX_VEH_PREVIEW,
    /// @}

    // @name Train ACC model attributes
    /// @{
    SUMO_ATTR_SC_GAIN,
    SUMO_ATTR_GCC_GAIN_SPEED,
    SUMO_ATTR_GCC_GAIN_SPACE,
    SUMO_ATTR_GC_GAIN_SPEED,
    SUMO_ATTR_GC_GAIN_SPACE,
    SUMO_ATTR_CA_GAIN_SPEED,
    SUMO_ATTR_CA_GAIN_SPACE,
    /// @}

    // @name Train CACC model attributes
    /// @{
    SUMO_ATTR_SC_GAIN_CACC,
    SUMO_ATTR_GCC_GAIN_GAP_CACC,
    SUMO_ATTR_GCC_GAIN_GAP_DOT_CACC,
    SUMO_ATTR_GC_GAIN_GAP_CACC,
    SUMO_ATTR_GC_GAIN_GAP_DOT_CACC,
    SUMO_ATTR_CA_GAIN_GAP_CACC,
    SUMO_ATTR_CA_GAIN_GAP_DOT_CACC,
    SUMO_ATTR_HEADWAY_TIME_CACC_TO_ACC,
    SUMO_ATTR_APPLYDRIVERSTATE,
    /// @}
    


    /// @name Train model attributes
    /// @{
    SUMO_ATTR_TRAIN_TYPE, //used by: Rail
    /// @}

    /// @name Lane changing model attributes
    /// @{
    SUMO_ATTR_LCA_STRATEGIC_PARAM,
    SUMO_ATTR_LCA_COOPERATIVE_PARAM,
    SUMO_ATTR_LCA_SPEEDGAIN_PARAM,
    SUMO_ATTR_LCA_KEEPRIGHT_PARAM,
    SUMO_ATTR_LCA_SUBLANE_PARAM,
    SUMO_ATTR_LCA_OPPOSITE_PARAM,
    SUMO_ATTR_LCA_PUSHY,
    SUMO_ATTR_LCA_PUSHYGAP,
    SUMO_ATTR_LCA_ASSERTIVE,
    SUMO_ATTR_LCA_IMPATIENCE,
    SUMO_ATTR_LCA_TIME_TO_IMPATIENCE,
    SUMO_ATTR_LCA_ACCEL_LAT,
    SUMO_ATTR_LCA_LOOKAHEADLEFT,
    SUMO_ATTR_LCA_SPEEDGAINRIGHT,
    SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD,
    SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT,
    SUMO_ATTR_LCA_COOPERATIVE_SPEED,
    SUMO_ATTR_LCA_MAXSPEEDLATSTANDING,
    SUMO_ATTR_LCA_MAXSPEEDLATFACTOR,
    SUMO_ATTR_LCA_MAXDISTLATSTANDING,
    SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE,
    SUMO_ATTR_LCA_OVERTAKE_RIGHT,
    SUMO_ATTR_LCA_LANE_DISCIPLINE,
    SUMO_ATTR_LCA_SIGMA,
    SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME,
    SUMO_ATTR_LCA_EXPERIMENTAL1,
    /// @}

    /// @name Junction model attributes
    /// @{
    SUMO_ATTR_JM_CROSSING_GAP,
    SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME,
    SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME,
    SUMO_ATTR_JM_DRIVE_RED_SPEED,
    SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME,
    SUMO_ATTR_JM_IGNORE_FOE_SPEED,
    SUMO_ATTR_JM_IGNORE_FOE_PROB,
    SUMO_ATTR_JM_IGNORE_JUNCTION_FOE_PROB,
    SUMO_ATTR_JM_SIGMA_MINOR,
    SUMO_ATTR_JM_STOPLINE_GAP,
    SUMO_ATTR_JM_TIMEGAP_MINOR,
    SUMO_ATTR_JM_IGNORE_IDS,
    SUMO_ATTR_JM_IGNORE_TYPES,
    /// @}

    /// @name route alternatives / distribution attributes
    /// @{
    SUMO_ATTR_LAST,
    SUMO_ATTR_COST,
    SUMO_ATTR_COSTS,
    SUMO_ATTR_SAVINGS,
    SUMO_ATTR_EXITTIMES,
    SUMO_ATTR_PROB,
    SUMO_ATTR_COUNT,
    SUMO_ATTR_PROBS,
    SUMO_ATTR_ROUTES,
    SUMO_ATTR_VTYPES,
    /// @}

    /// @name trip definition attributes
    /// @{
    SUMO_ATTR_LANES,
    SUMO_ATTR_FROM,
    SUMO_ATTR_TO,
    SUMO_ATTR_FROMLONLAT,
    SUMO_ATTR_TOLONLAT,
    SUMO_ATTR_FROMXY,
    SUMO_ATTR_TOXY,
    SUMO_ATTR_FROMJUNCTION,
    SUMO_ATTR_TOJUNCTION,
    SUMO_ATTR_PERIOD,
    SUMO_ATTR_REPEAT,
    SUMO_ATTR_CYCLETIME,
    SUMO_ATTR_FROM_TAZ,
    SUMO_ATTR_TO_TAZ,
    SUMO_ATTR_REROUTE,
    SUMO_ATTR_PERSON_CAPACITY,
    SUMO_ATTR_CONTAINER_CAPACITY,
    SUMO_ATTR_PARKING_LENGTH,
    SUMO_ATTR_PERSON_NUMBER,
    SUMO_ATTR_CONTAINER_NUMBER,
    SUMO_ATTR_MODES,
    SUMO_ATTR_WALKFACTOR,
    /// @}

    /// @name source definitions
    /// @{
    SUMO_ATTR_FUNCTION,
    SUMO_ATTR_POSITION_LAT,
    SUMO_ATTR_FREQUENCY,
    SUMO_ATTR_STYLE,
    SUMO_ATTR_FILE,
    SUMO_ATTR_JUNCTION,
    SUMO_ATTR_NUMBER,
    SUMO_ATTR_DURATION,
    SUMO_ATTR_UNTIL,
    SUMO_ATTR_ARRIVAL,
    SUMO_ATTR_EXTENSION,
    SUMO_ATTR_ROUTEPROBE,
    SUMO_ATTR_STARTED,
    SUMO_ATTR_ENDED,
    /// @}

    /// @brief the edges crossed by a pedestrian crossing
    SUMO_ATTR_CROSSING_EDGES,
    /// @brief trigger: the time of the step
    SUMO_ATTR_TIME,
    /// @brief weights: time range begin
    SUMO_ATTR_BEGIN,
    /// @brief weights: time range end
    SUMO_ATTR_END,
    /// @brief link,node: the traffic light id responsible for this link
    SUMO_ATTR_TLID,
    /// @brief node: the type of traffic light
    SUMO_ATTR_TLTYPE,
    /// @brief node: the layout of the traffic light program
    SUMO_ATTR_TLLAYOUT,
    /// @brief link: the index of the link within the traffic light
    SUMO_ATTR_TLLINKINDEX,
    /// @brief link: the index of the opposite direction link of a pedestrian crossing
    SUMO_ATTR_TLLINKINDEX2,
    /// @brief edge: the shape in xml-definition
    SUMO_ATTR_SHAPE,
    /// @brief The information about how to spread the lanes from the given position
    SUMO_ATTR_SPREADTYPE,
    /// @brief The turning radius at an intersection in m
    SUMO_ATTR_RADIUS,
    /// @brief Whether vehicles must keep the junction clear
    SUMO_ATTR_KEEP_CLEAR,
    /// @brief Whether this connection is an indirect (left) turn
    SUMO_ATTR_INDIRECT,
    /// @brief How to compute right of way
    SUMO_ATTR_RIGHT_OF_WAY,
    /// @brief Fringe type of node
    SUMO_ATTR_FRINGE,
    /// @brief whether a given shape is user-defined
    SUMO_ATTR_CUSTOMSHAPE,
    /// @brief A color information
    SUMO_ATTR_COLOR,
    /// @brief The abstract direction of a link
    SUMO_ATTR_DIR,
    /// @brief The state of a link
    SUMO_ATTR_STATE,
    /// @brief foe visibility distance of a link
    SUMO_ATTR_VISIBILITY_DISTANCE,
    /// @brief A layer number
    SUMO_ATTR_LAYER,
    /// @brief Fill the polygon
    SUMO_ATTR_FILL,
    SUMO_ATTR_LINEWIDTH,
    SUMO_ATTR_PREFIX,
    SUMO_ATTR_DISCARD,

    SUMO_ATTR_FROM_LANE,
    SUMO_ATTR_TO_LANE,
    SUMO_ATTR_DEST,
    SUMO_ATTR_SOURCE,
    SUMO_ATTR_VIA,
    SUMO_ATTR_VIALONLAT,
    SUMO_ATTR_VIAXY,
    SUMO_ATTR_VIAJUNCTIONS,
    /// @brief a list of node ids, used for controlling joining
    SUMO_ATTR_NODES,

    /// @name Attributes for actuated traffic lights:
    /// @{
    /// @brief minimum duration of a phase
    SUMO_ATTR_MINDURATION,
    /// @brief maximum duration of a phase
    SUMO_ATTR_MAXDURATION,
    /// @brief succesor phase index
    SUMO_ATTR_NEXT,
    /// @}

    /// @name Attributes for junction-internal lanes
    /// @{
    /// @brief Information within the junction logic which internal lanes block external
    SUMO_ATTR_FOES,
    /// @}
    SUMO_ATTR_CONSTRAINTS,

    /// @name Attributes for detectors
    /// @{
    /// @brief Information whether the detector shall be continued on the folowing lanes
    SUMO_ATTR_CONT,
    SUMO_ATTR_CONTPOS,
    SUMO_ATTR_HALTING_TIME_THRESHOLD,
    SUMO_ATTR_HALTING_SPEED_THRESHOLD,
    SUMO_ATTR_JAM_DIST_THRESHOLD,
    SUMO_ATTR_SHOW_DETECTOR,
    SUMO_ATTR_OPEN_ENTRY,
    /// @}

    SUMO_ATTR_WAUT_ID,
    SUMO_ATTR_JUNCTION_ID,
    SUMO_ATTR_PROCEDURE,
    SUMO_ATTR_SYNCHRON,
    SUMO_ATTR_REF_TIME,
    SUMO_ATTR_START_PROG,

    SUMO_ATTR_OFF,
    SUMO_ATTR_FRIENDLY_POS,
    SUMO_ATTR_SPLIT_VTYPE,
    SUMO_ATTR_UNCONTROLLED,
    SUMO_ATTR_PASS,
    SUMO_ATTR_BUS_STOP,
    SUMO_ATTR_TRAIN_STOP,
    SUMO_ATTR_CONTAINER_STOP,
    SUMO_ATTR_PARKING_AREA,
    SUMO_ATTR_ROADSIDE_CAPACITY,
    SUMO_ATTR_ONROAD,
    SUMO_ATTR_CHARGING_STATION,
    SUMO_ATTR_GROUP,
    SUMO_ATTR_LINE,
    SUMO_ATTR_LINES,
    SUMO_ATTR_TRIP_ID,
    SUMO_ATTR_SPLIT,
    SUMO_ATTR_JOIN,
    SUMO_ATTR_INTENDED,
    SUMO_ATTR_VALUE,
    SUMO_ATTR_PROHIBITOR,
    SUMO_ATTR_PROHIBITED,
    SUMO_ATTR_ALLOW,
    SUMO_ATTR_DISALLOW,
    SUMO_ATTR_PREFER,
    SUMO_ATTR_CHANGE_LEFT,
    SUMO_ATTR_CHANGE_RIGHT,
    SUMO_ATTR_CONTROLLED_INNER,
    SUMO_ATTR_VEHSPERHOUR,
    SUMO_ATTR_PERSONSPERHOUR,
    SUMO_ATTR_CONTAINERSPERHOUR,
    SUMO_ATTR_PERHOUR,
    SUMO_ATTR_OUTPUT,
    SUMO_ATTR_HEIGHT,
    SUMO_ATTR_GUISHAPE,
    SUMO_ATTR_OSGFILE,
    SUMO_ATTR_IMGFILE,
    SUMO_ATTR_RELATIVEPATH,
    SUMO_ATTR_EMISSIONCLASS,
    SUMO_ATTR_IMPATIENCE,
    SUMO_ATTR_STARTPOS,
    SUMO_ATTR_ENDPOS,
    SUMO_ATTR_TRIGGERED,
    SUMO_ATTR_CONTAINER_TRIGGERED,
    SUMO_ATTR_PARKING,
    SUMO_ATTR_EXPECTED,
    SUMO_ATTR_PERMITTED,
    SUMO_ATTR_EXPECTED_CONTAINERS,
    SUMO_ATTR_INDEX,

    SUMO_ATTR_ENTERING,
    SUMO_ATTR_EXCLUDE_EMPTY,
    SUMO_ATTR_WITH_INTERNAL,
    SUMO_ATTR_TRACK_VEHICLES,
    SUMO_ATTR_DETECT_PERSONS,
    SUMO_ATTR_MAX_TRAVELTIME,
    SUMO_ATTR_MIN_SAMPLES,
    SUMO_ATTR_WRITE_ATTRIBUTES,

    SUMO_ATTR_LON,
    SUMO_ATTR_LAT,
    SUMO_ATTR_GEO,
    SUMO_ATTR_GEOSHAPE,
    SUMO_ATTR_K,
    SUMO_ATTR_V,
    SUMO_ATTR_REF,
    SUMO_ATTR_HREF,
    SUMO_ATTR_ZOOM,
    SUMO_ATTR_INTERPOLATED,
    SUMO_ATTR_THRESHOLD,

    SUMO_ATTR_NET_OFFSET,
    SUMO_ATTR_CONV_BOUNDARY,
    SUMO_ATTR_ORIG_BOUNDARY,
    SUMO_ATTR_ORIG_PROJ,

    /// @name car-following model attributes
    /// @{
    SUMO_ATTR_CF_PWAGNER2009_TAULAST,
    SUMO_ATTR_CF_PWAGNER2009_APPROB,
    SUMO_ATTR_CF_IDM_DELTA,
    SUMO_ATTR_CF_IDM_STEPPING,
    SUMO_ATTR_CF_IDMM_ADAPT_FACTOR,
    SUMO_ATTR_CF_IDMM_ADAPT_TIME,
    SUMO_ATTR_CF_KERNER_PHI,
    SUMO_ATTR_CF_WIEDEMANN_SECURITY,
    SUMO_ATTR_CF_WIEDEMANN_ESTIMATION,
    SUMO_ATTR_CF_W99_CC1,
    SUMO_ATTR_CF_W99_CC2,
    SUMO_ATTR_CF_W99_CC3,
    SUMO_ATTR_CF_W99_CC4,
    SUMO_ATTR_CF_W99_CC5,
    SUMO_ATTR_CF_W99_CC6,
    SUMO_ATTR_CF_W99_CC7,
    SUMO_ATTR_CF_W99_CC8,
    SUMO_ATTR_CF_W99_CC9,

    SUMO_ATTR_CF_CC_CCDECEL,
    SUMO_ATTR_CF_CC_CONSTSPACING,
    SUMO_ATTR_CF_CC_KP,
    SUMO_ATTR_CF_CC_LAMBDA,
    SUMO_ATTR_CF_CC_C1,
    SUMO_ATTR_CF_CC_XI,
    SUMO_ATTR_CF_CC_OMEGAN,
    SUMO_ATTR_CF_CC_TAU,
    SUMO_ATTR_CF_CC_LANES_COUNT,
    SUMO_ATTR_CF_CC_CCACCEL,
    SUMO_ATTR_CF_CC_PLOEG_KP,
    SUMO_ATTR_CF_CC_PLOEG_KD,
    SUMO_ATTR_CF_CC_PLOEG_H,
    SUMO_ATTR_CF_CC_FLATBED_KA,
    SUMO_ATTR_CF_CC_FLATBED_KV,
    SUMO_ATTR_CF_CC_FLATBED_KP,
    SUMO_ATTR_CF_CC_FLATBED_D,
    SUMO_ATTR_CF_CC_FLATBED_H,
    /// @}

    SUMO_ATTR_GENERATE_WALKS,
    SUMO_ATTR_ACTTYPE,
    SUMO_ATTR_CORNERDETAIL,
    SUMO_ATTR_LINKDETAIL,
    SUMO_ATTR_RECTANGULAR_LANE_CUT,
    SUMO_ATTR_WALKINGAREAS,
    SUMO_ATTR_LEFTHAND,
    SUMO_ATTR_LIMIT_TURN_SPEED,
    SUMO_ATTR_CHECKLANEFOES_ALL,
    SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT,
    SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM,
    SUMO_ATTR_AVOID_OVERLAP,
    SUMO_ATTR_HIGHER_SPEED,
    SUMO_ATTR_COMMAND,

    SUMO_ATTR_ACTORCONFIG,
    SUMO_ATTR_STARTTIME,
    SUMO_ATTR_VEHICLECLASS,
    SUMO_ATTR_FUEL,
    SUMO_ATTR_ORIGIN,
    SUMO_ATTR_DESTINATION,
    SUMO_ATTR_VISIBLE,
    SUMO_ATTR_LIMIT,
    SUMO_ATTR_ARRIVALTIME,
    SUMO_ATTR_ARRIVALTIMEBRAKING,
    SUMO_ATTR_ARRIVALSPEEDBRAKING,

    /// @name ActivityGen Tags
    /// @{

    /// @name general object
    /// @{
    AGEN_ATTR_INHABITANTS,
    AGEN_ATTR_HOUSEHOLDS,
    AGEN_ATTR_CHILDREN,
    AGEN_ATTR_RETIREMENT,
    AGEN_ATTR_CARS,
    AGEN_ATTR_UNEMPLOYEMENT,
    AGEN_ATTR_LABORDEMAND,
    AGEN_ATTR_MAX_FOOT_DIST,
    AGEN_ATTR_IN_TRAFFIC,
    AGEN_ATTR_OUT_TRAFFIC,
    /// @}

    /// @name streets object
    /// @{
    //SUMO_ATTR_EDGE already defined
    AGEN_ATTR_POPULATION,
    AGEN_ATTR_OUT_WORKPOSITION,
    /// @}

    /// @name workHours object
    /// @{
    AGEN_ATTR_HOUR,
    AGEN_ATTR_PROP,
    /// @}

    /// @name school object
    /// @{
    //SUMO_ATTR_EDGE, SUMO_ATTR_POSITION, SUMO_ATTR_TYPE already defined
    AGEN_ATTR_CAPACITY,
    AGEN_ATTR_OPENING,
    AGEN_ATTR_CLOSING,
    /// @}

    /// @name busStation and Bus objects
    /// @{
    // ID, EDGE, POSITION, REFID, BEGIN and END are already defined
    AGEN_ATTR_MAX_TRIP_DURATION,
    //AGEN_ATTR_ORDER,
    AGEN_ATTR_RATE,
    /// @}

    /// @name population and children accompaniment brackets
    /// @{
    AGEN_ATTR_BEGINAGE,
    AGEN_ATTR_ENDAGE,
    AGEN_ATTR_PEOPLENBR,
    /// @}

    /// @name parameters
    /// @{
    AGEN_ATTR_CARPREF,
    AGEN_ATTR_CITYSPEED,
    AGEN_ATTR_FREETIMERATE,
    AGEN_ATTR_UNI_RAND_TRAFFIC,
    AGEN_ATTR_DEP_VARIATION,
    /// @}

    /// @name city gates
    /// @{
    AGEN_ATTR_INCOMING,
    AGEN_ATTR_OUTGOING,
    /// @}
    /// @}

    //@name Netedit Attributes (used as virtual property holders, must be in SumoXMLAttr)
    //@{
    /// @brief element is selected
    GNE_ATTR_SELECTED,
    /// @brief whether a feature has been loaded,guessed,modified or approved
    GNE_ATTR_MODIFICATION_STATUS,
    /// @brief first coordinate of edge shape
    GNE_ATTR_SHAPE_START,
    /// @brief last coordinate of edge shape
    GNE_ATTR_SHAPE_END,
    /// @brief whether an edge is part of a bidirectional railway
    GNE_ATTR_BIDIR,
    /// @brief Close shape of a polygon (Used by GNEPolys)
    GNE_ATTR_CLOSE_SHAPE,
    /// @brief parent of an additional element
    GNE_ATTR_PARENT,
    /// @brief data set of a generic data
    GNE_ATTR_DATASET,
    /// @brief parameters "key1=value1|key2=value2|...|keyN=valueN"
    GNE_ATTR_PARAMETERS,
    /// @brief min source (used only by TAZs)
    GNE_ATTR_MIN_SOURCE,
    /// @brief min sink (used only by TAZs)
    GNE_ATTR_MIN_SINK,
    /// @brief max source (used only by TAZs)
    GNE_ATTR_MAX_SOURCE,
    /// @brief max sink (used only by TAZs)
    GNE_ATTR_MAX_SINK,
    /// @brief average source (used only by TAZs)
    GNE_ATTR_AVERAGE_SOURCE,
    /// @brief average sink (used only by TAZs)
    GNE_ATTR_AVERAGE_SINK,
    /// @brief Color of TAZSources/TAZSinks
    GNE_ATTR_TAZCOLOR,
    /// @brief Flag to check if VType is a default VType
    GNE_ATTR_DEFAULT_VTYPE,
    /// @brief Flag to check if a default VType was modified
    GNE_ATTR_DEFAULT_VTYPE_MODIFIED,
    /// @brief flag to center camera after element creation
    GNE_ATTR_CENTER_AFTER_CREATION,
    /// @brief to busStop (used by personPlans)
    GNE_ATTR_TO_BUSSTOP,
    /// @brief to busStop (used by containerPlans)
    GNE_ATTR_TO_CONTAINERSTOP,
    /// @brief neighboring lane, simplified lane attr instead of child element
    GNE_ATTR_OPPOSITE,
    /// @brief shift lane index (only used by elements over lanes)
    GNE_ATTR_SHIFTLANEINDEX,
    /// @brief stop offset (virtual, used by edge and lanes)
    GNE_ATTR_STOPOFFSET,
    /// @brief stop exceptions (virtual, used by edge and lanes)
    GNE_ATTR_STOPOEXCEPTION,

    // @}

    /// @name train parameters
    /// @{
    SUMO_ATTR_CARRIAGE_LENGTH,
    SUMO_ATTR_LOCOMOTIVE_LENGTH,
    SUMO_ATTR_CARRIAGE_GAP,
    /// @}

    SUMO_ATTR_TARGETLANE,
    SUMO_ATTR_CROSSING,
    SUMO_ATTR_XMLNS,
    SUMO_ATTR_SCHEMA_LOCATION,

    //@name RNG state saving attributes
    // @{
    SUMO_ATTR_RNG_ROUTEHANDLER,
    SUMO_ATTR_RNG_INSERTIONCONTROL,
    SUMO_ATTR_RNG_DEVICE,
    SUMO_ATTR_RNG_DEVICE_BT,
    SUMO_ATTR_RNG_DEVICE_TOC,
    SUMO_ATTR_RNG_DRIVERSTATE,
    // @}

    //@name meso edge type attributes
    // @{
    SUMO_ATTR_MESO_TAUFF,
    SUMO_ATTR_MESO_TAUFJ,
    SUMO_ATTR_MESO_TAUJF,
    SUMO_ATTR_MESO_TAUJJ,
    SUMO_ATTR_MESO_JUNCTION_CONTROL,
    SUMO_ATTR_MESO_TLS_PENALTY,
    SUMO_ATTR_MESO_TLS_FLOW_PENALTY,
    SUMO_ATTR_MESO_MINOR_PENALTY,
    SUMO_ATTR_MESO_OVERTAKING
    // @}
};

/*
 * @brief definitions of special SumoXML-attribute values.
 * Since these enums shall be used in switch statements we keep them separated
 * @{
 */

/**
 * SumoXMLParam Key Constants. Since all usage contexts needs strings rather
 * than enum values we do not bother with a StringBijection
 */
extern const std::string SUMO_PARAM_ORIGID;

/**
 * @enum SumoXMLNodeType
 * @brief Numbers representing special SUMO-XML-attribute values
 * for representing node- (junction-) types used in netbuild/netimport and netload
 */
enum class SumoXMLNodeType {
    UNKNOWN, // terminator
    TRAFFIC_LIGHT,
    TRAFFIC_LIGHT_NOJUNCTION, // junction controlled only by traffic light but without other prohibitions,
    TRAFFIC_LIGHT_RIGHT_ON_RED,
    RAIL_SIGNAL,
    RAIL_CROSSING,
    PRIORITY,
    PRIORITY_STOP, // like priority but all minor links have stop signs
    RIGHT_BEFORE_LEFT,
    ALLWAY_STOP,
    ZIPPER,
    DISTRICT,
    NOJUNCTION,
    INTERNAL,
    DEAD_END,
    DEAD_END_DEPRECATED
};


/**
 * @enum SumoXMLEdgeFunc
 * @brief Numbers representing special SUMO-XML-attribute values
 * for representing edge functions used in netbuild/netimport and netload
 */
enum class SumoXMLEdgeFunc {
    UNKNOWN,
    NORMAL,
    CONNECTOR,
    CROSSING,
    WALKINGAREA,
    INTERNAL
};


/**
 * @enum LaneSpreadFunction
 * @brief Numbers representing special SUMO-XML-attribute values
 * Information how the edge's lateral offset shall be computed
 * In dependence to this value, lanes will be spread to the right side or
 * to both sides from the given edge geometry (Also used when node
 * positions are used as edge geometry).
 */
enum class LaneSpreadFunction {
    RIGHT = 0,
    ROADCENTER = 1,
    CENTER = 2
};


/// @brief algorithms for computing right of way
enum class RightOfWay {
    DEFAULT,
    EDGEPRIORITY
};

/// @brief classifying boundary nodes
enum class FringeType {
    // outer border of the network
    OUTER,
    // fringe edge within the network (i.e. due to pruning some road types)
    INNER,
    // not fringe (nothing is cut off)
    DEFAULT
};

/// @brief travel modes for persons
enum class PersonMode {
    NONE = 0,
    WALK_FORWARD = 1,
    WALK_BACKWARD = 2,
    WALK = 3,
    BICYCLE = 1 << 2,
    CAR = 1 << 3,
    PUBLIC = 1 << 4,
    TAXI = 1 << 5
};

/**
 * @enum LinkState
 * @brief The right-of-way state of a link between two lanes
 * used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane
 *
 * This enumerations holds the possible right-of-way rules a link
 *  may have. Beyond the righ-of-way rules, this enumeration also
 *  holds the possible traffic light states.
 *
 *  enum values are assigned so that chars can be cast back to linkstates
 *  @todo fix redundancy
 */
enum LinkState {
    /// @brief The link has green light, may pass
    LINKSTATE_TL_GREEN_MAJOR = 'G',
    /// @brief The link has green light, has to brake
    LINKSTATE_TL_GREEN_MINOR = 'g',
    /// @brief The link has red light (must brake)
    LINKSTATE_TL_RED = 'r',
    /// @brief The link has red light (must brake) but indicates upcoming green
    LINKSTATE_TL_REDYELLOW = 'u',
    /// @brief The link has yellow light, may pass
    LINKSTATE_TL_YELLOW_MAJOR = 'Y',
    /// @brief The link has yellow light, has to brake anyway
    LINKSTATE_TL_YELLOW_MINOR = 'y',
    /// @brief The link is controlled by a tls which is off and blinks, has to brake
    LINKSTATE_TL_OFF_BLINKING = 'o',
    /// @brief The link is controlled by a tls which is off, not blinking, may pass
    LINKSTATE_TL_OFF_NOSIGNAL = 'O',
    /// @brief This is an uncontrolled, major link, may pass
    LINKSTATE_MAJOR = 'M',
    /// @brief This is an uncontrolled, minor link, has to brake
    LINKSTATE_MINOR = 'm',
    /// @brief This is an uncontrolled, right-before-left link
    LINKSTATE_EQUAL = '=',
    /// @brief This is an uncontrolled, minor link, has to stop
    LINKSTATE_STOP = 's',
    /// @brief This is an uncontrolled, all-way stop link.
    LINKSTATE_ALLWAY_STOP = 'w',
    /// @brief This is an uncontrolled, zipper-merge link
    LINKSTATE_ZIPPER = 'Z',
    /// @brief This is a dead end link
    LINKSTATE_DEADEND = '-'
};

/**
 * @enum LinkDirection
 * @brief The different directions a link between two lanes may take (or a
 * stream between two edges).
 * used in netbuild (formerly NBMMLDirection) and MSLink
 */
enum class LinkDirection {
    /// @brief The link is a (hard) right direction
    RIGHT = 0,
    /// @brief The link is a partial right direction
    PARTRIGHT,
    /// @brief The link is a straight direction
    STRAIGHT,
    /// @brief The link is a partial left direction
    PARTLEFT,
    /// @brief The link is a (hard) left direction
    LEFT,
    /// @brief The link is a 180 degree turn
    TURN,
    /// @brief The link is a 180 degree turn (left-hand network)
    TURN_LEFTHAND,
    /// @brief The link has no direction (is a dead end link)
    NODIR
};


/// @enum TrafficLightType
enum class TrafficLightType {
    STATIC,
    RAIL_SIGNAL,
    RAIL_CROSSING,
    ACTUATED,
    DELAYBASED,
    SOTL_PHASE,
    SOTL_PLATOON,
    SOTL_REQUEST,
    SOTL_WAVE,
    SOTL_MARCHING,
    SWARM_BASED,
    HILVL_DETERMINISTIC,
    OFF,
    INVALID //< must be the last one
};

/// @enum TrafficLightLayout
enum class TrafficLightLayout {
    OPPOSITES,
    INCOMING,
    ALTERNATE_ONEWAY,
    DEFAULT //< must be the last one
};


/** @enum LaneChangeAction
 * @brief The state of a vehicle's lane-change behavior
 */
enum LaneChangeAction {
    /// @name currently wanted lane-change action
    /// @{
    /// @brief No action desired
    LCA_NONE = 0,
    /// @brief Needs to stay on the current lane
    LCA_STAY = 1 << 0,
    /// @brief Wants go to the left
    LCA_LEFT = 1 << 1,
    /// @brief Wants go to the right
    LCA_RIGHT = 1 << 2,
    /// @brief The action is needed to follow the route (navigational lc)
    LCA_STRATEGIC = 1 << 3,
    /// @brief The action is done to help someone else
    LCA_COOPERATIVE = 1 << 4,
    /// @brief The action is due to the wish to be faster (tactical lc)
    LCA_SPEEDGAIN = 1 << 5,
    /// @brief The action is due to the default of keeping right "Rechtsfahrgebot"
    LCA_KEEPRIGHT = 1 << 6,
    /// @brief The action is due to a TraCI request
    LCA_TRACI = 1 << 7,
    /// @brief The action is urgent (to be defined by lc-model)
    LCA_URGENT = 1 << 8,
    /// @brief The action has not been determined
    LCA_UNKNOWN = 1 << 30,
    /// @}

    /// @name External state
    /// @{
    /// @brief The vehicle is blocked by left leader
    LCA_BLOCKED_BY_LEFT_LEADER = 1 << 9,
    /// @brief The vehicle is blocked by left follower
    LCA_BLOCKED_BY_LEFT_FOLLOWER = 1 << 10,
    /// @brief The vehicle is blocked by right leader
    LCA_BLOCKED_BY_RIGHT_LEADER = 1 << 11,
    /// @brief The vehicle is blocked by right follower
    LCA_BLOCKED_BY_RIGHT_FOLLOWER = 1 << 12,
    /// @brief The vehicle is blocked being overlapping
    LCA_OVERLAPPING = 1 << 13,
    /// @brief The vehicle does not have enough space to complete a continuous change before the next turn
    LCA_INSUFFICIENT_SPACE = 1 << 14,
    /// @brief used by the sublane model
    LCA_SUBLANE = 1 << 15,
    /// @brief Vehicle is too slow to complete a continuous lane change (in case that maxSpeedLatStanding==0)
    LCA_INSUFFICIENT_SPEED = 1 << 28,
    /// @brief lane can change
    LCA_WANTS_LANECHANGE = LCA_LEFT | LCA_RIGHT,
    /// @brief lane can change or stay
    LCA_WANTS_LANECHANGE_OR_STAY = LCA_WANTS_LANECHANGE | LCA_STAY,
    /// @brief blocked left
    LCA_BLOCKED_LEFT = LCA_BLOCKED_BY_LEFT_LEADER | LCA_BLOCKED_BY_LEFT_FOLLOWER,
    /// @brief blocked right
    LCA_BLOCKED_RIGHT = LCA_BLOCKED_BY_RIGHT_LEADER | LCA_BLOCKED_BY_RIGHT_FOLLOWER,
    /// @brief blocked by leader
    LCA_BLOCKED_BY_LEADER = LCA_BLOCKED_BY_LEFT_LEADER | LCA_BLOCKED_BY_RIGHT_LEADER,
    /// @brief blocker by follower
    LCA_BLOCKED_BY_FOLLOWER = LCA_BLOCKED_BY_LEFT_FOLLOWER | LCA_BLOCKED_BY_RIGHT_FOLLOWER,
    /// @brief blocked in all directions
    LCA_BLOCKED = LCA_BLOCKED_LEFT | LCA_BLOCKED_RIGHT | LCA_INSUFFICIENT_SPACE | LCA_INSUFFICIENT_SPEED,
    /// @brief reasons of lane change
    LCA_CHANGE_REASONS = (LCA_STRATEGIC | LCA_COOPERATIVE | LCA_SPEEDGAIN | LCA_KEEPRIGHT | LCA_SUBLANE | LCA_TRACI),
    // LCA_BLOCKED_BY_CURRENT_LEADER = 1 << 28
    // LCA_BLOCKED_BY_CURRENT_FOLLOWER = 1 << 29
    /// @}

    /// @name originally model specific states (migrated here since
    ///       they were duplicated in all current models)
    /// @{
    LCA_AMBLOCKINGLEADER = 1 << 16,
    LCA_AMBLOCKINGFOLLOWER = 1 << 17,
    LCA_MRIGHT = 1 << 18,
    LCA_MLEFT = 1 << 19,
    // !!! never set LCA_UNBLOCK = 1 << 20,
    LCA_AMBLOCKINGFOLLOWER_DONTBRAKE = 1 << 21,
    // !!! never used LCA_AMBLOCKINGSECONDFOLLOWER = 1 << 22,
    LCA_CHANGE_TO_HELP = 1 << 23,
    // !!! never read LCA_KEEP1 = 1 << 24,
    // !!! never used LCA_KEEP2 = 1 << 25,
    LCA_AMBACKBLOCKER = 1 << 26,
    LCA_AMBACKBLOCKER_STANDING = 1 << 27
                                 /// @}
};


/// @enum LaneChangeModel
enum LaneChangeModel {
    LCM_DK2008,
    LCM_LC2013,
    LCM_SL2015,
    LCM_DEFAULT
};

/// @enum train types
enum TrainType {
    TRAINTYPE_NGT400,
    TRAINTYPE_NGT400_16,
    TRAINTYPE_RB425,
    TRAINTYPE_RB628,
    TRAINTYPE_ICE1,
    TRAINTYPE_REDOSTO7,
    TRAINTYPE_FREIGHT,
    TRAINTYPE_ICE3,
    TRAINTYPE_UNKNOWN
};

// @}

/**
 * @class SUMOXMLDefinitions
 * @brief class for maintaining associations between enums and xml-strings
 */
class SUMOXMLDefinitions {

public:
    /// @brief The names of SUMO-XML elements (for passing to GenericSAXHandler)
    static StringBijection<int>::Entry tags[];

    /// @brief The names of SUMO-XML attributes (for passing to GenericSAXHandler)
    static StringBijection<int>::Entry attrs[];

    /// @brief The names of SUMO-XML elements for use in netbuild
    static StringBijection<int> Tags;

    /// @brief The names of SUMO-XML attributes for use in netbuild
    static StringBijection<int> Attrs;

    /// @name Special values of SUMO-XML attributes
    /// @{

    /// @brief node types
    static StringBijection<SumoXMLNodeType> NodeTypes;

    /// @brief edge functions
    static StringBijection<SumoXMLEdgeFunc> EdgeFunctions;

    /// @brief lane spread functions
    static StringBijection<LaneSpreadFunction> LaneSpreadFunctions;

    /// @brief righ of way algorithms
    static StringBijection<RightOfWay> RightOfWayValues;

    /// @brief fringe types
    static StringBijection<FringeType> FringeTypeValues;

    /// @brief person modes
    static StringBijection<PersonMode> PersonModeValues;

    /// @brief link states
    static StringBijection<LinkState> LinkStates;

    /// @brief link directions
    static StringBijection<LinkDirection> LinkDirections;

    /// @brief traffic light types
    static StringBijection<TrafficLightType> TrafficLightTypes;

    /// @brief traffic light layouts
    static StringBijection<TrafficLightLayout> TrafficLightLayouts;

    /// @brief lane change models
    static StringBijection<LaneChangeModel> LaneChangeModels;

    /// @brief car following models
    static StringBijection<SumoXMLTag> CarFollowModels;

    /// @brief lane change actions
    static StringBijection<LaneChangeAction> LaneChangeActions;

    /// @brief train types
    static StringBijection<TrainType> TrainTypes;
    /// @}

    /// @name Helper functions for ID-string manipulations
    /// @{

    /// @brief whether the given string is a valid id for a network element
    static bool isValidNetID(const std::string& value);

    /// @brief whether the given string is a valid id for a vehicle or flow
    static bool isValidVehicleID(const std::string& value);

    /// @brief whether the given string is a valid id for an edge or vehicle type
    static bool isValidTypeID(const std::string& value);

    /// @brief whether the given string is a valid id for an additional object
    static bool isValidAdditionalID(const std::string& value);

    /// @brief whether the given string is a valid id for an detector
    static bool isValidDetectorID(const std::string& value);

    /// @brief whether the given string is a valid attribute for a certain key (for example, a name)
    static bool isValidAttribute(const std::string& value);

    /// @brief whether the given string is a valid attribute for a filename (for example, a name)
    static bool isValidFilename(const std::string& value);

    /// @brief whether the given string is a valid list of id for a network (empty aren't allowed)
    static bool isValidListOfNetIDs(const std::string& value);

    /// @brief whether the given string is a valid list of ids for an edge or vehicle type (empty aren't allowed)
    static bool isValidListOfTypeID(const std::string& value);

    /// @brief whether the given list of strings is a valid list of ids for an edge or vehicle type (empty aren't allowed)
    static bool isValidListOfTypeID(const std::vector<std::string>& typeIDs);

    /// @brief whether the given string is a valid key for a parameter
    static bool isValidParameterKey(const std::string& value);

    /// @brief return the junction id when given an edge of type internal, crossing or WalkingArea
    static std::string getJunctionIDFromInternalEdge(const std::string internalEdge);

    /// @brief return edge id when given the lane ID
    static std::string getEdgeIDFromLane(const std::string laneID);

    /// @brief return lane index when given the lane ID
    static int getIndexFromLane(const std::string laneID);
    /// @}

    /// @brief all allowed characters for phase state
    static const std::string ALLOWED_TLS_LINKSTATES;



private:
    /// @brief containers for the different SUMOXMLDefinitions
    /// @{

    /// @brief node type values
    static StringBijection<SumoXMLNodeType>::Entry sumoNodeTypeValues[];

    /// @brief edge function values
    static StringBijection<SumoXMLEdgeFunc>::Entry sumoEdgeFuncValues[];

    /// @brief lane spread function values
    static StringBijection<LaneSpreadFunction>::Entry laneSpreadFunctionValues[];

    /// @brief lane spread function values
    static StringBijection<RightOfWay>::Entry rightOfWayValuesInitializer[];

    /// @brief lane spread function values
    static StringBijection<FringeType>::Entry fringeTypeValuesInitializer[];

    /// @brief person mode values
    static StringBijection<PersonMode>::Entry personModeValuesInitializer[];

    /// @brief link state values
    static StringBijection<LinkState>::Entry linkStateValues[];

    /// @brief link direction values
    static StringBijection<LinkDirection>::Entry linkDirectionValues[];

    /// @brief traffic light types values
    static StringBijection<TrafficLightType>::Entry trafficLightTypesValues[];

    /// @brief traffic light layout values
    static StringBijection<TrafficLightLayout>::Entry trafficLightLayoutValues[];

    /// @brief lane change model values
    static StringBijection<LaneChangeModel>::Entry laneChangeModelValues[];

    /// @brief car follwing model values
    static StringBijection<SumoXMLTag>::Entry carFollowModelValues[];

    /// @brief lane change action values
    static StringBijection<LaneChangeAction>::Entry laneChangeActionValues[];

    /// @brief train type values values
    static StringBijection<TrainType>::Entry trainTypeValues[];
    /// @}

    /// @brief all allowed characters for phase state
    static const char AllowedTLS_linkStatesInitializer[];
};
/****************************************************************************/
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
// Copyright (C) 2002-2021 German Aerospace Center (DLR) and others.
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0/
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License 2.0 are satisfied: GNU General Public License, version 2
// or later which is available at
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
/****************************************************************************/
/// @file    SUMOXMLDefinitions.cpp
/// @author  Daniel Krajzewicz
/// @author  Jakob Erdmann
/// @author  Clemens Honomichl
/// @author  Piotr Woznica
/// @author  Michael Behrisch
/// @author  Walter Bamberger
/// @date    Sept 2002
///
// Definitions of elements and attributes known by SUMO
/****************************************************************************/
#include <config.h>

#include <cassert>
#include <utils/common/StringBijection.h>
#include <utils/common/StringTokenizer.h>
#include <utils/common/StringUtils.h>

#include "SUMOXMLDefinitions.h"

// ===========================================================================
// definitions
// ===========================================================================

StringBijection<int>::Entry SUMOXMLDefinitions::tags[] = {
    // Simulation elements
    { "net",                            SUMO_TAG_NET },
    { "edge",                           SUMO_TAG_EDGE },
    { "lane",                           SUMO_TAG_LANE },
    { "neigh",                          SUMO_TAG_NEIGH },
    { "poly",                           SUMO_TAG_POLY },
    { "poi",                            SUMO_TAG_POI },
    { "junction",                       SUMO_TAG_JUNCTION },
    { "restriction",                    SUMO_TAG_RESTRICTION },
    { "meso",                           SUMO_TAG_MESO },
    { "e1Detector",                     SUMO_TAG_E1DETECTOR },
    { "inductionLoop",                  SUMO_TAG_INDUCTION_LOOP },
    { "e2Detector",                     SUMO_TAG_E2DETECTOR },
    { "e2MultilaneDetector",            GNE_TAG_E2DETECTOR_MULTILANE },
    { "laneAreaDetector",               SUMO_TAG_LANE_AREA_DETECTOR },
    { "e3Detector",                     SUMO_TAG_E3DETECTOR },
    { "entryExitDetector",              SUMO_TAG_ENTRY_EXIT_DETECTOR },
    { "edgeData",                       SUMO_TAG_MEANDATA_EDGE },
    { "laneData",                       SUMO_TAG_MEANDATA_LANE },
    { "detEntry",                       SUMO_TAG_DET_ENTRY },
    { "detExit",                        SUMO_TAG_DET_EXIT },
    { "edgeFollowDetector",             SUMO_TAG_EDGEFOLLOWDETECTOR },
    { "instantInductionLoop",           SUMO_TAG_INSTANT_INDUCTION_LOOP },
    { "variableSpeedSign",              SUMO_TAG_VSS },
    { "calibrator",                     SUMO_TAG_CALIBRATOR },
    { "laneCalibrator",                 SUMO_TAG_LANECALIBRATOR },
    { "rerouter",                       SUMO_TAG_REROUTER },
    { "busStop",                        SUMO_TAG_BUS_STOP },
    { "trainStop",                      SUMO_TAG_TRAIN_STOP },
    { "ptLine",                         SUMO_TAG_PT_LINE },
    { "access",                         SUMO_TAG_ACCESS },
    { "containerStop",                  SUMO_TAG_CONTAINER_STOP },
    { "parkingArea",                    SUMO_TAG_PARKING_AREA },
    { "space",                          SUMO_TAG_PARKING_SPACE },
    { "chargingStation",                SUMO_TAG_CHARGING_STATION },
    { "overheadWireSegment",            SUMO_TAG_OVERHEAD_WIRE_SEGMENT },
    { "overheadWire",                   SUMO_TAG_OVERHEAD_WIRE_SECTION },
    { "tractionSubstation",             SUMO_TAG_TRACTION_SUBSTATION },
    { "overheadWireClamp",              SUMO_TAG_OVERHEAD_WIRE_CLAMP },
    { "vTypeProbe",                     SUMO_TAG_VTYPEPROBE },
    { "routeProbe",                     SUMO_TAG_ROUTEPROBE },
    { "routes",                         SUMO_TAG_ROUTES },
    { "vehicle",                        SUMO_TAG_VEHICLE },
    { "vType",                          SUMO_TAG_VTYPE },
    { "pType",                          SUMO_TAG_PTYPE },
    { "route",                          SUMO_TAG_ROUTE },
    { "request",                        SUMO_TAG_REQUEST },
    { "source",                         SUMO_TAG_SOURCE },
    { "taz",                            SUMO_TAG_TAZ },
    { "tazSource",                      SUMO_TAG_TAZSOURCE },
    { "tazSink",                        SUMO_TAG_TAZSINK },
    { "trafficLight",                   SUMO_TAG_TRAFFIC_LIGHT },
    { "tlLogic",                        SUMO_TAG_TLLOGIC },
    { "phase",                          SUMO_TAG_PHASE },
    { "trip",                           SUMO_TAG_TRIP },
    { "tripTAZ",                        SUMO_TAG_TRIP_TAZ },
    { "flow",                           SUMO_TAG_FLOW },
    { "flowState",                      SUMO_TAG_FLOWSTATE },
    { "step",                           SUMO_TAG_STEP },
    { "interval",                       SUMO_TAG_INTERVAL },
    { "edgeRelation",                   SUMO_TAG_EDGEREL },
    { "tazRelation",                    SUMO_TAG_TAZREL },
    { "timedEvent",                     SUMO_TAG_TIMEDEVENT },
    { "fromEdge",                       SUMO_TAG_FROMEDGE },
    { "toEdge",                         SUMO_TAG_TOEDGE },
    { "sink",                           SUMO_TAG_SINK },
    { "param",                          SUMO_TAG_PARAM },
    { "WAUT",                           SUMO_TAG_WAUT },
    { "wautSwitch",                     SUMO_TAG_WAUT_SWITCH },
    { "wautJunction",                   SUMO_TAG_WAUT_JUNCTION },
    { "segment",                        SUMO_TAG_SEGMENT },
    { "delete",                         SUMO_TAG_DEL },
    { "stop",                           SUMO_TAG_STOP },
    { "stopBusStop",                    SUMO_TAG_STOP_BUSSTOP },
    { "stopContainerStop",              SUMO_TAG_STOP_CONTAINERSTOP },
    { "stopChargingStation",            SUMO_TAG_STOP_CHARGINGSTATION },
    { "stopParkingArea",                SUMO_TAG_STOP_PARKINGAREA },
    { "stopLane",                       SUMO_TAG_STOP_LANE },
    { "destProbReroute",                SUMO_TAG_DEST_PROB_REROUTE },
    { "closingReroute",                 SUMO_TAG_CLOSING_REROUTE },
    { "closingLaneReroute",             SUMO_TAG_CLOSING_LANE_REROUTE },
    { "routeProbReroute",               SUMO_TAG_ROUTE_PROB_REROUTE },
    { "parkingAreaReroute",             SUMO_TAG_PARKING_ZONE_REROUTE },
    { "polygonType",                    SUMO_TAG_POLYTYPE },
    { "connection",                     SUMO_TAG_CONNECTION },
    { "prohibition",                    SUMO_TAG_PROHIBITION },
    { "split",                          SUMO_TAG_SPLIT },
    { "node",                           SUMO_TAG_NODE },
    { "type",                           SUMO_TAG_TYPE },
    { "laneType",                       SUMO_TAG_LANETYPE },
    { "detectorDefinition",             SUMO_TAG_DETECTOR_DEFINITION },
    { "routeDistribution",              SUMO_TAG_ROUTE_DISTRIBUTION },
    { "vTypeDistribution",              SUMO_TAG_VTYPE_DISTRIBUTION },
    { "vaporizer",                      SUMO_TAG_VAPORIZER },
    { "roundabout",                     SUMO_TAG_ROUNDABOUT },
    { "join",                           SUMO_TAG_JOIN },
    { "joinExclude",                    SUMO_TAG_JOINEXCLUDE },
    { "crossing",                       SUMO_TAG_CROSSING },
    { "walkingArea",                    SUMO_TAG_WALKINGAREA },
    { "stopOffset",                     SUMO_TAG_STOPOFFSET },
    { "railSignalConstraints",          SUMO_TAG_RAILSIGNAL_CONSTRAINTS },
    { "predecessor",                    SUMO_TAG_PREDECESSOR },
    { "insertionPredecessor",           SUMO_TAG_INSERTION_PREDECESSOR },
    { "railSignalConstraintTracker",    SUMO_TAG_RAILSIGNAL_CONSTRAINT_TRACKER },
    { "link",                           SUMO_TAG_LINK },
    { "approaching",                    SUMO_TAG_APPROACHING },
    // OSM
    { "way",                            SUMO_TAG_WAY },
    { "nd",                             SUMO_TAG_ND },
    { "tag",                            SUMO_TAG_TAG },
    { "relation",                       SUMO_TAG_RELATION },
    { "member",                         SUMO_TAG_MEMBER },
    // View
    { "viewsettings",                   SUMO_TAG_VIEWSETTINGS },
    { "decal",                          SUMO_TAG_VIEWSETTINGS_DECAL },
    { "light",                          SUMO_TAG_VIEWSETTINGS_LIGHT },
    { "scheme",                         SUMO_TAG_VIEWSETTINGS_SCHEME },
    { "opengl",                         SUMO_TAG_VIEWSETTINGS_OPENGL },
    { "background",                     SUMO_TAG_VIEWSETTINGS_BACKGROUND },
    { "edges",                          SUMO_TAG_VIEWSETTINGS_EDGES },
    { "vehicles",                       SUMO_TAG_VIEWSETTINGS_VEHICLES },
    { "persons",                        SUMO_TAG_VIEWSETTINGS_PERSONS },
    { "containers",                     SUMO_TAG_VIEWSETTINGS_CONTAINERS },
    { "junctions",                      SUMO_TAG_VIEWSETTINGS_JUNCTIONS },
    { "additionals",                    SUMO_TAG_VIEWSETTINGS_ADDITIONALS },
    { "pois",                           SUMO_TAG_VIEWSETTINGS_POIS },
    { "polys",                          SUMO_TAG_VIEWSETTINGS_POLYS },
    { "legend",                         SUMO_TAG_VIEWSETTINGS_LEGEND },
    { "event",                          SUMO_TAG_VIEWSETTINGS_EVENT },
    { "jamTime",                        SUMO_TAG_VIEWSETTINGS_EVENT_JAM_TIME },
    { "include",                        SUMO_TAG_INCLUDE },
    { "delay",                          SUMO_TAG_DELAY },
    { "viewport",                       SUMO_TAG_VIEWPORT },
    { "snapshot",                       SUMO_TAG_SNAPSHOT },
    { "breakpoint",                     SUMO_TAG_BREAKPOINT },
    { "location",                       SUMO_TAG_LOCATION },
    { "colorScheme",                    SUMO_TAG_COLORSCHEME },
    { "scalingScheme",                  SUMO_TAG_SCALINGSCHEME },
    { "entry",                          SUMO_TAG_ENTRY },
    { "rngState",                       SUMO_TAG_RNGSTATE },
    { "rngLane",                        SUMO_TAG_RNGLANE },
    { "vehicleTransfer",                SUMO_TAG_VEHICLETRANSFER },
    { "device",                         SUMO_TAG_DEVICE },
    // Cars
    { "carFollowing-IDM",               SUMO_TAG_CF_IDM },
    { "carFollowing-IDMM",              SUMO_TAG_CF_IDMM },
    { "carFollowing-Krauss",            SUMO_TAG_CF_KRAUSS },
    { "carFollowing-KraussPS",          SUMO_TAG_CF_KRAUSS_PLUS_SLOPE },
    { "carFollowing-KraussOrig1",       SUMO_TAG_CF_KRAUSS_ORIG1 },
    { "carFollowing-KraussX",           SUMO_TAG_CF_KRAUSSX },
    { "carFollowing-EIDM",              SUMO_TAG_CF_EIDM },
    { "carFollowing-SmartSK",           SUMO_TAG_CF_SMART_SK },
    { "carFollowing-Daniel1",           SUMO_TAG_CF_DANIEL1 },
    { "carFollowing-PWagner2009",       SUMO_TAG_CF_PWAGNER2009 },
    { "carFollowing-BKerner",           SUMO_TAG_CF_BKERNER },
    { "carFollowing-Wiedemann",         SUMO_TAG_CF_WIEDEMANN },
    { "carFollowing-W99",               SUMO_TAG_CF_W99 },
    { "carFollowing-Rail",              SUMO_TAG_CF_RAIL },
    { "carFollowing-ACC",               SUMO_TAG_CF_ACC },
    { "carFollowing-CACC",              SUMO_TAG_CF_CACC },
    { "carFollowing-CC",                SUMO_TAG_CF_CC },
    { "carFollowing-GM",                SUMO_TAG_CF_GM },
    // Person
    { "person",                         SUMO_TAG_PERSON },
    { "personTrip",                     SUMO_TAG_PERSONTRIP },
    { "ride",                           SUMO_TAG_RIDE },
    { "walk",                           SUMO_TAG_WALK },
    { "personFlow",                     SUMO_TAG_PERSONFLOW },
    // Data (Netedit)
    { "dataSet",                        SUMO_TAG_DATASET },
    { "dataInterval",                   SUMO_TAG_DATAINTERVAL },
    // Transport
    { "container",                      SUMO_TAG_CONTAINER },
    { "transport",                      SUMO_TAG_TRANSPORT },
    { "tranship",                       SUMO_TAG_TRANSHIP },
    { "containerFlow",					SUMO_TAG_CONTAINERFLOW },
    //Trajectories
    { "trajectories",                   SUMO_TAG_TRAJECTORIES },
    { "timestep",                       SUMO_TAG_TIMESTEP },
    { "timeSlice",                      SUMO_TAG_TIMESLICE },
    { "actorConfig",                    SUMO_TAG_ACTORCONFIG },
    { "motionState",                    SUMO_TAG_MOTIONSTATE },
    { "odPair",                         SUMO_TAG_OD_PAIR },
    { "transportables",                 SUMO_TAG_TRANSPORTABLES },
    // ActivityGen statistics file
    { "general",                        AGEN_TAG_GENERAL },
    { "street",                         AGEN_TAG_STREET },
    { "workHours",                      AGEN_TAG_WORKHOURS },
    { "opening",                        AGEN_TAG_OPENING },
    { "closing",                        AGEN_TAG_CLOSING },
    { "schools",                        AGEN_TAG_SCHOOLS },
    { "school",                         AGEN_TAG_SCHOOL },
    { "busStation",                     AGEN_TAG_BUSSTATION },
    { "busLine",                        AGEN_TAG_BUSLINE },
    { "stations",                       AGEN_TAG_STATIONS },
    { "revStations",                    AGEN_TAG_REV_STATIONS },
    { "station",                        AGEN_TAG_STATION },
    { "frequency",                      AGEN_TAG_FREQUENCY },
    { "population",                     AGEN_TAG_POPULATION },
    { "bracket",                        AGEN_TAG_BRACKET },
    { "cityGates",                      AGEN_TAG_CITYGATES },
    { "entrance",                       AGEN_TAG_ENTRANCE },
    { "parameters",                     AGEN_TAG_PARAM },
    // NETEDIT
    { "internalLane",                   GNE_TAG_INTERNAL_LANE },
    { "flowCalibrator",                 GNE_TAG_FLOW_CALIBRATOR },
    { "poiLane",                        GNE_TAG_POILANE },
    { "poiGeo",                         GNE_TAG_POIGEO },
    { "rerouterSymbol",                 GNE_TAG_REROUTER_SYMBOL },
    { "variableSpeedSignSymbol",        GNE_TAG_VSS_SYMBOL },
    { "vehicleWithRoute",               GNE_TAG_VEHICLE_WITHROUTE },
    { "routeEmbedded",                  GNE_TAG_ROUTE_EMBEDDED },
    { "flowRoute",                      GNE_TAG_FLOW_ROUTE },
    { "flowWithRoute",                  GNE_TAG_FLOW_WITHROUTE },
    // GNE Person trips
    { "personTrip: edge->edge",         GNE_TAG_PERSONTRIP_EDGE },
    { "personTrip: edge->busStop",      GNE_TAG_PERSONTRIP_BUSSTOP },
    // GNE Walks
    { "walk: edge->edge",               GNE_TAG_WALK_EDGE },
    { "walk: edge->busStop",            GNE_TAG_WALK_BUSSTOP },
    { "walk: edges",                    GNE_TAG_WALK_EDGES },
    { "walk: route",                    GNE_TAG_WALK_ROUTE },
    // GNE Rides
    { "ride: edge->edge",               GNE_TAG_RIDE_EDGE },
    { "ride: edge->busStop",            GNE_TAG_RIDE_BUSSTOP },
    // GNE person Stops
    { "stopPerson: busStop",            GNE_TAG_STOPPERSON_BUSSTOP },
    { "stopPerson: edge",               GNE_TAG_STOPPERSON_EDGE },
    // GNE transports
    { "transport: edge->edge",          GNE_TAG_TRANSPORT_EDGE },
    { "transport: edge->containerStop", GNE_TAG_TRANSPORT_CONTAINERSTOP },
    // GNE tranships
    { "tranship: edge->edge",           GNE_TAG_TRANSHIP_EDGE },
    { "tranship: edge->containerStop",  GNE_TAG_TRANSHIP_CONTAINERSTOP },
    { "tranship: edges",                GNE_TAG_TRANSHIP_EDGES },
    // GNE container Stops
    { "stopContainer: containerStop",   GNE_TAG_STOPCONTAINER_CONTAINERSTOP },
    { "stopContainer: edge",            GNE_TAG_STOPCONTAINER_EDGE },
    // root file
    { "rootFile",                       SUMO_TAG_ROOTFILE },
    // Last element
    { "",                               SUMO_TAG_NOTHING }  // -> must be the last one
};


StringBijection<int>::Entry SUMOXMLDefinitions::attrs[] = {
    // meta value for attribute enum
    { "default",                SUMO_ATTR_DEFAULT },
    // meandata
    { "sampledSeconds",         SUMO_ATTR_SAMPLEDSECONDS },
    { "density",                SUMO_ATTR_DENSITY },
    { "laneDensity",            SUMO_ATTR_LANEDENSITY },
    { "occupancy",              SUMO_ATTR_OCCUPANCY },
    { "waitingTime",            SUMO_ATTR_WAITINGTIME },
    { "timeLoss",               SUMO_ATTR_TIMELOSS },
    { "speed",                  SUMO_ATTR_SPEED },
    { "departed",               SUMO_ATTR_DEPARTED },
    { "arrived",                SUMO_ATTR_ARRIVED },
    { "entered",                SUMO_ATTR_ENTERED },
    { "left",                   SUMO_ATTR_LEFT },
    { "vaporized",              SUMO_ATTR_VAPORIZED },
    { "traveltime",             SUMO_ATTR_TRAVELTIME },
    { "laneChangedFrom",        SUMO_ATTR_LANECHANGEDFROM },
    { "laneChangedTo",          SUMO_ATTR_LANECHANGEDTO },
    { "overlapTraveltime",      SUMO_ATTR_OVERLAPTRAVELTIME },
    { "CO_abs",                 SUMO_ATTR_CO_ABS },
    { "CO2_abs",                SUMO_ATTR_CO2_ABS },
    { "HC_abs",                 SUMO_ATTR_HC_ABS },
    { "PMx_abs",                SUMO_ATTR_PMX_ABS },
    { "NOx_abs",                SUMO_ATTR_NOX_ABS },
    { "fuel_abs",               SUMO_ATTR_FUEL_ABS },
    { "electricity_abs",        SUMO_ATTR_ELECTRICITY_ABS },
    { "CO_normed",              SUMO_ATTR_CO_NORMED },
    { "CO2_normed",             SUMO_ATTR_CO2_NORMED },
    { "HC_normed",              SUMO_ATTR_HC_NORMED },
    { "PMx_normed",             SUMO_ATTR_PMX_NORMED },
    { "NOx_normed",             SUMO_ATTR_NOX_NORMED },
    { "fuel_normed",            SUMO_ATTR_FUEL_NORMED },
    { "electricity_normed",     SUMO_ATTR_ELECTRICITY_NORMED },
    { "CO_perVeh",              SUMO_ATTR_CO_PERVEH },
    { "CO2_perVeh",             SUMO_ATTR_CO2_PERVEH },
    { "HC_perVeh",              SUMO_ATTR_HC_PERVEH },
    { "PMx_perVeh",             SUMO_ATTR_PMX_PERVEH },
    { "NOx_perVeh",             SUMO_ATTR_NOX_PERVEH },
    { "fuel_perVeh",            SUMO_ATTR_FUEL_PERVEH },
    { "electricity_perVeh",     SUMO_ATTR_ELECTRICITY_PERVEH },
    { "noise",                  SUMO_ATTR_NOISE },
    { "amount",                 SUMO_ATTR_AMOUNT },
    { "averageSpeed",           SUMO_ATTR_AVERAGESPEED },
    // FCD
    { "x",                      SUMO_ATTR_X },
    { "y",                      SUMO_ATTR_Y },
    { "z",                      SUMO_ATTR_Z },
    { "angle",                  SUMO_ATTR_ANGLE },
    { "type",                   SUMO_ATTR_TYPE },
    { "pos",                    SUMO_ATTR_POSITION },
    { "edge",                   SUMO_ATTR_EDGE },
    { "lane",                   SUMO_ATTR_LANE },
    { "slope",                  SUMO_ATTR_SLOPE },
    { "signals",                SUMO_ATTR_SIGNALS },
    { "acceleration",           SUMO_ATTR_ACCELERATION },
    { "accelerationLat",        SUMO_ATTR_ACCELERATION_LAT },
    { "distance",               SUMO_ATTR_DISTANCE },
    { "leaderID",               SUMO_ATTR_LEADER_ID },
    { "leaderSpeed",            SUMO_ATTR_LEADER_SPEED },
    { "leaderGap",              SUMO_ATTR_LEADER_GAP },
    { "vehicle",                SUMO_ATTR_VEHICLE },

    // Edge
    { "id",                     SUMO_ATTR_ID },
    { "refId",                  SUMO_ATTR_REFID },
    { "name",                   SUMO_ATTR_NAME },
    { "version",                SUMO_ATTR_VERSION },
    { "priority",               SUMO_ATTR_PRIORITY },
    { "numLanes",               SUMO_ATTR_NUMLANES },
    { "oneway",                 SUMO_ATTR_ONEWAY },
    { "width",                  SUMO_ATTR_WIDTH },
    { "widthResolution",        SUMO_ATTR_WIDTHRESOLUTION },
    { "maxWidth",               SUMO_ATTR_MAXWIDTH },
    { "minWidth",               SUMO_ATTR_MINWIDTH },
    { "sidewalkWidth",          SUMO_ATTR_SIDEWALKWIDTH },
    { "bikeLaneWidth",          SUMO_ATTR_BIKELANEWIDTH },
    { "remove",                 SUMO_ATTR_REMOVE },
    { "length",                 SUMO_ATTR_LENGTH },
    { "bidi",                   SUMO_ATTR_BIDI },
    // Split
    { "idBefore",               SUMO_ATTR_ID_BEFORE },
    { "idAfter",                SUMO_ATTR_ID_AFTER },
    // Positions
    { "center",                 SUMO_ATTR_CENTER },
    { "centerX",                SUMO_ATTR_CENTER_X },
    { "centerY",                SUMO_ATTR_CENTER_Y },
    { "centerZ",                SUMO_ATTR_CENTER_Z },

    { "key",                    SUMO_ATTR_KEY },
    { "requestSize",            SUMO_ATTR_REQUESTSIZE },
    { "request",                SUMO_ATTR_REQUEST },
    { "response",               SUMO_ATTR_RESPONSE },
    { "programID",              SUMO_ATTR_PROGRAMID },
    { "phase",                  SUMO_ATTR_PHASE },
    { "offset",                 SUMO_ATTR_OFFSET },
    { "endOffset",              SUMO_ATTR_ENDOFFSET },
    { "incLanes",               SUMO_ATTR_INCLANES },
    { "intLanes",               SUMO_ATTR_INTLANES },

    { "weight",                 SUMO_ATTR_WEIGHT },
    { "node",                   SUMO_ATTR_NODE },
    { "edges",                  SUMO_ATTR_EDGES },
    // Vehicle
    { "depart",                 SUMO_ATTR_DEPART },
    { "departLane",             SUMO_ATTR_DEPARTLANE },
    { "departPos",              SUMO_ATTR_DEPARTPOS },
    { "departPosLat",           SUMO_ATTR_DEPARTPOS_LAT },
    { "departSpeed",            SUMO_ATTR_DEPARTSPEED },
    { "departEdge",             SUMO_ATTR_DEPARTEDGE },
    { "arrivalLane",            SUMO_ATTR_ARRIVALLANE },
    { "arrivalPos",             SUMO_ATTR_ARRIVALPOS },
    { "arrivalPosLat",          SUMO_ATTR_ARRIVALPOS_LAT },
    { "arrivalSpeed",           SUMO_ATTR_ARRIVALSPEED },
    { "arrivalEdge",            SUMO_ATTR_ARRIVALEDGE },
    { "route",                  SUMO_ATTR_ROUTE },
    { "maxSpeed",               SUMO_ATTR_MAXSPEED },
    { "maxSpeedLat",            SUMO_ATTR_MAXSPEED_LAT },
    { "latAlignment",           SUMO_ATTR_LATALIGNMENT },
    { "minGapLat",              SUMO_ATTR_MINGAP_LAT },
    { "accel",                  SUMO_ATTR_ACCEL },
    { "decel",                  SUMO_ATTR_DECEL },
    { "emergencyDecel",         SUMO_ATTR_EMERGENCYDECEL },
    { "apparentDecel",          SUMO_ATTR_APPARENTDECEL },
    { "actionStepLength",       SUMO_ATTR_ACTIONSTEPLENGTH },
    { "vClass",                 SUMO_ATTR_VCLASS },
    { "vClasses",               SUMO_ATTR_VCLASSES },
    { "exceptions",             SUMO_ATTR_EXCEPTIONS },
    { "repno",                  SUMO_ATTR_REPNUMBER },
    { "speedFactor",            SUMO_ATTR_SPEEDFACTOR },
    { "speedDev",               SUMO_ATTR_SPEEDDEV },
    { "laneChangeModel",        SUMO_ATTR_LANE_CHANGE_MODEL },
    { "carFollowModel",         SUMO_ATTR_CAR_FOLLOW_MODEL },
    { "minGap",                 SUMO_ATTR_MINGAP },
    { "collisionMinGapFactor",  SUMO_ATTR_COLLISION_MINGAP_FACTOR },
    { "boardingDuration",       SUMO_ATTR_BOARDING_DURATION },
    { "loadingDuration",        SUMO_ATTR_LOADING_DURATION },
    { "maneuverAngleTimes",     SUMO_ATTR_MANEUVER_ANGLE_TIMES },
    // MSDevice_ElecHybrid
    { "overheadWireChargingPower",      SUMO_ATTR_OVERHEADWIRECHARGINGPOWER },
    // OverheadWire
    { "overheadWireSegment",    SUMO_ATTR_OVERHEAD_WIRE_SEGMENT },
    { "segments",               SUMO_ATTR_OVERHEAD_WIRE_SECTION },
    { "voltage",                SUMO_ATTR_VOLTAGE },
    { "voltageSource",          SUMO_ATTR_VOLTAGESOURCE },
    { "currentLimit",           SUMO_ATTR_CURRENTLIMIT },
    { "substationId",           SUMO_ATTR_SUBSTATIONID },
    { "wireResistivity",        SUMO_ATTR_OVERHEAD_WIRE_RESISTIVITY },
    { "forbiddenInnerLanes",    SUMO_ATTR_OVERHEAD_WIRE_FORBIDDEN },
    { "clamps",                  SUMO_ATTR_OVERHEAD_WIRE_CLAMPS },
    { "idSegmentStartClamp",    SUMO_ATTR_OVERHEAD_WIRE_CLAMP_START },
    { "idSegmentEndClamp",      SUMO_ATTR_OVERHEAD_WIRE_CLAMP_END },
    // Charging Station
    { "power",                  SUMO_ATTR_CHARGINGPOWER },
    { "efficiency",             SUMO_ATTR_EFFICIENCY },
    { "chargeInTransit",        SUMO_ATTR_CHARGEINTRANSIT },
    { "chargeDelay",            SUMO_ATTR_CHARGEDELAY},
    // MSDevice_Battery
    { "actualBatteryCapacity",          SUMO_ATTR_ACTUALBATTERYCAPACITY },
    { "maximumBatteryCapacity",         SUMO_ATTR_MAXIMUMBATTERYCAPACITY },
    { "maximumPower",                   SUMO_ATTR_MAXIMUMPOWER },
    { "vehicleMass",                    SUMO_ATTR_VEHICLEMASS },
    { "frontSurfaceArea",               SUMO_ATTR_FRONTSURFACEAREA },
    { "airDragCoefficient",             SUMO_ATTR_AIRDRAGCOEFFICIENT },
    { "internalMomentOfInertia",        SUMO_ATTR_INTERNALMOMENTOFINERTIA },
    { "radialDragCoefficient",          SUMO_ATTR_RADIALDRAGCOEFFICIENT },
    { "rollDragCoefficient",            SUMO_ATTR_ROLLDRAGCOEFFICIENT },
    { "constantPowerIntake",            SUMO_ATTR_CONSTANTPOWERINTAKE },
    { "propulsionEfficiency",           SUMO_ATTR_PROPULSIONEFFICIENCY },
    { "recuperationEfficiency",         SUMO_ATTR_RECUPERATIONEFFICIENCY },
    { "recuperationEfficiencyByDecel",  SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION },
    { "stoppingTreshold",               SUMO_ATTR_STOPPINGTRESHOLD },
    // MSElecHybridExport
    { "overheadWireId",         SUMO_ATTR_OVERHEADWIREID },
    { "tractionSubstationId",   SUMO_ATTR_TRACTIONSUBSTATIONID },
    { "current",                SUMO_ATTR_CURRENTFROMOVERHEADWIRE },
    { "circuitVoltage",         SUMO_ATTR_VOLTAGEOFOVERHEADWIRE },
    { "alphaCircuitSolver",     SUMO_ATTR_ALPHACIRCUITSOLVER },
    // MSBatteryExport
    { "energyConsumed",         SUMO_ATTR_ENERGYCONSUMED },
    { "totalEnergyConsumed",    SUMO_ATTR_TOTALENERGYCONSUMED },
    { "totalEnergyRegenerated", SUMO_ATTR_TOTALENERGYREGENERATED },
    { "chargingStationId",      SUMO_ATTR_CHARGINGSTATIONID },
    { "energyCharged",          SUMO_ATTR_ENERGYCHARGED },
    { "energyChargedInTransit", SUMO_ATTR_ENERGYCHARGEDINTRANSIT },
    { "energyChargedStopped",   SUMO_ATTR_ENERGYCHARGEDSTOPPED },
    { "posOnLane",              SUMO_ATTR_POSONLANE },
    { "timeStopped",            SUMO_ATTR_TIMESTOPPED },
    // ChargingStation output
    { "chargingStatus",                 SUMO_ATTR_CHARGING_STATUS },
    { "totalEnergyCharged",             SUMO_ATTR_TOTALENERGYCHARGED },
    { "chargingSteps",                  SUMO_ATTR_CHARGINGSTEPS },
    { "totalEnergyChargedIntoVehicle",  SUMO_ATTR_TOTALENERGYCHARGED_VEHICLE },
    { "chargingBegin",                  SUMO_ATTR_CHARGINGBEGIN },
    { "chargingEnd",                    SUMO_ATTR_CHARGINGEND },
    { "partialCharge",                  SUMO_ATTR_PARTIALCHARGE },

    { "sigma",                  SUMO_ATTR_SIGMA },
    { "tau",                    SUMO_ATTR_TAU },
    { "tmp1",                   SUMO_ATTR_TMP1 },
    { "tmp2",                   SUMO_ATTR_TMP2 },
    { "tmp3",                   SUMO_ATTR_TMP3 },
    { "tmp4",                   SUMO_ATTR_TMP4 },
    { "tmp5",                   SUMO_ATTR_TMP5 },

    { "vehdynamics",            SUMO_ATTR_CF_EIDM_USEVEHDYNAMICS },
    { "tpreview",               SUMO_ATTR_CF_EIDM_T_LOOK_AHEAD },
    { "tPersDrive",             SUMO_ATTR_CF_EIDM_T_PERSISTENCE_DRIVE },
    { "treaction",              SUMO_ATTR_CF_EIDM_T_REACTION },
    { "tPersEstimate",          SUMO_ATTR_CF_EIDM_T_PERSISTENCE_ESTIMATE },
    { "ccoolness",              SUMO_ATTR_CF_EIDM_C_COOLNESS },
    { "sigmaleader",            SUMO_ATTR_CF_EIDM_SIG_LEADER },
    { "sigmagap",               SUMO_ATTR_CF_EIDM_SIG_GAP },
    { "sigmaerror",             SUMO_ATTR_CF_EIDM_SIG_ERROR },
    { "jerkmax",                SUMO_ATTR_CF_EIDM_JERK_MAX },
    { "epsilonacc",             SUMO_ATTR_CF_EIDM_EPSILON_ACC },
    { "taccmax",                SUMO_ATTR_CF_EIDM_T_ACC_MAX },
    { "Mflatness",              SUMO_ATTR_CF_EIDM_M_FLATNESS },
    { "Mbegin",                 SUMO_ATTR_CF_EIDM_M_BEGIN },
    { "maxvehpreview",          SUMO_ATTR_CF_EIDM_MAX_VEH_PREVIEW },

    { "speedControlGain",               SUMO_ATTR_SC_GAIN },
    { "gapClosingControlGainSpeed",     SUMO_ATTR_GCC_GAIN_SPEED },
    { "gapClosingControlGainSpace",     SUMO_ATTR_GCC_GAIN_SPACE },
    { "gapControlGainSpeed",            SUMO_ATTR_GC_GAIN_SPEED },
    { "gapControlGainSpace",            SUMO_ATTR_GC_GAIN_SPACE },
    { "collisionAvoidanceGainSpeed",    SUMO_ATTR_CA_GAIN_SPEED },
    { "collisionAvoidanceGainSpace",    SUMO_ATTR_CA_GAIN_SPACE },

    { "speedControlGainCACC",           SUMO_ATTR_SC_GAIN_CACC },
    { "gapClosingControlGainGap",       SUMO_ATTR_GCC_GAIN_GAP_CACC },
    { "gapClosingControlGainGapDot",    SUMO_ATTR_GCC_GAIN_GAP_DOT_CACC },
    { "gapControlGainGap",              SUMO_ATTR_GC_GAIN_GAP_CACC },
    { "gapControlGainGapDot",           SUMO_ATTR_GC_GAIN_GAP_DOT_CACC },
    { "collisionAvoidanceGainGap",      SUMO_ATTR_CA_GAIN_GAP_CACC },
    { "collisionAvoidanceGainGapDot",   SUMO_ATTR_CA_GAIN_GAP_DOT_CACC },
    { "tauCACCToACC",                   SUMO_ATTR_HEADWAY_TIME_CACC_TO_ACC },
    { "applyDriverState",               SUMO_ATTR_APPLYDRIVERSTATE },

    { "trainType",              SUMO_ATTR_TRAIN_TYPE },

    { "lcStrategic",                SUMO_ATTR_LCA_STRATEGIC_PARAM },
    { "lcCooperative",              SUMO_ATTR_LCA_COOPERATIVE_PARAM },
    { "lcSpeedGain",                SUMO_ATTR_LCA_SPEEDGAIN_PARAM },
    { "lcKeepRight",                SUMO_ATTR_LCA_KEEPRIGHT_PARAM },
    { "lcSublane",                  SUMO_ATTR_LCA_SUBLANE_PARAM },
    { "lcOpposite",                 SUMO_ATTR_LCA_OPPOSITE_PARAM },
    { "lcPushy",                    SUMO_ATTR_LCA_PUSHY },
    { "lcPushyGap",                 SUMO_ATTR_LCA_PUSHYGAP },
    { "lcAssertive",                SUMO_ATTR_LCA_ASSERTIVE },
    { "lcImpatience",               SUMO_ATTR_LCA_IMPATIENCE },
    { "lcTimeToImpatience",         SUMO_ATTR_LCA_TIME_TO_IMPATIENCE },
    { "lcAccelLat",                 SUMO_ATTR_LCA_ACCEL_LAT },
    { "lcTurnAlignmentDistance",    SUMO_ATTR_LCA_TURN_ALIGNMENT_DISTANCE },
    { "lcOvertakeRight",            SUMO_ATTR_LCA_OVERTAKE_RIGHT },
    { "lcLookaheadLeft",            SUMO_ATTR_LCA_LOOKAHEADLEFT },
    { "lcSpeedGainRight",           SUMO_ATTR_LCA_SPEEDGAINRIGHT },
    { "lcSpeedGainLookahead",       SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD },
    { "lcCooperativeRoundabout",    SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT },
    { "lcCooperativeSpeed",         SUMO_ATTR_LCA_COOPERATIVE_SPEED },
    { "lcMaxSpeedLatStanding",      SUMO_ATTR_LCA_MAXSPEEDLATSTANDING },
    { "lcMaxSpeedLatFactor",        SUMO_ATTR_LCA_MAXSPEEDLATFACTOR },
    { "lcMaxDistLatStanding",       SUMO_ATTR_LCA_MAXDISTLATSTANDING },
    { "lcLaneDiscipline",           SUMO_ATTR_LCA_LANE_DISCIPLINE },
    { "lcSigma",                    SUMO_ATTR_LCA_SIGMA },
    { "lcKeepRightAcceptanceTime",  SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME },
    { "lcExperimental1",            SUMO_ATTR_LCA_EXPERIMENTAL1 },

    { "jmCrossingGap",          SUMO_ATTR_JM_CROSSING_GAP },
    { "jmDriveAfterYellowTime", SUMO_ATTR_JM_DRIVE_AFTER_YELLOW_TIME },
    { "jmDriveAfterRedTime",    SUMO_ATTR_JM_DRIVE_AFTER_RED_TIME },
    { "jmDriveRedSpeed",        SUMO_ATTR_JM_DRIVE_RED_SPEED },
    { "jmIgnoreKeepClearTime",  SUMO_ATTR_JM_IGNORE_KEEPCLEAR_TIME },
    { "jmIgnoreFoeSpeed",       SUMO_ATTR_JM_IGNORE_FOE_SPEED },
    { "jmIgnoreFoeProb",        SUMO_ATTR_JM_IGNORE_FOE_PROB },
    { "jmIgnoreJunctionFoeProb", SUMO_ATTR_JM_IGNORE_JUNCTION_FOE_PROB },
    { "jmSigmaMinor",           SUMO_ATTR_JM_SIGMA_MINOR },
    { "jmStoplineGap",          SUMO_ATTR_JM_STOPLINE_GAP },
    { "jmTimegapMinor",         SUMO_ATTR_JM_TIMEGAP_MINOR },
    { "junctionModel.ignoreIDs", SUMO_ATTR_JM_IGNORE_IDS },
    { "junctionModel.ignoreTypes", SUMO_ATTR_JM_IGNORE_TYPES },

    { "last",                   SUMO_ATTR_LAST },
    { "cost",                   SUMO_ATTR_COST },
    { "costs",                  SUMO_ATTR_COSTS },
    { "savings",                SUMO_ATTR_SAVINGS },
    { "exitTimes",              SUMO_ATTR_EXITTIMES },
    { "probability",            SUMO_ATTR_PROB },
    { "count",                  SUMO_ATTR_COUNT },
    { "probabilities",          SUMO_ATTR_PROBS },
    { "routes",                 SUMO_ATTR_ROUTES },
    { "vTypes",                 SUMO_ATTR_VTYPES },

    { "lanes",                  SUMO_ATTR_LANES },
    { "from",                   SUMO_ATTR_FROM },
    { "to",                     SUMO_ATTR_TO },
    { "fromLonLat",             SUMO_ATTR_FROMLONLAT },
    { "toLonLat",               SUMO_ATTR_TOLONLAT },
    { "fromXY",                 SUMO_ATTR_FROMXY },
    { "toXY",                   SUMO_ATTR_TOXY },
    { "fromJunction",           SUMO_ATTR_FROMJUNCTION },
    { "toJunction",             SUMO_ATTR_TOJUNCTION },
    { "period",                 SUMO_ATTR_PERIOD },
    { "repeat",                 SUMO_ATTR_REPEAT },
    { "cycleTime",              SUMO_ATTR_CYCLETIME },
    { "fromTaz",                SUMO_ATTR_FROM_TAZ },
    { "toTaz",                  SUMO_ATTR_TO_TAZ },
    { "reroute",                SUMO_ATTR_REROUTE },
    { "personCapacity",         SUMO_ATTR_PERSON_CAPACITY },
    { "containerCapacity",      SUMO_ATTR_CONTAINER_CAPACITY },
    { "parkingLength",          SUMO_ATTR_PARKING_LENGTH },
    { "personNumber",           SUMO_ATTR_PERSON_NUMBER },
    { "containerNumber",        SUMO_ATTR_CONTAINER_NUMBER },
    { "modes",                  SUMO_ATTR_MODES },
    { "walkFactor",             SUMO_ATTR_WALKFACTOR },

    { "function",               SUMO_ATTR_FUNCTION },
    { "posLat",                 SUMO_ATTR_POSITION_LAT },
    { "freq",                   SUMO_ATTR_FREQUENCY },
    { "style",                  SUMO_ATTR_STYLE },
    { "file",                   SUMO_ATTR_FILE },
    { "junction",               SUMO_ATTR_JUNCTION },
    { "number",                 SUMO_ATTR_NUMBER },
    { "duration",               SUMO_ATTR_DURATION },
    { "until",                  SUMO_ATTR_UNTIL },
    { "arrival",                SUMO_ATTR_ARRIVAL },
    { "extension",              SUMO_ATTR_EXTENSION },
    { "started",                SUMO_ATTR_STARTED },
    { "ended",                  SUMO_ATTR_ENDED },
    { "routeProbe",             SUMO_ATTR_ROUTEPROBE },
    { "crossingEdges",          SUMO_ATTR_CROSSING_EDGES },
    // Traffic light & Nodes
    { "time",                   SUMO_ATTR_TIME },
    { "begin",                  SUMO_ATTR_BEGIN },
    { "end",                    SUMO_ATTR_END },
    { "tl",                     SUMO_ATTR_TLID },
    { "tlType",                 SUMO_ATTR_TLTYPE },
    { "tlLayout",               SUMO_ATTR_TLLAYOUT },
    { "linkIndex",              SUMO_ATTR_TLLINKINDEX },
    { "linkIndex2",             SUMO_ATTR_TLLINKINDEX2 },
    { "shape",                  SUMO_ATTR_SHAPE },
    { "spreadType",             SUMO_ATTR_SPREADTYPE },
    { "radius",                 SUMO_ATTR_RADIUS },
    { "customShape",            SUMO_ATTR_CUSTOMSHAPE },
    { "keepClear",              SUMO_ATTR_KEEP_CLEAR },
    { "indirect",               SUMO_ATTR_INDIRECT },
    { "rightOfWay",             SUMO_ATTR_RIGHT_OF_WAY },
    { "fringe",                 SUMO_ATTR_FRINGE },
    { "color",                  SUMO_ATTR_COLOR },
    { "dir",                    SUMO_ATTR_DIR },
    { "state",                  SUMO_ATTR_STATE },
    { "layer",                  SUMO_ATTR_LAYER },
    { "fill",                   SUMO_ATTR_FILL },
    { "lineWidth",              SUMO_ATTR_LINEWIDTH },
    { "prefix",                 SUMO_ATTR_PREFIX },
    { "discard",                SUMO_ATTR_DISCARD },

    { "fromLane",               SUMO_ATTR_FROM_LANE },
    { "toLane",                 SUMO_ATTR_TO_LANE },
    { "dest",                   SUMO_ATTR_DEST },
    { "source",                 SUMO_ATTR_SOURCE },
    { "via",                    SUMO_ATTR_VIA },
    { "viaLonLat",              SUMO_ATTR_VIALONLAT },
    { "viaXY",                  SUMO_ATTR_VIAXY },
    { "viaJunctions",           SUMO_ATTR_VIAJUNCTIONS },
    { "nodes",                  SUMO_ATTR_NODES },
    { "visibility",             SUMO_ATTR_VISIBILITY_DISTANCE },

    { "minDur",                 SUMO_ATTR_MINDURATION },
    { "maxDur",                 SUMO_ATTR_MAXDURATION },
    { "next",                   SUMO_ATTR_NEXT },
    { "foes",                   SUMO_ATTR_FOES },
    { "constraints",            SUMO_ATTR_CONSTRAINTS },
    // E2 detector
    { "cont",                   SUMO_ATTR_CONT },
    { "contPos",                SUMO_ATTR_CONTPOS },
    { "timeThreshold",          SUMO_ATTR_HALTING_TIME_THRESHOLD },
    { "speedThreshold",         SUMO_ATTR_HALTING_SPEED_THRESHOLD },
    { "jamThreshold",           SUMO_ATTR_JAM_DIST_THRESHOLD },
    { "show",                   SUMO_ATTR_SHOW_DETECTOR },
    // E3 detector
    { "openEntry",              SUMO_ATTR_OPEN_ENTRY },

    { "wautID",                 SUMO_ATTR_WAUT_ID },
    { "junctionID",             SUMO_ATTR_JUNCTION_ID },
    { "procedure",              SUMO_ATTR_PROCEDURE },
    { "synchron",               SUMO_ATTR_SYNCHRON },
    { "refTime",                SUMO_ATTR_REF_TIME },
    { "startProg",              SUMO_ATTR_START_PROG },
    { "off",                    SUMO_ATTR_OFF },
    { "friendlyPos",            SUMO_ATTR_FRIENDLY_POS },
    { "splitByType",            SUMO_ATTR_SPLIT_VTYPE },
    { "uncontrolled",           SUMO_ATTR_UNCONTROLLED },
    { "pass",                   SUMO_ATTR_PASS },
    { "busStop",                SUMO_ATTR_BUS_STOP },
    { "trainStop",              SUMO_ATTR_TRAIN_STOP },
    { "containerStop",          SUMO_ATTR_CONTAINER_STOP },
    { "parkingArea",            SUMO_ATTR_PARKING_AREA },
    { "roadsideCapacity",       SUMO_ATTR_ROADSIDE_CAPACITY },
    { "onRoad",                 SUMO_ATTR_ONROAD },
    { "chargingStation",        SUMO_ATTR_CHARGING_STATION},
    { "group",                  SUMO_ATTR_GROUP},
    { "line",                   SUMO_ATTR_LINE },
    { "lines",                  SUMO_ATTR_LINES },
    { "tripId",                 SUMO_ATTR_TRIP_ID },
    { "split",                  SUMO_ATTR_SPLIT },
    { "join",                   SUMO_ATTR_JOIN },
    { "intended",               SUMO_ATTR_INTENDED },
    { "value",                  SUMO_ATTR_VALUE },
    { "prohibitor",             SUMO_ATTR_PROHIBITOR },
    { "prohibited",             SUMO_ATTR_PROHIBITED },
    { "allow",                  SUMO_ATTR_ALLOW },
    { "disallow",               SUMO_ATTR_DISALLOW },
    { "prefer",                 SUMO_ATTR_PREFER },
    { "changeLeft",             SUMO_ATTR_CHANGE_LEFT },
    { "changeRight",            SUMO_ATTR_CHANGE_RIGHT },
    { "controlledInner",        SUMO_ATTR_CONTROLLED_INNER },
    { "vehsPerHour",            SUMO_ATTR_VEHSPERHOUR },
    { "personsPerHour",         SUMO_ATTR_PERSONSPERHOUR },
    { "containersPerHour",		SUMO_ATTR_CONTAINERSPERHOUR },
    { "perHour",				SUMO_ATTR_PERHOUR },
    { "output",                 SUMO_ATTR_OUTPUT },
    { "height",                 SUMO_ATTR_HEIGHT },
    { "guiShape",               SUMO_ATTR_GUISHAPE },
    { "osgFile",                SUMO_ATTR_OSGFILE },
    { "imgFile",                SUMO_ATTR_IMGFILE },
    { "relativePath",           SUMO_ATTR_RELATIVEPATH },
    { "emissionClass",          SUMO_ATTR_EMISSIONCLASS },
    { "impatience",             SUMO_ATTR_IMPATIENCE },
    { "startPos",               SUMO_ATTR_STARTPOS },
    { "endPos",                 SUMO_ATTR_ENDPOS },
    { "triggered",              SUMO_ATTR_TRIGGERED },
    { "containerTriggered",     SUMO_ATTR_CONTAINER_TRIGGERED },
    { "parking",                SUMO_ATTR_PARKING },
    { "expected",               SUMO_ATTR_EXPECTED },
    { "permitted",              SUMO_ATTR_PERMITTED },
    { "expectedContainers",     SUMO_ATTR_EXPECTED_CONTAINERS },
    { "index",                  SUMO_ATTR_INDEX },

    { "entering",               SUMO_ATTR_ENTERING },
    { "excludeEmpty",           SUMO_ATTR_EXCLUDE_EMPTY },
    { "withInternal",           SUMO_ATTR_WITH_INTERNAL },
    { "trackVehicles",          SUMO_ATTR_TRACK_VEHICLES },
    { "detectPersons",          SUMO_ATTR_DETECT_PERSONS },
    { "maxTraveltime",          SUMO_ATTR_MAX_TRAVELTIME },
    { "minSamples",             SUMO_ATTR_MIN_SAMPLES },
    { "writeAttributes",        SUMO_ATTR_WRITE_ATTRIBUTES },

    { "lon",                    SUMO_ATTR_LON },
    { "lat",                    SUMO_ATTR_LAT },
    { "geo",                    SUMO_ATTR_GEO },
    { "geoShape",               SUMO_ATTR_GEOSHAPE },
    { "k",                      SUMO_ATTR_K },
    { "v",                      SUMO_ATTR_V },
    { "ref",                    SUMO_ATTR_REF },
    { "href",                   SUMO_ATTR_HREF },
    { "zoom",                   SUMO_ATTR_ZOOM },
    { "interpolated",           SUMO_ATTR_INTERPOLATED },
    { "threshold",              SUMO_ATTR_THRESHOLD },

    { "netOffset",              SUMO_ATTR_NET_OFFSET },
    { "convBoundary",           SUMO_ATTR_CONV_BOUNDARY },
    { "origBoundary",           SUMO_ATTR_ORIG_BOUNDARY },
    { "projParameter",          SUMO_ATTR_ORIG_PROJ },

    { "tauLast",                SUMO_ATTR_CF_PWAGNER2009_TAULAST },
    { "apProb",                 SUMO_ATTR_CF_PWAGNER2009_APPROB },
    { "delta",                  SUMO_ATTR_CF_IDM_DELTA },
    { "stepping",               SUMO_ATTR_CF_IDM_STEPPING },
    { "adaptFactor",            SUMO_ATTR_CF_IDMM_ADAPT_FACTOR },
    { "adaptTime",              SUMO_ATTR_CF_IDMM_ADAPT_TIME },
    { "phi",                    SUMO_ATTR_CF_KERNER_PHI },

    { "alpha",                  SUMO_ATTR_GM_Alpha },
    { "M",                      SUMO_ATTR_GM_M },
    { "L",                      SUMO_ATTR_GM_L },

    { "security",               SUMO_ATTR_CF_WIEDEMANN_SECURITY },
    { "estimation",             SUMO_ATTR_CF_WIEDEMANN_ESTIMATION },
    { "cc1",                    SUMO_ATTR_CF_W99_CC1 },
    { "cc2",                    SUMO_ATTR_CF_W99_CC2 },
    { "cc3",                    SUMO_ATTR_CF_W99_CC3 },
    { "cc4",                    SUMO_ATTR_CF_W99_CC4 },
    { "cc5",                    SUMO_ATTR_CF_W99_CC5 },
    { "cc6",                    SUMO_ATTR_CF_W99_CC6 },
    { "cc7",                    SUMO_ATTR_CF_W99_CC7 },
    { "cc8",                    SUMO_ATTR_CF_W99_CC8 },
    { "cc9",                    SUMO_ATTR_CF_W99_CC9 },

    { "ccDecel",                SUMO_ATTR_CF_CC_CCDECEL },
    { "constSpacing",           SUMO_ATTR_CF_CC_CONSTSPACING },
    { "kp",                     SUMO_ATTR_CF_CC_KP },
    { "lambda",                 SUMO_ATTR_CF_CC_LAMBDA },
    { "c1",                     SUMO_ATTR_CF_CC_C1 },
    { "xi",                     SUMO_ATTR_CF_CC_XI },
    { "omegaN",                 SUMO_ATTR_CF_CC_OMEGAN },
    { "tauEngine",              SUMO_ATTR_CF_CC_TAU },
    { "lanesCount",             SUMO_ATTR_CF_CC_LANES_COUNT },
    { "ccAccel",                SUMO_ATTR_CF_CC_CCACCEL },
    { "ploegKp",                SUMO_ATTR_CF_CC_PLOEG_KP },
    { "ploegKd",                SUMO_ATTR_CF_CC_PLOEG_KD },
    { "ploegH",                 SUMO_ATTR_CF_CC_PLOEG_H },
    { "flatbedKa",              SUMO_ATTR_CF_CC_FLATBED_KA },
    { "flatbedKv",              SUMO_ATTR_CF_CC_FLATBED_KV },
    { "flatbedKp",              SUMO_ATTR_CF_CC_FLATBED_KP },
    { "flatbedD",               SUMO_ATTR_CF_CC_FLATBED_D },
    { "flatbedH",               SUMO_ATTR_CF_CC_FLATBED_H },

    { "generateWalks",          SUMO_ATTR_GENERATE_WALKS },
    { "actType",                SUMO_ATTR_ACTTYPE },
    { "junctionCornerDetail",   SUMO_ATTR_CORNERDETAIL },
    { "junctionLinkDetail",     SUMO_ATTR_LINKDETAIL },
    { "rectangularLaneCut",     SUMO_ATTR_RECTANGULAR_LANE_CUT },
    { "walkingareas",           SUMO_ATTR_WALKINGAREAS },
    { "lefthand",               SUMO_ATTR_LEFTHAND },
    { "limitTurnSpeed",         SUMO_ATTR_LIMIT_TURN_SPEED },
    { "checkLaneFoesAll",       SUMO_ATTR_CHECKLANEFOES_ALL },
    { "checkLaneFoesRoundabout", SUMO_ATTR_CHECKLANEFOES_ROUNDABOUT },
    { "tlsIgnoreInternalJunctionJam", SUMO_ATTR_TLS_IGNORE_INTERNAL_JUNCTION_JAM },
    { "avoidOverlap",           SUMO_ATTR_AVOID_OVERLAP },
    { "junctionHigherSpeed",    SUMO_ATTR_HIGHER_SPEED },

    { "actorConfig",            SUMO_ATTR_ACTORCONFIG },
    { "startTime",              SUMO_ATTR_STARTTIME },
    { "vehicleClass",           SUMO_ATTR_VEHICLECLASS },
    { "fuel",                   SUMO_ATTR_FUEL },
    { "origin",                 SUMO_ATTR_ORIGIN },
    { "destination",            SUMO_ATTR_DESTINATION },
    { "visible",                SUMO_ATTR_VISIBLE },
    { "limit",                  SUMO_ATTR_LIMIT },
    { "arrivalTime",            SUMO_ATTR_ARRIVALTIME },
    { "arrivalTimeBraking",     SUMO_ATTR_ARRIVALTIMEBRAKING },
    { "arrivalSpeedBraking",    SUMO_ATTR_ARRIVALSPEEDBRAKING },

#ifndef WIN32
    { "commandPosix",   SUMO_ATTR_COMMAND },
#else
    { "commandWindows", SUMO_ATTR_COMMAND },
#endif

    // ActivityGen statistics file
    { "inhabitants",            AGEN_ATTR_INHABITANTS },
    { "households",             AGEN_ATTR_HOUSEHOLDS },
    { "childrenAgeLimit",       AGEN_ATTR_CHILDREN },
    { "retirementAgeLimit",     AGEN_ATTR_RETIREMENT },
    { "carRate",                AGEN_ATTR_CARS },
    { "unemploymentRate",       AGEN_ATTR_UNEMPLOYEMENT },
    { "laborDemand",            AGEN_ATTR_LABORDEMAND },
    { "footDistanceLimit",      AGEN_ATTR_MAX_FOOT_DIST },
    { "incomingTraffic",        AGEN_ATTR_IN_TRAFFIC },
    { "incoming",               AGEN_ATTR_INCOMING },
    { "outgoingTraffic",        AGEN_ATTR_OUT_TRAFFIC },
    { "outgoing",               AGEN_ATTR_OUTGOING },
    { "population",             AGEN_ATTR_POPULATION },
    { "workPosition",           AGEN_ATTR_OUT_WORKPOSITION },
    { "hour",                   AGEN_ATTR_HOUR },
    { "proportion",             AGEN_ATTR_PROP },
    { "capacity",               AGEN_ATTR_CAPACITY },
    { "opening",                AGEN_ATTR_OPENING },
    { "closing",                AGEN_ATTR_CLOSING },
    { "maxTripDuration",        AGEN_ATTR_MAX_TRIP_DURATION },
    { "rate",                   AGEN_ATTR_RATE },
    { "beginAge",               AGEN_ATTR_BEGINAGE },
    { "endAge",                 AGEN_ATTR_ENDAGE },
    { "peopleNbr",              AGEN_ATTR_PEOPLENBR },
    { "carPreference",          AGEN_ATTR_CARPREF },
    { "meanTimePerKmInCity",    AGEN_ATTR_CITYSPEED },
    { "freeTimeActivityRate",   AGEN_ATTR_FREETIMERATE },
    { "uniformRandomTraffic",   AGEN_ATTR_UNI_RAND_TRAFFIC },
    { "departureVariation",     AGEN_ATTR_DEP_VARIATION },

    // NETEDIT Attributes
    { "selected",                           GNE_ATTR_SELECTED },
    { "modificationStatusNotForPrinting",   GNE_ATTR_MODIFICATION_STATUS },
    { "shapeStart",                         GNE_ATTR_SHAPE_START },
    { "shapeEnd",                           GNE_ATTR_SHAPE_END },
    { "bidiRail",                           GNE_ATTR_BIDIR },
    { "closedShape",                        GNE_ATTR_CLOSE_SHAPE },
    { "parentItem",                         GNE_ATTR_PARENT },
    { "dataSet",                            GNE_ATTR_DATASET },
    { "genericParameter",                   GNE_ATTR_PARAMETERS },
    { "defaultVTypeModified",               GNE_ATTR_DEFAULT_VTYPE_MODIFIED },
    { "centerAfterCreation",                GNE_ATTR_CENTER_AFTER_CREATION },
    { "toBusStop",                          GNE_ATTR_TO_BUSSTOP },
    { "toContainerStop",                    GNE_ATTR_TO_CONTAINERSTOP },
    { "opposite",                           GNE_ATTR_OPPOSITE },
    { "shiftLaneIndex",                     GNE_ATTR_SHIFTLANEINDEX },
    { "stopOffset",                         GNE_ATTR_STOPOFFSET },
    { "stopOException",                     GNE_ATTR_STOPOEXCEPTION },

    { "carriageLength",     SUMO_ATTR_CARRIAGE_LENGTH },
    { "locomotiveLength",   SUMO_ATTR_LOCOMOTIVE_LENGTH },
    { "carriageGap",        SUMO_ATTR_CARRIAGE_GAP },

    { "targetLanes",    SUMO_ATTR_TARGETLANE },
    { "crossing",       SUMO_ATTR_CROSSING },

    { "xmlns:xsi",                      SUMO_ATTR_XMLNS },
    { "xsi:noNamespaceSchemaLocation",  SUMO_ATTR_SCHEMA_LOCATION },

    //@name RNG state saving attributes
    // @{
    { "routeHandler",      SUMO_ATTR_RNG_ROUTEHANDLER },
    { "insertionControl",  SUMO_ATTR_RNG_INSERTIONCONTROL },
    { "device",            SUMO_ATTR_RNG_DEVICE },
    { "device.btreceiver", SUMO_ATTR_RNG_DEVICE_BT },
    { "device.toc",        SUMO_ATTR_RNG_DEVICE_TOC },
    { "driverState",       SUMO_ATTR_RNG_DRIVERSTATE },
    // @}

    //@name meso edge type attributes
    // @{
    { "tauff",             SUMO_ATTR_MESO_TAUFF },
    { "taufj",             SUMO_ATTR_MESO_TAUFJ },
    { "taujf",             SUMO_ATTR_MESO_TAUJF },
    { "taujj",             SUMO_ATTR_MESO_TAUJJ },
    { "junctionControl",   SUMO_ATTR_MESO_JUNCTION_CONTROL },
    { "tlsPenalty",        SUMO_ATTR_MESO_TLS_PENALTY },
    { "tlsFlowPenalty",    SUMO_ATTR_MESO_TLS_FLOW_PENALTY },
    { "minorPenalty",      SUMO_ATTR_MESO_MINOR_PENALTY },
    { "overtaking",        SUMO_ATTR_MESO_OVERTAKING },
    // @}

    // Other
    { "",                       SUMO_ATTR_NOTHING } //< must be the last one
};


const std::string SUMO_PARAM_ORIGID("origId");


StringBijection<SumoXMLNodeType>::Entry SUMOXMLDefinitions::sumoNodeTypeValues[] = {
    {"traffic_light",               SumoXMLNodeType::TRAFFIC_LIGHT},
    {"traffic_light_unregulated",   SumoXMLNodeType::TRAFFIC_LIGHT_NOJUNCTION},
    {"traffic_light_right_on_red",  SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED},
    {"rail_signal",                 SumoXMLNodeType::RAIL_SIGNAL},
    {"rail_crossing",               SumoXMLNodeType::RAIL_CROSSING},
    {"priority",                    SumoXMLNodeType::PRIORITY},
    {"priority_stop",               SumoXMLNodeType::PRIORITY_STOP},
    {"right_before_left",           SumoXMLNodeType::RIGHT_BEFORE_LEFT},
    {"allway_stop",                 SumoXMLNodeType::ALLWAY_STOP},
    {"zipper",                      SumoXMLNodeType::ZIPPER},
    {"district",                    SumoXMLNodeType::DISTRICT},
    {"unregulated",                 SumoXMLNodeType::NOJUNCTION},
    {"internal",                    SumoXMLNodeType::INTERNAL},
    {"dead_end",                    SumoXMLNodeType::DEAD_END},
    {"DEAD_END",                    SumoXMLNodeType::DEAD_END_DEPRECATED},
    {"unknown",                     SumoXMLNodeType::UNKNOWN} //< must be the last one
};


StringBijection<SumoXMLEdgeFunc>::Entry SUMOXMLDefinitions::sumoEdgeFuncValues[] = {
    {"unknown",     SumoXMLEdgeFunc::UNKNOWN},
    {"normal",      SumoXMLEdgeFunc::NORMAL},
    {"connector",   SumoXMLEdgeFunc::CONNECTOR},
    {"crossing",    SumoXMLEdgeFunc::CROSSING},
    {"walkingarea", SumoXMLEdgeFunc::WALKINGAREA},
    {"internal",    SumoXMLEdgeFunc::INTERNAL} //< must be the last one
};


StringBijection<LaneSpreadFunction>::Entry SUMOXMLDefinitions::laneSpreadFunctionValues[] = {
    {"right",      LaneSpreadFunction::RIGHT }, // default: geometry is left edge border, lanes flare to the right
    {"roadCenter", LaneSpreadFunction::ROADCENTER }, // geometry is center of the bidirectional road
    {"center",     LaneSpreadFunction::CENTER } // geometry is center of the edge (must be the last one)
};

StringBijection<RightOfWay>::Entry SUMOXMLDefinitions::rightOfWayValuesInitializer[] = {
    {"edgePriority", RightOfWay::EDGEPRIORITY },
    {"default",      RightOfWay::DEFAULT } // default (must be the last one)
};

StringBijection<FringeType>::Entry SUMOXMLDefinitions::fringeTypeValuesInitializer[] = {
    {"outer",   FringeType::OUTER },
    {"inner",   FringeType::INNER },
    {"default", FringeType::DEFAULT } // default (must be the last one)
};

StringBijection<PersonMode>::Entry SUMOXMLDefinitions::personModeValuesInitializer[] = {
    {"none",         PersonMode::NONE},
    {"walkForward",  PersonMode::WALK_FORWARD},
    {"walkBackward", PersonMode::WALK_BACKWARD},
    {"walk",         PersonMode::WALK},
    {"bicycle",      PersonMode::BICYCLE },
    {"car",          PersonMode::CAR },
    {"taxi",         PersonMode::TAXI },
    {"public",       PersonMode::PUBLIC} // (must be the last one)
};

StringBijection<LinkState>::Entry SUMOXMLDefinitions::linkStateValues[] = {
    { "G", LINKSTATE_TL_GREEN_MAJOR },
    { "g", LINKSTATE_TL_GREEN_MINOR },
    { "r", LINKSTATE_TL_RED },
    { "u", LINKSTATE_TL_REDYELLOW },
    { "Y", LINKSTATE_TL_YELLOW_MAJOR },
    { "y", LINKSTATE_TL_YELLOW_MINOR },
    { "o", LINKSTATE_TL_OFF_BLINKING },
    { "O", LINKSTATE_TL_OFF_NOSIGNAL },
    { "M", LINKSTATE_MAJOR },
    { "m", LINKSTATE_MINOR },
    { "=", LINKSTATE_EQUAL },
    { "s", LINKSTATE_STOP },
    { "w", LINKSTATE_ALLWAY_STOP },
    { "Z", LINKSTATE_ZIPPER },
    { "-", LINKSTATE_DEADEND } //< must be the last one
};

const char SUMOXMLDefinitions::AllowedTLS_linkStatesInitializer[] = {
    LINKSTATE_TL_GREEN_MAJOR,
    LINKSTATE_TL_GREEN_MINOR,
    LINKSTATE_STOP, // used for SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED
    LINKSTATE_TL_RED,
    LINKSTATE_TL_REDYELLOW,
    LINKSTATE_TL_YELLOW_MAJOR,
    LINKSTATE_TL_YELLOW_MINOR,
    LINKSTATE_TL_OFF_BLINKING,
    LINKSTATE_TL_OFF_NOSIGNAL
};
const std::string SUMOXMLDefinitions::ALLOWED_TLS_LINKSTATES(AllowedTLS_linkStatesInitializer, 9);

StringBijection<LinkDirection>::Entry SUMOXMLDefinitions::linkDirectionValues[] = {
    { "s",      LinkDirection::STRAIGHT },
    { "t",      LinkDirection::TURN },
    { "T",      LinkDirection::TURN_LEFTHAND },
    { "l",      LinkDirection::LEFT },
    { "r",      LinkDirection::RIGHT },
    { "L",      LinkDirection::PARTLEFT },
    { "R",      LinkDirection::PARTRIGHT },
    { "invalid", LinkDirection::NODIR } //< must be the last one
};


StringBijection<TrafficLightType>::Entry SUMOXMLDefinitions::trafficLightTypesValues[] = {
    { "static",         TrafficLightType::STATIC },
    { "railSignal",     TrafficLightType::RAIL_SIGNAL },
    { "railCrossing",   TrafficLightType::RAIL_CROSSING },
    { "actuated",       TrafficLightType::ACTUATED },
    { "delay_based",    TrafficLightType::DELAYBASED },
    { "sotl_phase",     TrafficLightType::SOTL_PHASE },
    { "sotl_platoon",   TrafficLightType::SOTL_PLATOON },
    { "sotl_request",   TrafficLightType::SOTL_REQUEST },
    { "sotl_wave",      TrafficLightType::SOTL_WAVE },
    { "sotl_marching",  TrafficLightType::SOTL_MARCHING },
    { "swarm",          TrafficLightType::SWARM_BASED },
    { "deterministic",  TrafficLightType::HILVL_DETERMINISTIC },
    { "off",            TrafficLightType::OFF },
    { "<invalid>",      TrafficLightType::INVALID } //< must be the last one
};


StringBijection<TrafficLightLayout>::Entry SUMOXMLDefinitions::trafficLightLayoutValues[] = {
    { "opposites",       TrafficLightLayout::OPPOSITES },
    { "incoming",        TrafficLightLayout::INCOMING },
    { "alternateOneWay", TrafficLightLayout::ALTERNATE_ONEWAY },
    { "",                TrafficLightLayout::DEFAULT } //< must be the last one
};


StringBijection<LaneChangeModel>::Entry SUMOXMLDefinitions::laneChangeModelValues[] = {
    { "DK2008",     LCM_DK2008 },
    { "LC2013",     LCM_LC2013 },
    { "SL2015",     LCM_SL2015 },
    { "default",    LCM_DEFAULT } //< must be the last one
};

StringBijection<SumoXMLTag>::Entry SUMOXMLDefinitions::carFollowModelValues[] = {
    { "IDM",         SUMO_TAG_CF_IDM },
    { "IDMM",        SUMO_TAG_CF_IDMM },
    { "Krauss",      SUMO_TAG_CF_KRAUSS },
    { "KraussPS",    SUMO_TAG_CF_KRAUSS_PLUS_SLOPE },
    { "KraussOrig1", SUMO_TAG_CF_KRAUSS_ORIG1 },
    { "KraussX",     SUMO_TAG_CF_KRAUSSX }, // experimental extensions to the Krauss model
    { "EIDM",        SUMO_TAG_CF_EIDM },
    { "SmartSK",     SUMO_TAG_CF_SMART_SK },
    { "Daniel1",     SUMO_TAG_CF_DANIEL1 },
    { "PWagner2009", SUMO_TAG_CF_PWAGNER2009 },
    { "BKerner",     SUMO_TAG_CF_BKERNER },
    { "Rail",        SUMO_TAG_CF_RAIL },
    { "CC",          SUMO_TAG_CF_CC },
    { "ACC",         SUMO_TAG_CF_ACC },
    { "CACC",        SUMO_TAG_CF_CACC },
    { "W99",         SUMO_TAG_CF_W99 },
    { "GM",          SUMO_TAG_CF_GM },
    { "Wiedemann",   SUMO_TAG_CF_WIEDEMANN } //< must be the last one
};

StringBijection<LaneChangeAction>::Entry SUMOXMLDefinitions::laneChangeActionValues[] = {
    { "stay",        LCA_STAY },
    { "left",        LCA_LEFT },
    { "right",       LCA_RIGHT },
    { "strategic",   LCA_STRATEGIC },
    { "cooperative", LCA_COOPERATIVE },
    { "speedGain",   LCA_SPEEDGAIN },
    { "keepRight",   LCA_KEEPRIGHT },
    { "sublane",     LCA_SUBLANE },
    { "traci",       LCA_TRACI },
    { "urgent",      LCA_URGENT },
    { "overlapping", LCA_OVERLAPPING },
    { "blocked",     LCA_BLOCKED },
    { "amBL",        LCA_AMBLOCKINGLEADER },
    { "amBF",        LCA_AMBLOCKINGFOLLOWER },
    { "amBB",        LCA_AMBACKBLOCKER },
    { "amBBS",       LCA_AMBACKBLOCKER_STANDING },
    { "MR",          LCA_MRIGHT },
    { "ML",          LCA_MLEFT },

    { "unknown",     LCA_UNKNOWN } //< must be the last one
};

StringBijection<TrainType>::Entry SUMOXMLDefinitions::trainTypeValues[] = {
    { "NGT400",     TRAINTYPE_NGT400 },
    { "NGT400_16",  TRAINTYPE_NGT400_16 },
    { "RB425",      TRAINTYPE_RB425 },
    { "RB628",      TRAINTYPE_RB628 },
    { "ICE1",       TRAINTYPE_ICE1 },
    { "REDosto7",   TRAINTYPE_REDOSTO7 },
    { "Freight",    TRAINTYPE_FREIGHT },
    { "ICE3",       TRAINTYPE_ICE3 }
};


StringBijection<int> SUMOXMLDefinitions::Tags(
    SUMOXMLDefinitions::tags, SUMO_TAG_NOTHING);

StringBijection<int> SUMOXMLDefinitions::Attrs(
    SUMOXMLDefinitions::attrs, SUMO_ATTR_NOTHING);

StringBijection<SumoXMLNodeType> SUMOXMLDefinitions::NodeTypes(
    SUMOXMLDefinitions::sumoNodeTypeValues, SumoXMLNodeType::UNKNOWN);

StringBijection<SumoXMLEdgeFunc> SUMOXMLDefinitions::EdgeFunctions(
    SUMOXMLDefinitions::sumoEdgeFuncValues, SumoXMLEdgeFunc::INTERNAL);

StringBijection<LaneSpreadFunction> SUMOXMLDefinitions::LaneSpreadFunctions(
    SUMOXMLDefinitions::laneSpreadFunctionValues, LaneSpreadFunction::CENTER);

StringBijection<RightOfWay> SUMOXMLDefinitions::RightOfWayValues(
    SUMOXMLDefinitions::rightOfWayValuesInitializer, RightOfWay::DEFAULT);

StringBijection<FringeType> SUMOXMLDefinitions::FringeTypeValues(
    SUMOXMLDefinitions::fringeTypeValuesInitializer, FringeType::DEFAULT);

StringBijection<PersonMode> SUMOXMLDefinitions::PersonModeValues(
    SUMOXMLDefinitions::personModeValuesInitializer, PersonMode::PUBLIC);

StringBijection<LinkState> SUMOXMLDefinitions::LinkStates(
    SUMOXMLDefinitions::linkStateValues, LINKSTATE_DEADEND);

StringBijection<LinkDirection> SUMOXMLDefinitions::LinkDirections(
    SUMOXMLDefinitions::linkDirectionValues, LinkDirection::NODIR);

StringBijection<TrafficLightType> SUMOXMLDefinitions::TrafficLightTypes(
    SUMOXMLDefinitions::trafficLightTypesValues, TrafficLightType::INVALID);

StringBijection<TrafficLightLayout> SUMOXMLDefinitions::TrafficLightLayouts(
    SUMOXMLDefinitions::trafficLightLayoutValues, TrafficLightLayout::DEFAULT);

StringBijection<LaneChangeModel> SUMOXMLDefinitions::LaneChangeModels(
    SUMOXMLDefinitions::laneChangeModelValues, LCM_DEFAULT);

StringBijection<SumoXMLTag> SUMOXMLDefinitions::CarFollowModels(
    SUMOXMLDefinitions::carFollowModelValues, SUMO_TAG_CF_WIEDEMANN);

StringBijection<LaneChangeAction> SUMOXMLDefinitions::LaneChangeActions(
    SUMOXMLDefinitions::laneChangeActionValues, LCA_UNKNOWN);

StringBijection<TrainType> SUMOXMLDefinitions::TrainTypes(
    SUMOXMLDefinitions::trainTypeValues, TRAINTYPE_ICE3);


std::string
SUMOXMLDefinitions::getJunctionIDFromInternalEdge(const std::string internalEdge) {
    assert(internalEdge[0] == ':');
    return internalEdge.substr(1, internalEdge.rfind('_') - 1);
}


std::string
SUMOXMLDefinitions::getEdgeIDFromLane(const std::string laneID) {
    return laneID.substr(0, laneID.rfind('_'));
}

int
SUMOXMLDefinitions::getIndexFromLane(const std::string laneID) {
    return StringUtils::toInt(laneID.substr(laneID.rfind('_') + 1));
}


bool
SUMOXMLDefinitions::isValidNetID(const std::string& value) {
    return (value.size() > 0) && value.find_first_of(" \t\n\r|\\'\";,:!<>&*?") == std::string::npos;
}


bool
SUMOXMLDefinitions::isValidVehicleID(const std::string& value) {
    return (value.size() > 0) && value.find_first_of(" \t\n\r|\\'\";,!<>&*?") == std::string::npos;
}


bool
SUMOXMLDefinitions::isValidTypeID(const std::string& value) {
    return (value.size() > 0) && value.find_first_of(" \t\n\r|\\'\";,<>&*?") == std::string::npos;
}

bool
SUMOXMLDefinitions::isValidAdditionalID(const std::string& value) {
    return (value.size() > 0) && value.find_first_of(" \t\n\r|\\'\";,!<>&*?") == std::string::npos;
}

bool
SUMOXMLDefinitions::isValidDetectorID(const std::string& value) {
    // special case: ' ' allowed
    return (value.size() > 0) && value.find_first_of("\t\n\r|\\'\";,!<>&*?") == std::string::npos;
}

bool
SUMOXMLDefinitions::isValidAttribute(const std::string& value) {
    return value.find_first_of("\t\n\r@$%^&/|\\{}*'\";<>") == std::string::npos;
}


bool
SUMOXMLDefinitions::isValidFilename(const std::string& value) {
    return (value.find_first_of("\t\n\r@$%^&|{}*'\";<>") == std::string::npos);
}


bool
SUMOXMLDefinitions::isValidListOfNetIDs(const std::string& value) {
    const std::vector<std::string>& typeIDs = StringTokenizer(value).getVector();
    if (typeIDs.empty()) {
        return false;
    } else {
        // check that gives IDs are valid
        for (auto i : typeIDs) {
            if (!SUMOXMLDefinitions::isValidNetID(i)) {
                return false;
            }
        }
        return true;
    }
}


bool
SUMOXMLDefinitions::isValidListOfTypeID(const std::string& value) {
    return isValidListOfTypeID(StringTokenizer(value).getVector());
}


bool
SUMOXMLDefinitions::isValidListOfTypeID(const std::vector<std::string>& typeIDs) {
    if (typeIDs.empty()) {
        return false;
    } else {
        // check that gives IDs are valid
        for (const auto& typeID : typeIDs) {
            if (!SUMOXMLDefinitions::isValidTypeID(typeID)) {
                return false;
            }
        }
        return true;
    }
}


bool
SUMOXMLDefinitions::isValidParameterKey(const std::string& value) {
    // Generic parameters keys cannot be empty
    if (value.empty()) {
        return false;
    } else {
        return isValidAttribute(value);
    }
}

/****************************************************************************/

Back to the top