sumolib.vehicletype

  1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
  2# Copyright (C) 2008-2026 German Aerospace Center (DLR) and others.
  3# This program and the accompanying materials are made available under the
  4# terms of the Eclipse Public License 2.0 which is available at
  5# https://www.eclipse.org/legal/epl-2.0/
  6# This Source Code may also be made available under the following Secondary
  7# Licenses when the conditions for such availability set forth in the Eclipse
  8# Public License 2.0 are satisfied: GNU General Public License, version 2
  9# or later which is available at
 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 12
 13# @file    vehicletype.py
 14# @author  Mirko Barthauer (Technische Universitaet Braunschweig, Institut fuer Verkehr und Stadtbauwesen)
 15# @author  Jakob Erdmann
 16# @author  Michael Behrisch
 17# @author  Maxwell Schrader
 18# @date    2021-07-19
 19
 20# This file is a port of createVehTypeDistribution.py to sumolib
 21
 22from __future__ import absolute_import
 23from __future__ import print_function
 24import os
 25import json
 26import re
 27import random
 28from typing import Union, Any  # noqa
 29
 30import sumolib
 31
 32
 33class _FixDistribution(object):
 34
 35    def __init__(self, params, isNumeric=True):
 36        if isNumeric:
 37            self._params = tuple([float(p) for p in params])
 38        else:
 39            self._params = params
 40        self._limits = (0, None)
 41        self._isNumeric = isNumeric
 42        self._maxSampleAttempts = 10
 43
 44    def setMaxSamplingAttempts(self, n):
 45        if n is not None:
 46            self._maxSampleAttempts = n
 47
 48    def setLimits(self, limits):
 49        self._limits = limits
 50
 51    def sampleValue(self):
 52        if self._isNumeric:
 53            value = None
 54            nrSampleAttempts = 0
 55            # Sample until value falls into limits
 56            while nrSampleAttempts < self._maxSampleAttempts \
 57                    and (value is None or (self._limits[1] is not None and value > self._limits[1]) or
 58                         (self._limits[0] is not None and value < self._limits[0])):
 59                value = self._sampleValue()
 60                nrSampleAttempts += 1
 61            # Eventually apply fallback cutting value to limits
 62            if self._limits[0] is not None and value < self._limits[0]:
 63                value = self._limits[0]
 64            elif self._limits[1] is not None and value > self._limits[1]:
 65                value = self._limits[1]
 66        else:
 67            value = self._sampleValue()
 68        return value
 69
 70    def sampleValueString(self, decimalPlaces):
 71        if self._isNumeric:
 72            decimalPattern = "%." + str(decimalPlaces) + "f"
 73            return decimalPattern % self.sampleValue()
 74        return self.sampleValue()
 75
 76    def _sampleValue(self):
 77        return self._params[0]
 78
 79
 80class _NormalDistribution(_FixDistribution):
 81
 82    def __init__(self, mu, sd):
 83        _FixDistribution.__init__(self, (mu, sd))
 84
 85    def _sampleValue(self):
 86        return random.normalvariate(self._params[0], self._params[1])
 87
 88
 89class _LogNormalDistribution(_FixDistribution):
 90
 91    def __init__(self, mu, sd):
 92        _FixDistribution.__init__(self, (mu, sd))
 93
 94    def _sampleValue(self):
 95        return random.lognormvariate(self._params[0], self._params[1])
 96
 97
 98class _NormalCappedDistribution(_FixDistribution):
 99
