signals_gen.py 4.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/env python3
  2. ''' generates signals xml files for MATSim from OSM data '''
  3. import lxml.etree as etree
  4. INPUT_NETWORK = 'input/network.xml'
  5. INPUT_SIGNALS = 'input/signals.xml'
  6. OUT_SIGNAL_SYSTEMS = 'out_signals_systems.xml'
  7. OUT_SIGNAL_GROUPS = 'out_signals_groups.xml'
  8. OUT_SIGNAL_CONTROL = 'out_signals_control.xml'
  9. CYCLE_TIME = 120
  10. def make_subelement(parent_node, sub_name, sub_attrs=None):
  11. ''' creates an xml sub element and set its attributes '''
  12. sub = etree.SubElement(parent_node, sub_name)
  13. if sub_attrs is None:
  14. return sub
  15. for attr, value in sub_attrs.items():
  16. sub.set(attr, value)
  17. return sub
  18. def make_signal_systems(network_root, signals):
  19. ''' make signal systems xml root '''
  20. signal_systems = etree.Element('signalSystems')
  21. for n_sig, sig in enumerate(signals):
  22. sig_node_id = sig.get('id')
  23. links = network_root.xpath("/network/links/link[@to='{}']".format(sig_node_id))
  24. if links:
  25. signal_system = make_subelement(signal_systems, 'signalSystem', {'id': str(n_sig+1)})
  26. signals = make_subelement(signal_system, 'signals')
  27. for n_link, link in enumerate(links):
  28. make_subelement(signals, 'signal', {'linkIdRef': link.get('id'), 'id': str(n_link+1)})
  29. return signal_systems
  30. def make_signal_groups(signal_systems):
  31. ''' make signal groups xml root '''
  32. signal_groups = etree.Element('signalGroups')
  33. for n_sig_sys, sig_sys in enumerate(signal_systems.xpath('/signalSystems/signalSystem')):
  34. signal_system = make_subelement(signal_groups, 'signalSystem', {'refId': sig_sys.get('id')})
  35. for n_sig, sig in enumerate(sig_sys.xpath('signals/signal')):
  36. signal_group = make_subelement(signal_system, 'signalGroup', {'id': str(n_sig+1)})
  37. make_subelement(signal_group, 'signal', {'refId': sig.get('id')})
  38. return signal_groups
  39. def make_signal_control(signal_systems, signal_groups):
  40. ''' make signal control xml root '''
  41. signal_control = etree.Element('signalControl')
  42. for sig_sys in signal_systems.xpath('/signalSystems/signalSystem'):
  43. sig_sys_id = sig_sys.get('id')
  44. signal_system = make_subelement(signal_control, 'signalSystem', {'refId': sig_sys_id})
  45. sig_sys_controller = make_subelement(signal_system, 'signalSystemController')
  46. controller_identifier = make_subelement(sig_sys_controller, 'controllerIdentifier')
  47. controller_identifier.text = 'DefaultPlanbasedSignalSystemController'
  48. signal_plan = make_subelement(sig_sys_controller, 'signalPlan', {'id': '1'})
  49. make_subelement(signal_plan, 'start', {'daytime': '06:00:00'})
  50. make_subelement(signal_plan, 'stop', {'daytime': '18:00:00'})
  51. make_subelement(signal_plan, 'cycleTime', {'sec': str(CYCLE_TIME)})
  52. make_subelement(signal_plan, 'offset', {'sec': '0'})
  53. sig_groups = signal_groups.xpath("/signalGroups/signalSystem[@refId='{}']/signalGroup".format(sig_sys_id))
  54. for n_sig_grp, sig_grp in enumerate(sig_groups):
  55. sig_group_settings = make_subelement(signal_plan, 'signalGroupSettings', {'refId': sig_grp.get('id')})
  56. delta_sec = int(CYCLE_TIME / len(sig_groups))
  57. onset_sec = delta_sec * n_sig_grp
  58. dropping_sec = onset_sec + delta_sec - 5
  59. make_subelement(sig_group_settings, 'onset', {'sec': str(onset_sec)})
  60. make_subelement(sig_group_settings, 'dropping', {'sec': str(dropping_sec)})
  61. return signal_control
  62. if __name__ == '__main__':
  63. # network nodes
  64. NETWORK_ROOT = etree.parse(INPUT_NETWORK)
  65. # signals nodes
  66. SIGNALS_ROOT = etree.parse(INPUT_SIGNALS)
  67. SIGNALS = SIGNALS_ROOT.xpath('/osm/node')
  68. # xml trees
  69. SIGNAL_SYSTEMS = make_signal_systems(NETWORK_ROOT, SIGNALS)
  70. SIGNAL_GROUPS = make_signal_groups(SIGNAL_SYSTEMS)
  71. SIGNAL_CONTROL = make_signal_control(SIGNAL_SYSTEMS, SIGNAL_GROUPS)
  72. # output
  73. TREE_SIGNAL_SYSTEMS = etree.ElementTree(SIGNAL_SYSTEMS)
  74. TREE_SIGNAL_GROUPS = etree.ElementTree(SIGNAL_GROUPS)
  75. TREE_SIGNAL_CONTROL = etree.ElementTree(SIGNAL_CONTROL)
  76. TREE_SIGNAL_SYSTEMS.write(OUT_SIGNAL_SYSTEMS, pretty_print=True, xml_declaration=True, encoding="utf-8")
  77. TREE_SIGNAL_GROUPS.write(OUT_SIGNAL_GROUPS, pretty_print=True, xml_declaration=True, encoding="utf-8")
  78. TREE_SIGNAL_CONTROL.write(OUT_SIGNAL_CONTROL, pretty_print=True, xml_declaration=True, encoding="utf-8")