Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/build_config/templates.py
169674 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2015-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file templates.py
15
# @author Pablo Alvarez Lopez
16
# @date Dec 2022
17
18
"""
19
This script rebuilds "src/netedit/templates.h" the files
20
representing the templates.
21
It does this by parsing the data from the sumo data dir.
22
"""
23
24
from __future__ import print_function
25
from __future__ import absolute_import
26
27
import sys
28
import os
29
import re
30
import subprocess
31
import io
32
from os.path import dirname, join
33
from glob import glob
34
35
# list of folders and tools
36
TOOLS = [
37
38
# detector
39
"detector/edgeDataFromFlow.py",
40
"detector/flowFromEdgeData.py",
41
"detector/mapDetectors.py",
42
43
# district
44
"district/filterDistricts.py",
45
"district/gridDistricts.py",
46
"district/stationDistricts.py",
47
48
# drt
49
# "drt/darpSolvers.py", NO CONFIG
50
"drt/drtOrtools.py",
51
# "drt/ortools_pdp.py", NO CONFIG
52
53
# emissions
54
# "emissions/findMinDiffModel.py", NO CONFIG
55
# "emissions/nefz.py", NO CONFIG
56
57
# import
58
"import/citybrain/citybrain_flow.py",
59
"import/citybrain/citybrain_infostep.py",
60
"import/citybrain/citybrain_road.py",
61
"import/dxf/dxf2jupedsim.py",
62
"import/gtfs/gtfs2fcd.py",
63
# "import/gtfs/gtfs2osm.py", NO CONFIG
64
"import/gtfs/gtfs2pt.py",
65
"import/vissim/vissim_parseRoutes.py",
66
"import/visum/visum_convertEdgeTypes.py",
67
68
# net
69
"net/abstractRail.py",
70
"net/createRoundaboutConnections.py",
71
"net/net2geojson.py",
72
"net/net2jpsgeometry.py",
73
"net/net2kml.py",
74
"net/net2poly.py",
75
"net/netcheck.py",
76
"net/netdiff.py",
77
# "net/netduplicate.py", NO CONFIG
78
"net/netmatch.py",
79
"net/network_statistics.py",
80
# "net/odConnectionsCheck.py", NO CONFIG
81
# "net/prepareVISUM.py", NO CONFIG
82
"net/reduceLanes.py",
83
# "net/reprojectpolys.py", NO CONFIG
84
"net/split_at_stops.py",
85
# "net/visum_mapDistricts.py", NO CONFIG
86
# "net/xmlconnections_mapEdges.py", NO CONFIG
87
# "net/xmledges_applyOffset.py", NO CONFIG
88
# "net/xmlnodes_applyOffset.py", NO CONFIG
89
90
# route
91
"route/addStopDelay.py",
92
"route/addStops2Routes.py",
93
"route/addTAZ.py",
94
"route/checkStopOrder.py",
95
"route/implausibleRoutes.py",
96
"route/route2OD.py",
97
"route/route2poly.py",
98
"route/route2sel.py",
99
"route/routecheck.py",
100
"route/routecompare.py",
101
"route/routeStats.py",
102
"route/scaleTimeLine.py",
103
"route/sort_routes.py",
104
"route/splitRandom.py",
105
"route/splitRouteFiles.py",
106
"route/tracegenerator.py",
107
"route/tracemapper.py",
108
# "route/vehicle2flow.py", NO CONFIG
109
110
# output
111
"output/aggregateBatteryOutput.py",
112
"output/analyze_pedestrian_jam.py",
113
"output/analyze_teleports.py",
114
"output/attributeStats.py",
115
"output/attributeDiff.py",
116
"output/attributeCompare.py",
117
"output/computeCoordination.py",
118
"output/computePassengerCounts.py",
119
"output/computeStoppingPlaceUsage.py",
120
"output/countLaneChanges.py",
121
"output/edgeDataDiff.py",
122
# "output/edgeDataStatistics.py", NO CONFIG
123
"output/fcdDiff.py",
124
# "output/generateITetrisIntersectionMetrics.py", NO CONFIG
125
# "output/generateITetrisNetworkMetrics.py", NO CONFIG
126
# "output/generateTLSE1Detectors.py", NO CONFIG
127
"output/generateTLSE2Detectors.py",
128
# "output/generateTLSE3Detectors.py", NO CONFIG
129
# "output/netdumpdiff.py", NO CONFIG
130
# "output/netdumpmean.py", NO CONFIG
131
"output/parkingSearchTraffic.py",
132
"output/scheduleStats.py",
133
# "output/statisticsElements.py", NO CONFIG
134
"output/stopOrder.py",
135
# "output/tables.py", NO CONFIG
136
# "output/timingStats.py", NO CONFIG
137
"output/tripinfoByType.py",
138
# "output/tripStatistics.py", NO CONFIG
139
"output/vehLanes.py",
140
"output/vehrouteCountValidation.py",
141
"output/vehrouteDiff.py",
142
"output/walkFactor.py",
143
144
# shapes
145
"shapes/circlePolygon.py",
146
# "shapes/CSV2polyconvertXML.py", NO CONFIG
147
# "shapes/poi_alongRoads.py", NO CONFIG
148
# "shapes/poi_at_stops.py", NO CONFIG
149
# "shapes/poi_atTLS.py", NO CONFIG
150
151
# tls
152
# "tls/buildTransitions.py", NO CONFIG
153
"tls/createTlsCsv.py",
154
# "tls/tls_check.py", NO CONFIG
155
"tls/tls_csvSignalGroups.py",
156
157
# turn-defs
158
# "turn-defs/collectinghandler.py", NO CONFIG
159
# "turn-defs/connections.py", NO CONFIG
160
# "turn-defs/generateTurnDefs.py", NO CONFIG
161
"turn-defs/generateTurnRatios.py",
162
"turn-defs/turnCount2EdgeCount.py",
163
# "turn-defs/turndefinitions.py", NO CONFIG
164
"turn-defs/turnFile2EdgeRelations.py",
165
166
# visualization
167
# "visualization/mpl_dump_onNet.py", NO CONFIG
168
# "visualization/mpl_dump_timeline.py", NO CONFIG
169
# "visualization/mpl_dump_twoAgainst.py", NO CONFIG
170
# "visualization/mpl_tripinfos_twoAgainst.py", NO CONFIG
171
"visualization/plot_csv_bars.py",
172
"visualization/plot_csv_pie.py",
173
"visualization/plot_csv_timeline.py",
174
"visualization/plot_net_dump.py",
175
"visualization/plot_net_selection.py",
176
"visualization/plot_net_speeds.py",
177
"visualization/plot_net_trafficLights.py",
178
"visualization/plot_summary.py",
179
"visualization/plotXMLAttributes.py",
180
181
# xml
182
# "xml/addSchema.py", IGNORE
183
# "xml/binary2plain.py", NO CONFIG
184
"xml/csv2xml.py",
185
"xml/xml2csv.py",
186
"xml/changeAttribute.py",
187
"xml/filterElements.py",
188
189
# other
190
"countEdgeUsage.py",
191
"createVehTypeDistribution.py",
192
"edgesInDistricts.py",
193
# "extractTest.py", NOT_SUITABLE
194
"fcdReplay.py",
195
"findAllRoutes.py",
196
"generateBidiDistricts.py",
197
"generateContinuousRerouters.py",
198
"generateParkingAreaRerouters.py",
199
"generateParkingAreas.py",
200
"generateRailSignalConstraints.py",
201
"generateRerouters.py",
202
# "osmBuild.py", NOT_SUITABLE
203
"osmGet.py",
204
"plot_trajectories.py",
205
"ptlines2flows.py",
206
"randomTrips.py",
207
"routeSampler.py",
208
"runSeeds.py",
209
"stateReplay.py",
210
"tileGet.py",
211
"tlsCoordinator.py",
212
"tlsCycleAdaptation.py",
213
214
215
"jtcrouter.py",
216
"distributeChargingStations.py",
217
"traceExporter.py",
218
"createScreenshotSequence.py",
219
"averageTripStatistics.py",
220
"generateLandmarks.py",
221
# "osmWebWizard.py", NOT_WORKING
222
"assign/duaIterateMix.py",
223
"assign/duaIterate_analysis.py",
224
"assign/duaIterate_reroutingAnalysis.py",
225
"assign/one-shot.py",
226
# "assign/cadytsIterate.py", NOT_WORKING (on windows to due classpath default)
227
"assign/costFunctionChecker.py",
228
"assign/duaIterate.py",
229
"detector/aggregateFlows.py",
230
"detector/filterFlows.py",
231
"detector/flowFromRoutes.py",
232
"detector/flowrouter.py",
233
"detector/routeUsage.py",
234
"detector/validate.py",
235
"detector/plotFlows.py",
236
"drt/drtOnline.py",
237
"import/matsim/matsim_importPlans.py",
238
"import/osm/osmTaxiStop.py",
239
"import/vissim/convert_detectors2SUMO.py",
240
"import/vissim/convert_vissimXML_flows_statRoutes.py",
241
"import/vissim/tls_vissimXML2SUMOnet_update.py",
242
"import/vissim/vissim2poly.py",
243
"import/vissim/vissim_parseBusStops.py",
244
"import/visum/visum_convertRoutes.py",
245
"import/visum/visum_convertTurnPercentages.py",
246
"import/visum/visum_parseZaehlstelle.py",
247
"import/opendrive/signal_POIs_from_xodr.py",
248
"output/generateMeanDataDefinitions.py",
249
"output/edgeDepartDelay.py",
250
"output/vehroute2amitranOD.py",
251
"output/tripinfoByTAZ.py",
252
"output/tripinfoDiff.py",
253
"route/route_departOffset.py",
254
"route/cutTrips.py",
255
"route/driveways2poly.py",
256
"route/addParkingAreaStops2Trips.py",
257
"route/analyzePersonPlans.py",
258
"route/addParkingAreaStops2Routes.py",
259
"route/cutRoutes.py",
260
"route/route2alts.py",
261
"route/route_1htoDay.py",
262
"route/geoTrip2POI.py",
263
"visualization/macrOutput.py",
264
"visualization/plotWKT.py",
265
"xml/protobuf2xml.py",
266
"xml/xml2protobuf.py",
267
"district/aggregateAndSplitMatrices.py",
268
"district/countConnectionsInDistricts.py",
269
"district/districtMapper.py",
270
"emissions/hbefa2sumo.py",
271
"net/buildFullGraph.py",
272
"net/generateStationEdges.py",
273
"net/patchVClasses.py",
274
"shapes/poly2edgedata.py",
275
"tls/buildTransitions.py",
276
"tls/tls_csv2SUMO.py",
277
"trigger/csv2vss.py",
278
"trigger/meandata2vss.py",
279
]
280
281
282
PATH_MAPPING = {
283
"import/dxf": "import",
284
"import/osm": "import",
285
"import/matsim": "import",
286
"import/opendrive": "import",
287
}
288
289
290
SOURCE_DEPS = [
291
"microsim/MSFrame.cpp", "microsim/devices/*.cpp",
292
"utils/common/RandHelper.cpp", "utils/common/SystemFrame.cpp",
293
"utils/geom/GeoConvHelper.cpp",
294
]
295
296
297
def buildTemplateToolHeader(templateHeaderFile):
298
print(
299
u"#pragma once\n"
300
"#include <string>\n"
301
"#include <vector>\n"
302
"\n"
303
"// @brief template tool\n"
304
"struct TemplateTool {\n"
305
"\n"
306
" // @brief constructor\n"
307
" TemplateTool(const std::string name_, const std::string pythonPath_,\n"
308
" const std::string subfolder_, const std::string templateStr_) :\n"
309
" name(name_),\n"
310
" pythonPath(pythonPath_),\n"
311
" subfolder(subfolder_),\n"
312
" templateStr(templateStr_) {\n"
313
" }\n"
314
"\n"
315
" // @brief tool name\n"
316
" const std::string name;\n"
317
"\n"
318
" // @brief python path\n"
319
" const std::string pythonPath;\n"
320
"\n"
321
" // @brief subfolder path\n"
322
" const std::string subfolder;\n"
323
"\n"
324
" // @brief tool template\n"
325
" const std::string templateStr;\n"
326
"};\n",
327
file=templateHeaderFile)
328
329
330
def formatBinTemplate(templateStr):
331
"""
332
@brief parse binary of a bin template (sumo, netconvert, etc.)
333
"""
334
# remove endlines in Windows
335
templateStr = templateStr.replace("\\r", '')
336
# replace " with \"
337
templateStr = templateStr.replace('"', '\\"')
338
# split lines
339
return templateStr.replace("\n", '"\n "')
340
341
342
def formatToolTemplate(templateStr):
343
"""
344
@brief format python tool template
345
"""
346
if templateStr == '' or templateStr[0] != "<":
347
return '""'
348
# replace all current directory values (src/netedit)
349
templateStr = re.sub("(?<=value)(.*)(?=netedit)", "", templateStr)
350
templateStr = templateStr.replace('netedit', '="')
351
# replace " with \"
352
templateStr = templateStr.replace('"', '\\"')
353
# add quotes and end lines
354
return templateStr.replace("<", '"<').replace("\n", '"\n')
355
356
357
def generateTemplate(app, appBin):
358
"""
359
@brief generate template for the given app
360
"""
361
print("Obtaining " + app + " template")
362
env = dict(os.environ)
363
# the *SAN_OPTIONS are only relevant for the clang build but should not hurt others
364
env["LSAN_OPTIONS"] = "suppressions=%s/../../build_config/clang_memleak_suppressions.txt" % dirname(__file__)
365
env["UBSAN_OPTIONS"] = "suppressions=%s/../../build_config/clang_ubsan_suppressions.txt" % dirname(__file__)
366
# obtain template piping stdout using check_output
367
try:
368
template = formatBinTemplate(subprocess.check_output(
369
[appBin, "--save-template", "stdout"], env=env, universal_newlines=True))
370
except subprocess.CalledProcessError as e:
371
sys.stderr.write("Error when generating template for " + app + ": '%s'" % e)
372
template = ""
373
# join variable and formatted template
374
return u'const std::string %sTemplate = "%s";\n' % (app, template)
375
376
377
def _collectOutput(procs, toolPaths, failed, verbose, testFailure):
378
result = u""
379
for p, toolPath in zip(procs, toolPaths):
380
toolName = os.path.basename(toolPath)[:-3]
381
d = os.path.dirname(toolPath)
382
result += 'TemplateTool("%s", "tools/%s", "%s",\n' % (toolName, toolPath, PATH_MAPPING.get(d, d))
383
stdout, stderr = p.communicate()
384
if p.returncode:
385
failed.append(toolPath if testFailure else toolName)
386
if verbose:
387
print("Cannot generate tool template for %s: '%s'." % (toolName, stderr), file=sys.stderr)
388
result += '""'
389
else:
390
result += formatToolTemplate(stdout)
391
result += '),\n'
392
return result
393
394
395
def generateToolTemplates(toolDir, toolPaths, verbose, testFailure=False):
396
"""
397
@brief generate tool template
398
"""
399
print("Obtaining tool templates.")
400
procs = []
401
result = u""
402
failed = []
403
paths = []
404
env = dict(os.environ)
405
if "SUMO_HOME" not in env:
406
env["SUMO_HOME"] = join(dirname(__file__), '..', '..')
407
for toolPath in toolPaths:
408
toolName = os.path.basename(toolPath)[:-3]
409
if verbose:
410
print("Obtaining '" + toolName + "' tool template.")
411
procs.append(subprocess.Popen([sys.executable, join(toolDir, toolPath), "--save-template", "stdout"], env=env,
412
stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True))
413
paths.append(toolPath)
414
if len(procs) == 32:
415
result += _collectOutput(procs, paths, failed, verbose, testFailure)
416
procs = []
417
paths = []
418
result += _collectOutput(procs, paths, failed, verbose, testFailure)
419
if testFailure:
420
return failed
421
if failed:
422
print("Could not generate tool templates for %s." % (", ".join(failed)), file=sys.stderr)
423
return result
424
425
426
def checkMod(toolDir, reference):
427
mtime = os.path.getmtime(reference)
428
for root, _, files in os.walk(toolDir):
429
for f in files:
430
if f[-3:] == ".py" and os.path.getmtime(join(root, f)) > mtime:
431
return True
432
srcDir = join(dirname(toolDir), 'src')
433
for p in SOURCE_DEPS:
434
for f in glob(join(srcDir, p)):
435
if os.path.getmtime(f) > mtime:
436
return True
437
return False
438
439
440
def main():
441
if len(sys.argv) != 3:
442
sys.exit("Arguments: <pathToSumo> <pathToNetgenerate>")
443
# get tool dir path (SUMO/tools)
444
toolDir = join(dirname(__file__), '..')
445
if not os.path.exists("templates.h") or checkMod(toolDir, "templates.h"):
446
# write templates.h
447
with io.open("templates.h", 'w', encoding='utf8') as templateHeaderFile:
448
buildTemplateToolHeader(templateHeaderFile)
449
is_debug = sys.argv[1].endswith("D") or sys.argv[1].endswith("D.exe")
450
print(u"const std::vector<TemplateTool> templateTools {\n", file=templateHeaderFile)
451
print(generateToolTemplates(toolDir, TOOLS, is_debug), file=templateHeaderFile)
452
print(u"};\n", file=templateHeaderFile)
453
# generate sumo Template
454
print(generateTemplate("sumo", sys.argv[1]), file=templateHeaderFile)
455
# generate netgenerate Template
456
print(generateTemplate("netgenerate", sys.argv[2]), file=templateHeaderFile)
457
458
459
if __name__ == "__main__":
460
main()
461
462