100    def __init__(self, mu, sd, min, max):
101        _FixDistribution.__init__(self, (mu, sd, min, max))
102        if mu < min or mu > max:
103            raise ValueError("mean %s is outside cutoff bounds [%s, %s]" % (mu, min, max))
104
105    def _sampleValue(self):
106        while True:
107            cand = random.normalvariate(self._params[0], self._params[1])
108            if cand >= self._params[2] and cand <= self._params[3]:
109                return cand
110
111
112class _UniformDistribution(_FixDistribution):
113
114    def __init__(self, a, b):
115        _FixDistribution.__init__(self, (a, b))
116
117    def _sampleValue(self):
118        return random.uniform(self._params[0], self._params[1])
119
120
121class _GammaDistribution(_FixDistribution):
122
123    def __init__(self, alpha, beta):
124        _FixDistribution.__init__(self, (alpha, 1.0 / beta))
125
126    def _sampleValue(self):
127        return random.gammavariate(self._params[0], self._params[1])
128
129
130_DIST_DICT = {
131    'normal': _NormalDistribution,
132    'lognormal': _LogNormalDistribution,
133    'normalCapped': _NormalCappedDistribution,
134    'uniform': _UniformDistribution,
135    'gamma': _GammaDistribution
136}
137
138
139class VehAttribute:
140
141    def __init__(self, name, is_param=False, distribution=None, distribution_params=None,
142                 bounds=None, attribute_value=None):
143        # type: (str, bool, str, Union[dict, Any], tuple, str) -> None
144        """
145        This emmulates one line of example config.txt in
146            https://sumo.dlr.de/docs/Tools/Misc.html#createvehtypedistributionpy
147        Either distribution or attribute_value should be populated
148        Args:
149            name (str): the name of the attribute. Examples: "tau", "sigma", "length"
150            is_param (bool, optional): is the attribute a parameter that should be added as a child element.
151            distribution (str, optional): the name of the distribution to use ()
152            distribution_params (Union[dict, Any], optional): the parameters corresponding to the distribution
153            bounds (tuple, optional): the bounds of the distribution.
154            attribute_value (str, optional): if no distribution is given, the fixed value for the attribute
155        """
156        self.is_param = is_param
157        self.name = name
158        self.distribution = distribution
159        self.distribution_params = distribution_params
160        self.bounds = bounds
161        self.attribute_value = attribute_value
162        if self.attribute_value and self.distribution:
163            raise ValueError("Only one of distribution or attribute value should be defined, not both")
164        self.d_obj = self._dist_helper(distribution, distribution_params, bounds)
165
166    def _dist_helper(self, distribution, dist_params, dist_bounds):
167        # type: (...) -> Union[None, _FixDistribution]
168        if distribution:
169            try:
170                d = _DIST_DICT[distribution](**dist_params)
171                d.setLimits(dist_bounds) if dist_bounds else d.setLimits((0, None))
172            except KeyError:
173                raise ValueError("The distribution %s is not known. Please select one of: \n%s " %
174                                 (distribution, "\n".join(_DIST_DICT.keys())))
175        else:
176            isNumeric = False if self.name == "emissionClass" else len(
177                re.findall(r'^(-?[0-9]+(\.[0-9]+)?)$', self.attribute_value)) > 0
178            d = _FixDistribution((self.attribute_value, ), isNumeric)
179        return d
180
181    def add_sampling_attempts(self, attempts):
182        if self.d_obj:
183            self.d_obj.setMaxSamplingAttempts(attempts)
184
185
186class CreateVehTypeDistribution:
187
188    def __init__(self, seed=None, size=100, name='vehDist', resampling=100, decimal_places=3):
189        # type: (int, int, str, int, int) -> None
190        """
191        Creates a VehicleType Distribution.
192        See https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#vehicle_type_distributions
193
194        Args:
195            seed (int, optional): random seed.
196            size (int, optional): number of vTypes in the distribution.
197            name (str, optional): alphanumerical ID used for the created vehicle type distribution.
198            resampling (int, optional): number of attempts to resample a value until it lies in the specified bounds.
199            decimal_places (int, optional): number of decimal places.
200        """
201        if seed:
202            random.seed(seed)
203
204        self.size = size
205        self.name = name
206        self.resampling = resampling
207        self.decimal_places = decimal_places
208        self.attributes = []  # type: list[VehAttribute]
209
210    def add_attribute(self, attribute):
211        # type: (Union[VehAttribute, dict]) -> None
212        """
213        Add an instance of the attribute class to the Parameters. Pass the sampling attempts "global" parameter
214        Args:
215            attribute (VehAttribute or dict): An instance of VehAttribute or
216             a dictionary of parameters to be passed to the VehAttribute constructor
217        """
218        attribute = attribute if isinstance(attribute, VehAttribute) else VehAttribute(**attribute)
219        attribute.add_sampling_attempts(self.resampling)
220        self.attributes.append(attribute)
221
222    def create_veh_dist(self, xml_dom):
223        # type: (sumolib.xml.CompoundObject) -> sumolib.xml.CompoundObject
224        # create the vehicleDist node
225        vtype_dist_node = xml_dom.addChild("vTypeDistribution", {"id": self.name})
226
227        # create the vehicle types
228        for i in range(self.size):
229            veh_type_node = vtype_dist_node.addChild("vType", {"id": self.name + str(i)})
230            for attr in self.attributes:
231                if attr.is_param:
232                    veh_type_node.addChild("param", {"key": attr.name,
233                                                     "value": attr.d_obj.sampleValueString(self.decimal_places)})
234                else:
235                    veh_type_node.setAttribute(attr.name, attr.d_obj.sampleValueString(self.decimal_places))
236
237        return vtype_dist_node
238
239    def to_xml(self, file_path):
240        # type: (str) -> None
241        xml_dom, existing_file = self._check_existing(file_path)
242        if existing_file:
243            self._handle_existing(xml_dom)
244        self.create_veh_dist(xml_dom)
245        with sumolib.openz(file_path, 'w') as f:
246            sumolib.xml.writeHeader(f)
247            f.write(xml_dom.toXML())
248        print("Output written to %s" % file_path)
249
250    def _handle_existing(self, xmlTree):
251        # type: (sumolib.xml.CompoundObject, sumolib.xml.CompoundObject) -> None
252        if xmlTree.vTypeDistribution:
253            for existingDistNode in xmlTree.vTypeDistribution:
254                if existingDistNode.hasAttribute("id") and existingDistNode.id == self.name:
255                    xmlTree.removeChild(existingDistNode)
256                    break
257
258    @staticmethod
259    def _check_existing(file_path):
260        # type: (str) -> tuple[sumolib.xml.CompoundObject, bool]
261        if os.path.exists(file_path):
262            try:
263                xmlTree = list(sumolib.xml.parse(file_path, outputLevel=0))[0]
264                return xmlTree, True
265            except Exception as e:
266                raise ValueError("Cannot parse existing %s. Error: %s" % (file_path, e))
267        else:
268            return sumolib.xml.create_document("additional"), False
269
270    def save_myself(self, file_path):
271        # type: (str) -> None
272        """
273        This function saves the class to a json format. Used for logging simulation inputs
274
275        Args:
276            file_path (str): path to save json to
277        """
278        with sumolib.openz(file_path, "w") as f:
279            f.write(
280                json.dumps(
281                    self,
282                    default=lambda o: {
283                        key: param for key, param in o.__dict__.items() if '_' not in key[0]},
284                    sort_keys=True,
285                    indent=4,
286                )
287            )
288
289
290class CreateMultiVehTypeDistributions(CreateVehTypeDistribution):
291
292    def __init__(self):
293        # type: () -> None
294        self.distributions = []  # type: list[CreateVehTypeDistribution]
295
296    def register_veh_type_distribution(self, veh_type_dist, veh_attributes):
297        # type: (Union[dict, CreateVehTypeDistribution], list[Union[dict, VehAttribute]]) -> None
298        veh_type_dist = veh_type_dist if isinstance(
299            veh_type_dist, CreateVehTypeDistribution) else CreateVehTypeDistribution(**veh_type_dist)
300
301        for attr in veh_attributes:
302            veh_type_dist.add_attribute(attr if isinstance(attr, VehAttribute) else VehAttribute(**attr))
303
304        self.distributions.append(veh_type_dist)
305
306    def write_xml(self, file_path):
307        # type: (str) -> None
308        """
309        This function will overwrite existing files
310
311        Args:
312            file_path (str): Path to the file to write to
313        """
314        xml_dom, _ = self._check_existing(file_path)
315        with sumolib.openz(file_path, 'w') as f:
316            sumolib.xml.writeHeader(f, root="additional")
317            for dist in self.distributions:
318                f.write(dist.create_veh_dist(xml_dom=xml_dom).toXML())
319            print("</additional>", file=f)
class VehAttribute:
140class VehAttribute:
141
142    def __init__(self, name, is_param=False, distribution=None, distribution_params=None,
143                 bounds=None, attribute_value=None):
144        # type: (str, bool, str, Union[dict, Any], tuple, str) -> None
145        """
146        This emmulates one line of example config.txt in
147            https://sumo.dlr.de/docs/Tools/Misc.html#createvehtypedistributionpy
148        Either distribution or attribute_value should be populated
149        Args:
150            name (str): the name of the attribute. Examples: "tau", "sigma", "length"
151            is_param (bool, optional): is the attribute a parameter that should be added as a child element.
152            distribution (str, optional): the name of the distribution to use ()
153            distribution_params (Union[dict, Any], optional): the parameters corresponding to the distribution
154            bounds (tuple, optional): the bounds of the distribution.
155            attribute_value (str, optional): if no distribution is given, the fixed value for the attribute
156        """
157        self.is_param = is_param
158        self.name = name
159        self.distribution = distribution
160        self.distribution_params = distribution_params
161        self.bounds = bounds
162        self.attribute_value = attribute_value
163        if self.attribute_value and self.distribution:
164            raise ValueError("Only one of distribution or attribute value should be defined, not both")
165        self.d_obj = self._dist_helper(distribution, distribution_params, bounds)
166
167    def _dist_helper(self, distribution, dist_params, dist_bounds):
168        # type: (...) -> Union[None, _FixDistribution]
169        if distribution:
170            try:
171                d = _DIST_DICT[distribution](**dist_params)
172                d.setLimits(dist_bounds) if dist_bounds else d.setLimits((0, None))
173            except KeyError:
174                raise ValueError("The distribution %s is not known. Please select one of: \n%s " %
175                                 (distribution, "\n".join(_DIST_DICT.keys())))
176        else:
177            isNumeric = False if self.name == "emissionClass" else len(
178                re.findall(r'^(-?[0-9]+(\.[0-9]+)?)$', self.attribute_value)) > 0
179            d = _FixDistribution((self.attribute_value, ), isNumeric)
180        return d
181
182    def add_sampling_attempts(self, attempts):
183        if self.d_obj:
184            self.d_obj.setMaxSamplingAttempts(attempts)
VehAttribute( name, is_param=False, distribution=None, distribution_params=None, bounds=None, attribute_value=None)
142    def __init__(self, name, is_param=False, distribution=None, distribution_params=None,
143                 bounds=None, attribute_value=None):
144        # type: (str, bool, str, Union[dict, Any], tuple, str) -> None
145        """
146        This emmulates one line of example config.txt in
147            https://sumo.dlr.de/docs/Tools/Misc.html#createvehtypedistributionpy
148        Either distribution or attribute_value should be populated
149        Args:
150            name (str): the name of the attribute. Examples: "tau", "sigma", "length"
151            is_param (bool, optional): is the attribute a parameter that should be added as a child element.
152            distribution (str, optional): the name of the distribution to use ()
153            distribution_params (Union[dict, Any], optional): the parameters corresponding to the distribution
154            bounds (tuple, optional): the bounds of the distribution.
155            attribute_value (str, optional): if no distribution is given, the fixed value for the attribute
156        """
157        self.is_param = is_param
158        self.name = name
159        self.distribution = distribution
160        self.distribution_params = distribution_params
161        self.bounds = bounds
162        self.attribute_value = attribute_value
163        if self.attribute_value and self.distribution:
164            raise ValueError("Only one of distribution or attribute value should be defined, not both")
165        self.d_obj = self._dist_helper(distribution, distribution_params, bounds)

This emmulates one line of example config.txt in https://sumo.dlr.de/docs/Tools/Misc.html#createvehtypedistributionpy Either distribution or attribute_value should be populated Args: name (str): the name of the attribute. Examples: "tau", "sigma", "length" is_param (bool, optional): is the attribute a parameter that should be added as a child element. distribution (str, optional): the name of the distribution to use () distribution_params (Union[dict, Any], optional): the parameters corresponding to the distribution bounds (tuple, optional): the bounds of the distribution. attribute_value (str, optional): if no distribution is given, the fixed value for the attribute

is_param
name
distribution
distribution_params
bounds
attribute_value
d_obj
def add_sampling_attempts(self, attempts):
182    def add_sampling_attempts(self, attempts):
183        if self.d_obj:
184            self.d_obj.setMaxSamplingAttempts(attempts)
class CreateVehTypeDistribution:
187class CreateVehTypeDistribution:
188
189    def __init__(self, seed=None, size=100, name='vehDist', resampling=100, decimal_places=3):
190        # type: (int, int, str, int, int) -> None
191        """
192        Creates a VehicleType Distribution.
193        See https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#vehicle_type_distributions
194
195        Args:
196            seed (int, optional): random seed.
197            size (int, optional): number of vTypes in the distribution.
198            name (str, optional): alphanumerical ID used for the created vehicle type distribution.
199            resampling (int, optional): number of attempts to resample a value until it lies in the specified bounds.
200            decimal_places (int, optional): number of decimal places.
201        """
202        if seed:
203            random.seed(seed)
204
205        self.size = size
206        self.name = name
207        self.resampling = resampling
208        self.decimal_places = decimal_places
209        self.attributes = []  # type: list[VehAttribute]
210
211    def add_attribute(self, attribute):
212        # type: (Union[VehAttribute, dict]) -> None
213        """
214        Add an instance of the attribute class to the Parameters. Pass the sampling attempts "global" parameter
215        Args:
216            attribute (VehAttribute or dict): An instance of VehAttribute or
217             a dictionary of parameters to be passed to the VehAttribute constructor
218        """
219        attribute = attribute if isinstance(attribute, VehAttribute) else VehAttribute(**attribute)
220        attribute.add_sampling_attempts(self.resampling)
221        self.attributes.append(attribute)
222
223    def create_veh_dist(self, xml_dom):
224        # type: (sumolib.xml.CompoundObject) -> sumolib.xml.CompoundObject
225        # create the vehicleDist node
226        vtype_dist_node = xml_dom.addChild("vTypeDistribution", {"id": self.name})
227
228        # create the vehicle types
229        for i in range(self.size):
230            veh_type_node = vtype_dist_node.addChild("vType", {"id": self.name + str(i)})
231            for attr in self.attributes:
232                if attr.is_param:
233                    veh_type_node.addChild("param", {"key": attr.name,
234                                                     "value": attr.d_obj.sampleValueString(self.decimal_places)})
235                else:
236                    veh_type_node.setAttribute(attr.name, attr.d_obj.sampleValueString(self.decimal_places))
237
238        return vtype_dist_node
239
240    def to_xml(self, file_path):
241        # type: (str) -> None
242        xml_dom, existing_file = self._check_existing(file_path)
243        if existing_file:
244            self._handle_existing(xml_dom)
245        self.create_veh_dist(xml_dom)
246        with sumolib.openz(file_path, 'w') as f:
247            sumolib.xml.writeHeader(f)
248            f.write(xml_dom.toXML())
249        print("Output written to %s" % file_path)
250
251    def _handle_existing(self, xmlTree):
252        # type: (sumolib.xml.CompoundObject, sumolib.xml.CompoundObject) -> None
253        if xmlTree.vTypeDistribution:
254            for existingDistNode in xmlTree.vTypeDistribution:
255                if existingDistNode.hasAttribute("id") and existingDistNode.id == self.name:
256                    xmlTree.removeChild(existingDistNode)
257                    break
258
259    @staticmethod
260    def _check_existing(file_path):
261        # type: (str) -> tuple[sumolib.xml.CompoundObject, bool]
262        if os.path.exists(file_path):
263            try:
264                xmlTree = list(sumolib.xml.parse(file_path, outputLevel=0))[0]
265                return xmlTree, True
266            except Exception as e:
267                raise ValueError("Cannot parse existing %s. Error: %s" % (file_path, e))
268        else:
269            return sumolib.xml.create_document("additional"), False
270
271    def save_myself(self, file_path):
272        # type: (str) -> None
273        """
274        This function saves the class to a json format. Used for logging simulation inputs
275
276        Args:
277            file_path (str): path to save json to
278        """
279        with sumolib.openz(file_path, "w") as f:
280            f.write(
281                json.dumps(
282                    self,
283                    default=lambda o: {
284                        key: param for key, param in o.__dict__.items() if '_' not in key[0]},
285                    sort_keys=True,
286                    indent=4,
287                )
288            )
CreateVehTypeDistribution( seed=None, size=100, name='vehDist', resampling=100, decimal_places=3)
189    def __init__(self, seed=None, size=100, name='vehDist', resampling=100, decimal_places=3):
190        # type: (int, int, str, int, int) -> None
191        """
192        Creates a VehicleType Distribution.
193        See https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#vehicle_type_distributions
194
195        Args:
196            seed (int, optional): random seed.
197            size (int, optional): number of vTypes in the distribution.
198            name (str, optional): alphanumerical ID used for the created vehicle type distribution.
199            resampling (int, optional): number of attempts to resample a value until it lies in the specified bounds.
200            decimal_places (int, optional): number of decimal places.
201        """
202        if seed:
203            random.seed(seed)
204
205        self.size = size
206        self.name = name
207        self.resampling = resampling
208        self.decimal_places = decimal_places
209        self.attributes = []  # type: list[VehAttribute]

Creates a VehicleType Distribution. See https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#vehicle_type_distributions

Args: seed (int, optional): random seed. size (int, optional): number of vTypes in the distribution. name (str, optional): alphanumerical ID used for the created vehicle type distribution. resampling (int, optional): number of attempts to resample a value until it lies in the specified bounds. decimal_places (int, optional): number of decimal places.

size
name
resampling
decimal_places
attributes
def add_attribute(self, attribute):
211    def add_attribute(self, attribute):
212        # type: (Union[VehAttribute, dict]) -> None
213        """
214        Add an instance of the attribute class to the Parameters. Pass the sampling attempts "global" parameter
215        Args:
216            attribute (VehAttribute or dict): An instance of VehAttribute or
217             a dictionary of parameters to be passed to the VehAttribute constructor
218        """
219        attribute = attribute if isinstance(attribute, VehAttribute) else VehAttribute(**attribute)
220        attribute.add_sampling_attempts(self.resampling)
221        self.attributes.append(attribute)

Add an instance of the attribute class to the Parameters. Pass the sampling attempts "global" parameter Args: attribute (VehAttribute or dict): An instance of VehAttribute or a dictionary of parameters to be passed to the VehAttribute constructor

def create_veh_dist(self, xml_dom):
223    def create_veh_dist(self, xml_dom):
224        # type: (sumolib.xml.CompoundObject) -> sumolib.xml.CompoundObject
225        # create the vehicleDist node
226        vtype_dist_node = xml_dom.addChild("vTypeDistribution", {"id": self.name})
227
228        # create the vehicle types
229        for i in range(self.size):
230            veh_type_node = vtype_dist_node.addChild("vType", {"id": self.name + str(i)})
231            for attr in self.attributes:
232                if attr.is_param:
233                    veh_type_node.addChild("param", {"key": attr.name,
234                                                     "value": attr.d_obj.sampleValueString(self.decimal_places)})
235                else:
236                    veh_type_node.setAttribute(attr.name, attr.d_obj.sampleValueString(self.decimal_places))
237
238        return vtype_dist_node
def to_xml(self, file_path):
240    def to_xml(self, file_path):
241        # type: (str) -> None
242        xml_dom, existing_file = self._check_existing(file_path)
243        if existing_file:
244            self._handle_existing(xml_dom)
245        self.create_veh_dist(xml_dom)
246        with sumolib.openz(file_path, 'w') as f:
247            sumolib.xml.writeHeader(f)
248            f.write(xml_dom.toXML())
249        print("Output written to %s" % file_path)
def save_myself(self, file_path):
271    def save_myself(self, file_path):
272        # type: (str) -> None
273        """
274        This function saves the class to a json format. Used for logging simulation inputs
275
276        Args:
277            file_path (str): path to save json to
278        """
279        with sumolib.openz(file_path, "w") as f:
280            f.write(
281                json.dumps(
282                    self,
283                    default=lambda o: {
284                        key: param for key, param in o.__dict__.items() if '_' not in key[0]},
285                    sort_keys=True,
286                    indent=4,
287                )
288            )

This function saves the class to a json format. Used for logging simulation inputs

Args: file_path (str): path to save json to

class CreateMultiVehTypeDistributions(CreateVehTypeDistribution):
291class CreateMultiVehTypeDistributions(CreateVehTypeDistribution):
292
293    def __init__(self):
294        # type: () -> None
295        self.distributions = []  # type: list[CreateVehTypeDistribution]
296
297    def register_veh_type_distribution(self, veh_type_dist, veh_attributes):
298        # type: (Union[dict, CreateVehTypeDistribution], list[Union[dict, VehAttribute]]) -> None
299        veh_type_dist = veh_type_dist if isinstance(
300            veh_type_dist, CreateVehTypeDistribution) else CreateVehTypeDistribution(**veh_type_dist)
301
302        for attr in veh_attributes:
303            veh_type_dist.add_attribute(attr if isinstance(attr, VehAttribute) else VehAttribute(**attr))
304
305        self.distributions.append(veh_type_dist)
306
307    def write_xml(self, file_path):
308        # type: (str) -> None
309        """
310        This function will overwrite existing files
311
312        Args:
313            file_path (str): Path to the file to write to
314        """
315        xml_dom, _ = self._check_existing(file_path)
316        with sumolib.openz(file_path, 'w') as f:
317            sumolib.xml.writeHeader(f, root="additional")
318            for dist in self.distributions:
319                f.write(dist.create_veh_dist(xml_dom=xml_dom).toXML())
320            print("</additional>", file=f)
CreateMultiVehTypeDistributions()
293    def __init__(self):
294        # type: () -> None
295        self.distributions = []  # type: list[CreateVehTypeDistribution]

Creates a VehicleType Distribution. See https://sumo.dlr.de/docs/Definition_of_Vehicles,_Vehicle_Types,_and_Routes.html#vehicle_type_distributions

Args: seed (int, optional): random seed. size (int, optional): number of vTypes in the distribution. name (str, optional): alphanumerical ID used for the created vehicle type distribution. resampling (int, optional): number of attempts to resample a value until it lies in the specified bounds. decimal_places (int, optional): number of decimal places.

distributions
def register_veh_type_distribution(self, veh_type_dist, veh_attributes):
297    def register_veh_type_distribution(self, veh_type_dist, veh_attributes):
298        # type: (Union[dict, CreateVehTypeDistribution], list[Union[dict, VehAttribute]]) -> None
299        veh_type_dist = veh_type_dist if isinstance(
300            veh_type_dist, CreateVehTypeDistribution) else CreateVehTypeDistribution(**veh_type_dist)
301
302        for attr in veh_attributes:
303            veh_type_dist.add_attribute(attr if isinstance(attr, VehAttribute) else VehAttribute(**attr))
304
305        self.distributions.append(veh_type_dist)
def write_xml(self, file_path):
307    def write_xml(self, file_path):
308        # type: (str) -> None
309        """
310        This function will overwrite existing files
311
312        Args:
313            file_path (str): Path to the file to write to
314        """
315        xml_dom, _ = self._check_existing(file_path)
316        with sumolib.openz(file_path, 'w') as f:
317            sumolib.xml.writeHeader(f, root="additional")
318            for dist in self.distributions:
319                f.write(dist.create_veh_dist(xml_dom=xml_dom).toXML())
320            print("</additional>", file=f)

This function will overwrite existing files

Args: file_path (str): Path to the file to write to